除非所有查询都只有一个表并且没有有趣的评论业务,否则使用正则表达式是一个失败的提议。反而:
SET SHOWPLAN_ALL ON;
--All your queries here
请参阅设置 showplan_all文档。
当我说正则表达式会变得复杂时,这就是我的意思。这些只是一些考虑因素:
您必须检测带引号的字符串的开头:"
, '
,[
并忽略其中的所有字符,直到正确终止。如果结束字符加倍,则不要终止(即'this is ''fun'', he said'
在 之后不停止is
)。
--
您必须排除不在引号内的单行注释,并在下一个 CRLF 处终止它们。注释中的引号不会像往常一样开始字符串。
您必须排除/*
不在引号内或单行注释内的多行注释(以 开头),然后跳过除终止符 . 之外的所有其他内容*/
。在您的正则表达式中,请务必*
使用反斜杠转义字符\
。
然后,您必须找到具有正确单词边界的有效子句(例如FROM
,列名SelfRom
或没有错误匹配)。AfroMonkey
要正确终止 FROM 子句,您必须在看到任何关键字时停止捕获,包括WHERE
、GROUP BY
、HAVING
、ORDER BY
和WITH
; 并且由于 SQL 查询不需要有分号终止符,;
那么您还必须在SELECT
, DBCC
, SET
, CREATE
,等处终止。ALTER
DROP
但即使是前两点本身也不够,因为如果您的查询如下所示:
SELECT *
FROM
MyTable T
INNER JOIN (
SELECT * FROM YourTable Y WHERE Active = 1
) X ON T.ID = Y.ID
INNER JOIN AnotherTable A
ON X.AID = A.AID
现在,您必须解析括号,并且在看到任何这些关键字时不要停止捕获 FROM 子句。而且你必须跟踪你有多少括号,并一直忽略,直到你有那么多括号。最后,你如何处理这些,因为派生表就像一个表——你想要派生表的全文还是里面的表?
为此,您不能只从FROM
文本中的第一个有效字符开始匹配,因为这可能在引号或注释中。您必须匹配从头开始的所有文本,因为这是使用正则表达式确保您找不到不应该匹配的唯一方法。
这是我想出的只是尝试处理评论的方法。甚至没有引号。它只能找到from子句,而不是里面的内容。另外,我们必须防止括号被捕获,这样在检查我们的捕获组以获取实际的 FROM 子句时,我们不会遇到可怕的混乱。
(?:(?:-(?!-)|/(?!\*)|f(?!rom)|[^-f/])|--[^\n]*\n|/\*(?:\*/)*\*/)*from()
而且它可能充满了错误,一旦我玩了一点,我就不得不重新考虑整个事情,总而言之,这将是巨大的时间浪费。
我认为您低估了要做好这样的事情的难度。但是有一个完全可靠的解决方案!我在上面给出的那个:让 SQL Server 为您解析所有内容。您可以轻松解析返回的计划,因为它的结构很容易。