如何无需手动解析从TSQL的CREATE TABLE脚本提取表属性信息?
无需手动解析的实现方案
你可以直接使用微软官方维护的Microsoft.SqlServer.TransactSql.ScriptDom库完成离线TSQL脚本解析,无需连接数据库,也不需要手动处理语法匹配。
使用步骤
- 第一步:通过NuGet安装
Microsoft.SqlServer.TransactSql.ScriptDom包,适配.NET Framework/.NET Core/.NET 5+全版本 - 第二步:调用解析器解析CREATE TABLE脚本,示例代码如下:
using Microsoft.SqlServer.TransactSql.ScriptDom; using System.Collections.Generic; using System.IO; using System.Linq; public class TableParseResult { public string TableName { get; set; } public List<TableAttribute> Attr { get; set; } = new(); } public class TableAttribute { public string ColumnName { get; set; } public string ColumnType { get; set; } public string Nullable { get; set; } public string Constraint { get; set; } } public static class SqlTableParser { public static TableParseResult ParseCreateTableScript(string sqlScript) { var parser = new TSql160Parser(false); IList<ParseError> errors; var fragment = parser.Parse(new StringReader(sqlScript), out errors); if (errors != null && errors.Count > 0) { throw new InvalidDataException("SQL脚本格式错误"); } var result = new TableParseResult(); var createTableStmt = fragment.Batches .SelectMany(b => b.Statements) .OfType<CreateTableStatement>() .FirstOrDefault(); if (createTableStmt == null) return result; // 提取表名 result.TableName = createTableStmt.SchemaObjectName .Identifiers.LastOrDefault()?.Value ?? string.Empty; // 先提取所有字段定义 var columnDefs = createTableStmt.Definition.ColumnDefinitions .ToDictionary(cd => cd.ColumnIdentifier.Value, cd => new TableAttribute { ColumnName = cd.ColumnIdentifier.Value, ColumnType = cd.DataType.ToSql(), Nullable = cd.IsNullable ? "NULL" : "NOT NULL" }); // 处理约束 foreach (var constraint in createTableStmt.Definition.TableConstraints) { if (constraint is UniqueConstraintDefinition pkConstraint && pkConstraint.IsPrimaryKey) { foreach (var col in pkConstraint.Columns) { var colName = col.Column.MultiPartIdentifier.Identifiers.Last().Value; if (columnDefs.ContainsKey(colName)) { columnDefs[colName].Constraint = "PK"; } } } // 可自行扩展外键、唯一约束等其他类型的解析逻辑 } result.Attr = columnDefs.Values.ToList(); return result; } // 辅助方法把DataType节点转成字符串 private static string ToSql(this DataType dataType) { if (dataType is SqlDataType sqlDataType) { var typeName = sqlDataType.SqlDataTypeOption.ToString(); if (sqlDataType.Parameters.Any()) { return $"{typeName}({string.Join(",", sqlDataType.Parameters.Select(p => p.Value))})"; } return typeName; } return dataType.ToString(); } }
- 第三步:调用方法即可得到你需要的结果,调用示例:
string sql = @"CREATE TABLE [dbo].[person] ( [id] [int] NOT NULL , [Name] [VARCHAR](1) NULL, [fk] [int] NULL, CONSTRAINT [PK_person] PRIMARY KEY CLUSTERED ([id]) )"; var ParseResult = SqlTableParser.ParseCreateTableScript(sql); string tblName = ParseResult.TableName; // 输出person TableAttribute a0 = ParseResult.Attr[0]; // 对应{"id", "int", "NOT NULL", "PK"} TableAttribute a1 = ParseResult.Attr[1]; // 对应{"Name", "VARCHAR(1)", "NULL", null} TableAttribute a2 = ParseResult.Attr[2]; // 对应{"fk", "int", "NULL", null}
扩展说明
你可以根据自己的需求扩展约束解析逻辑,支持外键、唯一键、默认值等所有CREATE TABLE支持的约束类型,不需要修改底层解析逻辑,只需补充对应约束类型的处理分支即可。
内容的提问来源于stack exchange,提问作者KindFrog
相关产品推荐
相关产品推荐

