.NET 中的 SQL Server T-SQL 解析器用于检查语法和对象存在

标签 sql .net parsing sql-server-2012

大家早上好 给我猜这个谜语。试图找到一种方法来解析存储在数据库文本字段中的sql脚本。 这些 SQL 语句用于确定系统健康状况,并在一个月内的特定时间或特定事件之后执行复杂的数据操作。这些语句可以包含任何内容,从简单的 select 语句到包含递归、sp 调用、变量、临时表等的大型 CRUD。

我现在已经拼凑出一个可以满足我需要的解决方案 我可以解析sql的语法有效性,检查。 我可以检查 sql 引用的列是否存在。查看。 我可以向用户报告“设计时”存在的任何错误,即语法上的错误

问题是,如果引用的表不存在,它就不会拾取。在很多情况下,解析器只会在执行 sql 时的“运行时”进行处理。

我提出的解决方案是(这就是我需要社区反馈的地方) 1. 创建.net SQL Connection、事务和命令对象 2. 将 Tx 挂接到连接和命令上 3. 执行命令中的 SQL 并解决出现的错误。 4. 不管怎样总是回滚Tx

免责声明:请不要继续讨论最佳实践,我知道它不是,但需要向 GUI 提供可用的反馈,据我所知,这是实现要求的唯一方法。

我已经使用了 NOEXEC、PARSEONLY 和 Microsoft.SqlServer.TransactSql.ScriptDom,但同样,这仅用于语法而非实际有效性。

我们将非常感谢您的想法和反馈。

谢谢

最佳答案

My question is, what would the possible implications be to execute statements as describes in a transaction and then roll it back

主要问题是并非所有内容都可以回滚。如果脚本使用诸如 xp_cmdshell 之类的东西,那就会很痛苦。但这有点符合地域。

事务的更好替代方案是:FMTONLY。这有点类似,但它不是执行工作然后撤消它,而是简单地短路所有涉及行的内容。这意味着它没有IO成本,没有回滚成本,并且不会导致阻塞。然而,它确实遇到了与 xp_cmdshell 等相同的问题。另外,请注意 MSDN 有警告:

Do not use this feature. This feature has been replaced by sp_describe_first_result_set (Transact-SQL), sp_describe_undeclared_parameters (Transact-SQL), sys.dm_exec_describe_first_result_set (Transact-SQL), and sys.dm_exec_describe_first_result_set_for_object (Transact-SQL).

不幸的是,正如名称所示:这些仅适用于第一个结果集。如果我们从注释中获取您的 [INFORMATION_SCHEMA].[TABLE] 示例,并尝试使用 SQL-Server 的建议选项:

EXEC sp_describe_first_result_set N'
SELECT * FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLE_NAME] = ''MasterCurrencyConversions'';
SELECT * FROM [INFORMATION_SCHEMA].[TABLE] WHERE [TABLE_NAME] = ''MasterCurrencyConversion'';
SELECT * FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLE_NAME] = ''MasterCurrencyConversions'';
';

然后它工作,返回:

is_hidden column_ordinal name            
--------- -------------- ----------------(snipped)
0         1              TABLE_CATALOG   
0         2              TABLE_SCHEMA    
0         3              TABLE_NAME      
0         4              TABLE_TYPE      

etc - 它没有告诉我们第二个 SELECT 中的问题,因为它在第一个 SELECT 处停止了。相反,使用现已弃用的 FMTONLY 选项:

SET FMTONLY ON;
SELECT * FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLE_NAME] = 'MasterCurrencyConversions';
SELECT * FROM [INFORMATION_SCHEMA].[TABLE] WHERE [TABLE_NAME] = 'MasterCurrencyConversion';
SELECT * FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLE_NAME] = 'MasterCurrencyConversions';
SET FMTONLY OFF;

给我们:

TABLE_CATALOG                                          
---------------------------------------------(snipped)

(0 row(s) affected)

Msg 208, Level 16, State 1, Line 3
Invalid object name 'INFORMATION_SCHEMA.TABLE'.

所以我们得到了错误,但我们正在使用官方的“不使用”功能:(

此外,请注意,它不执行 DDL 命令;这意味着其他有效操作可能会失败 - 例如,这里 @Foo 没问题,但 #Bar 失败:

SET FMTONLY ON;
DECLARE @Foo TABLE (id int not null identity(1,1))
SELECT * FROM @Foo
CREATE TABLE #Bar (id int not null identity(1,1))
SELECT * FROM #Bar
SET FMTONLY OFF;

输出:

id
-----------

(0 row(s) affected)

Msg 208, Level 16, State 0, Line 11
Invalid object name '#Bar'.

关于.NET 中的 SQL Server T-SQL 解析器用于检查语法和对象存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25887981/

相关文章:

sql - 如何删除主表中与临时表中的 ID 匹配的行?

sql - 如何将文本值聚合到单个记录中

sql - 在指定记录之后查找以前的记录并加入它们

c# - 建议代码分析,处理不止一次

PHP:找不到语法错误

sql - 通过BigQuery从Google分析中获取访问者的纬度和经度

C# 动态执行函数的名称?

c# - "App.Current.myProperty"不起作用,但 "((app)Application.Current).myProperty"起作用

javascript - JavaScript 语法部分的左因式分解

parsing - PARSE 中 BREAK 和 REJECT 的区别