大家早上好 给我猜这个谜语。试图找到一种方法来解析存储在数据库文本字段中的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/