2015-12-01 33 views
0

我有一个很长的SQL脚本,我想识别SQL列名称的出现并将它们替换为字典中的条目,但是我想保留参数名称。使用负向前瞻(或向后看?)从SQL中提取列名称

列名的格式为schema.TableName.ColumnName,TableName.ColumnNameColumnName。而参数名称的格式总是@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_])* 

(这是从左到右构建的一点小技巧,因此第一个匹配的组是或者是列名(如果是单标签d),表名(如果双重标记)或模式名(如果完全限定),但这不是一个大问题)。

...除了这个正则表达式也选择紧接着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

@a_horse_with_no_name我在SQL以外,在C#/。NET正则表达式事实上这样做。这是一个将处理数据库的schema + sproc转储的程序。 – Dai

回答

1

至于修复你的表情,你缺少一个\ b来表明我们在这个词的开头。

(?<[email protected])\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解析器或编写一个简单的解析器可能会更好,在您遇到它们时替换列名称。