2015-12-01 31 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解析器或編寫一個簡單的解析器可能會更好,在您遇到它們時替換列名稱。