.NET中的SQL Server T-SQL分析器,以检查语法和对象是否存在



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

我现在拼凑出了一个解决方案,可以满足我的需求我可以解析sql的语法有效性,检查一下。如果引用的列存在,我可以检查sql。检查我可以向用户报告"设计时"存在的任何错误,即语法

问题是,如果引用的表不存在,它就不起作用。有很多情况,解析器只有在执行sql时才会在"运行时"发现。

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

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

我已经使用了NOEXEC、PARSEONLY和Microsoft.SqlServer.Transactionsql.ScriptDom,但这只是为了语法而非实际有效性。

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

感谢

我的问题是,执行事务中描述的语句,然后回滚,可能会有什么影响

这里的主要问题是不是所有都可以回滚。如果脚本使用的是xp_cmdshell之类的东西,预计会很痛苦。但这与领土有关。

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

请勿使用此功能。此功能已被sp_describe_first_result_set(Transact-SQL)、sp_describe_undeclared_parameters(Transact-SQL)、sys.dm_exec_descripte_first_result_set(Transact-SQLServer)和sys.dm_Executi_descripte_irst_result_set_for_object(Transact-QL)所取代。

不幸的是,正如名称所示:这些仅适用于第一个结果集。如果我们从注释中选取您的[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中的问题,因为它在第一个停止了。相反,使用现在已弃用的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'.

最新更新