2012-12-20 21 views
3

我需要爲C#構建一個正則表達式,以捕獲select子句中的'from'關鍵字之後的所有表名。例如如何在C#中使用正則表達式獲取所有表名?

. 
. 
. 
SELECT field1, field2 
FROM table1 
WHERE condition1 
. 
. 
. 
SELECT field3, field4 
FROM table2 
WHERE condition2 
. 
. 
. 

裏有文件的多個選擇條款,我嘗試閱讀,並且可以有選擇之間的任何字符(包括新行,「:」,「_」和其他任何字符) 。 我應該如何構建我的正則表達式以獲取所有表名稱?

感謝

編輯: 我已經找到一個辦法讓所有的表名。

\s*SELECT[^;]*FROM\s*(?<key>[^\n]*) 

這可能會在某天幫助某人。 感謝

+0

當我嘗試'SELECT [\ D | \ d] * FROM(? [^ \ n] *)'時,它發現一個匹配以第一個選擇開始並一直延伸到最後一個。我反而希望它匹配所有選擇並返回其所有表名。 – Alpay

+0

給這個網站一試,總是幫我找出RegExes http://regexpal.com/ – Charleh

+0

@Charleh是爲JavaScript正則表達式。對於.NET,你應該使用[RegexHero](http://regexhero.net) –

回答

3

除非所有查詢都只有一張桌子,沒有有趣的業務,評論,使用正則表達式,這是一個虧本生意。相反:

SET SHOWPLAN_ALL ON; 

--All your queries here 

請參閱set showplan_all文檔編號:

當我說正則表達式會變得複雜時,這就是我的意思。這些只是的考慮的一些

  • 你必須檢測被引用字符串的開始:"',並[而忽略所有字符內,直到正常終止。如果結束字符加倍,則不要終止(即,'this is ''fun'', he said'不會在is後停止)。

  • 您必須排除不在引號內的單行註釋--,並在下一個CRLF處終止它們。引用標記內的註釋不會像往常一樣啓動字符串。

  • 你必須排除多行註釋(從/*)不在引號內或單行註釋的內部,然後跳過一切,除了終止,*/。在你的正則表達式中,請務必使用反斜槓\來跳過*字符。

  • 你必須然後找到有效FROM條款與適當的單詞邊界(列名SelfRomAfroMonkey沒有錯誤匹配,例如)。

  • 爲正確端接FROM子句中,你有當你看到包括任何關鍵字停止捕獲WHEREGROUP BYHAVINGORDER BYWITH;既然有分號終止; SQL查詢不需要那麼你也將不得不終止在SELECTDBCCSETCREATEALTERDROP等等等等。

  • 但即使前面兩點是不夠真正的自己,因爲如果您的查詢是什麼樣子的:

    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子句時,我們沒有太大的混亂。

(?:(?:-(?!-)|/(?!\*)|f(?!rom)|[^-f/])|--[^\n]*\n|/\*(?:\*/)*\*/)*from() 

而且它可能有錯誤的盛行,我不得不重新考慮整個事情一旦我用它玩了一下,所有的一切,這將是一次一個巨大的浪費。

我認爲你低估了這樣的事情會很難完成。但是有一個非常可靠的解決方案!我上面給出的一個:讓SQL Server爲你解析所有的東西。您可以輕鬆解析返回的計劃,因爲它的結構方式使其變得簡單。

1

首先我想說看看這個教程:http://www.codeproject.com/Articles/9099/The-30-Minute-Regex-Tutorial

退房這樣的正則表達式:((?<=FROM)[^\s]+)

此正則表達式將開始"FROM "(包括空格)後,直接讀取並停止在讀第一空白(^\s)

,如果你嘗試這樣

foreach (Match m in Regex.Matches(input, @"((?<=FROM)[^\s]+)") 
{ 
    string output = m.Value; 
} 

編輯:

我不是100%確定這個正則表達式。如果你的名字末尾有一個換行符,這個woudl可能會更好地完成這項工作:@"((?<=FROM)[^\n]+))但是你應該修剪輸出,因爲輸出字符串的開始處可能有一個空格。

+0

FORM!==從我親愛的chap – ErikE

+0

@ErikE對不起,誤讀了..變了! – 2pietjuh2

0
var input = "select name from Table1 where id =2"; 
var pattern = @"from\s*(.*?)\s*where"; // where car= is the first delimiter and ; is the second one 
var result = Regex.Match(input, pattern).Groups[1].Value; 
MessageBox.Show(result); 
+0

那麼說「來自」的評論呢?災害。 – ErikE

+0

多個查詢一起將不會被正確處理 - 結果將跨越所有這些查詢。 – ErikE

相關問題