我有一個很長的SQL腳本,我想識別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_])*
(這是從左到右構建的一點小技巧,因此第一個匹配的組是或者是列名(如果是單標籤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斷言。我已經嘗試將斷言放在父組之內和之外,並且嘗試了負向超前斷言,但沒有任何效果。
@a_horse_with_no_name我在SQL以外,在C#/。NET正則表達式事實上這樣做。這是一個將處理數據庫的schema + sproc轉儲的程序。 – Dai