问题描述
我的用例是接受 Azure Synapse DW DDL 作为输入,解析它并从中提取 sql 语句。此外,我不仅可以从基本语句(即、DECLARE、CREATE、ALTER、SELECT 等)中受益,还可以从其他 DDL 构造中受益,例如 PK 约束、索引、分布、分区等。
伸出手来了解是否有已知的方法来实现这一目标?非常感谢。
我尝试过的事情:
-
TsqlParser(所有 8 个可用版本 80,90,100,110,120,130,140,150)但它无法解析 DDL 并在几个特定于 DW 的令牌上出错。
-
将自定义 TSqlConcreteFragmentVisitor 传递给 TsqlFragment 但它也没有检测到 Create table 语句(尽管它可以访问 SELECT 语句,此处未显示在附加的 DDL 中)
-
使用 Microsoft.SqlServer.Management.SqlParser.Parser.Scanner 从 DDL 读取 sql 批处理,但它将整个 DDL 标识为单个批处理。这没有帮助,因为我基本上得到了与我传入的输入相同的输出。
-
使用 TSQL.TsqlStatementReader 对 DDL 进行标记,但它提供单个标记而不是 sql 语句(例如,在此处的 fiddle 中,PK 约束 NOT ENFORCED 被标记为 2 个标记而不是应有的单一约束。
请注意,如果我手动删除 DW 特定构造,如 PK 约束 NOT ENFORCED
和 WITH (...)
块,那么 TsqlParser 会成功解析 DDL 并正确地带出包含表、列和数据类型的 Create 语句。
示例 DDL:
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = N'tempschema_main')
EXEC('CREATE SCHEMA [schema_main]')
CREATE TABLE [schema_main].[temp_table]
(
[TempId1] NVARCHAR(128) NOT NULL,[TempId2] NVARCHAR(128) NOT NULL,CONSTRAINT PK_TempPkColumnId PRIMARY KEY NONCLUSTERED (TempId1,TempId2) NOT ENFORCED
)
WITH
(
CLUSTERED COLUMNSTORE INDEX,disTRIBUTION = ROUND_ROBIN
)
解决方法
正如您可能发现的那样,SQL 解析并不简单 - 考虑到编写相同语句的不同方式的数量、语句中可用的选项数以及语句的级别数一条语句(即 selects within selects within selects),加上所有非标准但特定于特定 DBMS 的语法。
您可能拥有的选项如下:
- 您很幸运,您可以使用的功能满足您的需求。根据您在问题中的陈述,情况并非如此,因为您尝试过的事情不起作用
- 如果您要处理的所有 DDL 的结构都相同,那么编写自己的解析器(javascript、VBA 等)可能会更容易,该解析器仅使用您拥有的数据即可完成您想要的操作立>
- 使用商业 SQL 解析器。我所知道的唯一一个真正有效的是SQLParser。如果您遇到任何不能用他们的工具正确解析的语法,那么他们会很快修复它。有一个免费版本,但(我认为)仅限于 SQL 语句中的几千个字符,因此您可能需要为此付费