我有一个很长的SQL脚本,我想识别SQL列名的出现,并用字典中的条目替换它们,但是我想保留参数名。
列名称的格式为schema.TableName.ColumnName
,TableName.ColumnName
或ColumnName
。参数名称的格式始终为@parameterName
。
所以给出了这个脚本(人为的例子):
DECLARE @foo varchar(max) = '123'
DECLARE @bar varchar(max) = '456'
SELECT foo, table.bar, @bar FROM table ORDER BY table.foo DESC
我想要匹配:
foo
table.bar
table
table.foo
我首先写了一个简单的正则表达式来匹配列名:
([A-Za-z_]+[0-9A-Za-z_]*)(\.[A-Za-z_]+[0-9A-Za-z_])*(\.[A-Za-z_]+[0-9A-Za-z_])*
(这是一个从左到右构建的黑客,所以第一个匹配的组是列名(如果是单标记的),表名(如果是双重标记的),或者模式名称(如果是完全限定的),但这不是一个大问题。)
...除了这个正则表达式之外还在at符号后面立即选择参数部分。所以我需要修改它,使其与参数不匹配。我添加了一个负面后瞻断言(?<!\@)
以匹配前导@
前缀,然后取消匹配,但它不起作用:
((?<!\@)([A-Za-z_]+[0-9A-Za-z_]*)(\.[A-Za-z_]+[0-9A-Za-z_])*(\.[A-Za-z_]+[0-9A-Za-z_])*
尽管存在负面观察断言,但鉴于输入“@foobar
”,它匹配/捕获“@f[oobar]
”而不是拒绝捕获它。
显然我没有正确使用lookbehind断言。我已经尝试将断言置于父组内外,并尝试使用否定前瞻断言,但没有效果。
答案 0 :(得分:1)
至于修复你的表达方式,你错过了一个\ b来表明我们在这个单词的开头。
(?<!@)\b([A-Za-z_]+\w*)(\.[A-Za-z_]+\w*)*\b
那将匹配
'SELECT', 'foo', 'table.bar', 'FROM', 'table', 'ORDER', 'BY', 'table.foo', 'DESC'
来自声明
SELECT foo, table.bar, @bar FROM table ORDER BY table.foo DESC
我觉得单凭正则表达式可能不是最佳解决方案 最好尝试找一个sql解析器或编写一个简单的解析器,在遇到列名时替换它们。