2008-11-11 77 views
6

我對正則表達式並不那麼熱心,它讓我的小心思融化了一些東西。在查詢中查找所有表名的正則表達式

我正試圖在查詢中查找所有表名。所以說我有查詢:

SELECT one, two, three FROM table1, table2 WHERE X=Y 

我想拉出來「表1,表2」或「表1」和「表2」

但是如果沒有where語句。它可能是文件的結尾,也可能是一個小組或一個命令等。我知道「最」的時間,這不會是一個問題,但我不喜歡編碼爲「最」的想法,並且知道我留下了一個可能導致事情晚點出錯的漏洞。

這是一個可行的正則表達式嗎?我是否是一個正則表達式?

(P.S.這將在C#中完成,但假定沒有多大關係)。

+0

正則表達式是個至少是你的問題。只要列舉一個表可以出現在SQL語句中的所有方式是一個複雜的問題。 BTW。你從來沒有提到你試圖分析哪種SQL。 – JohnFx 2010-02-12 16:58:20

+0

他想要解決的根本問題是什麼。 – 2010-02-12 17:10:52

回答

13

正則表達式是不是在這個非常好,因爲它是一個複雜得多比它出現:

  • 如果他們使用左/右內/外/ CROSS /合併/ NATURAL連接,而不是一個,b語法?無論如何應該避免使用a,b語法。
  • 嵌套查詢呢?
  • 如果沒有表格(選擇一個常數)會怎麼樣
  • 怎麼樣換行符和其他空白格式?
  • 別名?

我可以繼續。

你可以做的是尋找一個SQL解析器,並通過它來運行你的查詢。

1

這絕對不容易。

考慮子查詢。

select 
    * 
from 
    A 
    join (
    select 
     top 5 * 
    from 
     B) 
    on B.ID = A.ID 
where 
    A.ID in (
    select 
     ID 
    from 
     C 
    where C.DOB = A.DOB) 

在此查詢中使用了三個表。

1

我認爲將字符串標記並查找可能綁定表名的SQL關鍵字會更容易。您知道這些名稱將遵循FROM,但是如果它們在查詢的末尾,則可能會跟着WHERE,GROUP BY,HAVING或完全沒有關鍵字。

4

所有關於這種正則表達式在SQL上下文中的用處的說法。如果你堅持一個正則表達式和SQL語句看起來總是像一個你表明(這意味着沒有子查詢,連接,等等),你可以使用

​​
3

我對派對的時間很晚,但是我想我會分享一個正在使用的正則表達式來分析我們所有的數據庫對象,並且我不同意使用這種方法無法做到這一點的情緒。

正則表達式有您沒有使用A幾個假設

1),B加入無論正則表達式解析器使用的是支持忽略大小寫語法風格

2)。

3)您正在分析,選擇,加入,更新,刪除和截斷。它不支持前面提到的MERGE/NATURAL,因爲我們不使用它們,但是我相信進一步的支持並不難添加。

我很想知道該表是什麼類型的交易,所以我已經包括命名捕獲組來告訴我。

現在我還沒有使用正則表達式很長一段時間,所以可能有改進,但迄今爲止在我所有的測試中都是準確的。

\bjoin\s+(?<Retrieve>[a-zA-Z\._\d]+)\b|\bfrom\s+(?<Retrieve>[a-zA-Z\._\d]+)\b|\bupdate\s+(?<Update>[a-zA-Z\._\d]+)\b|\binsert\s+(?:\binto\b)?\s+(?<Insert>[a-zA-Z\._\d]+)\b|\btruncate\s+table\s+(?<Delete>[a-zA-Z\._\d]+)\b|\bdelete\s+(?:\bfrom\b)?\s+(?<Delete>[a-zA-Z\._\d]+)\b 
0

構建一個正則表達式是你的問題中最少的。根據您期望通過此代碼支持的SQL的風格,您可以在SQL語句中引用表的方式的數量是驚人的。

PLUS,如果查詢包含對視圖或UDF的引用,那麼關於哪些基礎表甚至不在字符串中的信息根本無法通過解析來獲取該信息。此外,你需要聰明地檢測臨時表並將它們排除在結果之外。

如果您必須這樣做,更好的方法是將API用於SQL所針對的特定數據庫引擎。例如,您可以基於查詢創建視圖,然後使用數據庫服務器API檢測該視圖的依賴關係。數據庫引擎將能夠比以往任何時候都更可靠地解析它,而無需大量的工作來對查詢引擎進行反向工程。

如果偶然,你使用SQL Server的工作,這裏是關於該平臺上檢測依賴性的文章:Finding Dependencies in SQL Server 2005

0

這將拿出一個表名上的INSERT INTO查詢:

(?<=(INTO)\s)[^\s]*(?=\(()) 

以下將做相同的,但有選擇,包括加入

(?<=(from|join)\s)[^\s]*(?=\s(on|join|where)) 

最後回到插入,如果你想返回只是在插入查詢保存的值使用下面的正則表達式

(?i)(?<=VALUES[ ]*\().*(?=\)) 

我知道這是一個古老的線程,但它可以幫助別人看着周圍

享受

0

我嘗試了上述所有但是因爲我使用了各種各樣的查詢,所以都沒有工作。我正在使用PHP,並使用稱爲SQL_Parser的PEAR庫,但希望我的解決方案能夠提供幫助。另外,我在使用撇號和MySQL保留的sencence時遇到了問題,所以我決定在解析之前從查詢中去掉所有的字段部分。

function getQueryTable ($query) { 
    require_once "SQL/Parser.php"; 
    $parser = new SQL_Parser(); 
    $parser->setDialect('MySQL'); 

    // Stripping fields section 
    $queryType = substr(strtoupper($query),0,6);    
    if($queryType == 'SELECT') { $query = "SELECT * ".stristr($query, "FROM"); } 
    if ($havingPos = stripos($query, 'HAVING')) { $query = substr($query, 0, $havingPos); } 


    $struct = $parser->parse($query); 

    $tableReferences = $struct[0]['from']['table_references']['table_factors']; 

    foreach ((Array) $tableReferences as $ref) { 
     $tables[] = ($ref['database'] ? $ref['database'].'.' : $ref['database']).$ref['table']; 
    } 

    return $tables; 

} 
0

在PHP中,我用這個函數,它返回與在SQL語句中使用的表名的數組:

function sql_query_get_tables($statement){ 
    preg_match_all("/(from|into|update|join) [\\'\\´]?([a-zA-Z0-9_-]+)[\\'\\´]?/i", 
      $statement, $matches); 
    if(!empty($matches)){ 
     return array_unique($matches[2]); 
    }else return array(); 
} 

注意,它不與工作,二連接或架構。表名命名

我希望它爲你工作

1

一個解決辦法是落實表和視圖的命名約定。然後可以在命名前綴上解析SQL語句。

例如:

SELECT tbltable1.one, tbltable1.two, tbltable2.three FROM tbltable1 INNER JOIN tbltable2 ON tbltable1.one = tbltable2.three

分割空白來數組:

("SELECT","tbltable1.one,","tbltable1.two,","tbltable2.three","FROM","tbltable1","INNER","JOIN","tbltable2","ON","tbltable1.one","=","tbltable2.three")

獲取左元素與週期:

("SELECT","tbltable1","tbltable1","tbltable2","FROM","tbltable1","INNER","JOIN","tbltable2","ON","tbltable1","=","tbltable2")

種刪除元素的符號:

("SELECT","tbltable1","tbltable1","tbltable2","FROM","tbltable1","INNER","JOIN","tbltable2","ON","tbltable1","tbltable2")

減少到唯一值:

("SELECT","tbltable1","tbltable2","FROM","INNER","JOIN","ON")

過濾器上左3個字符= 「TBL」

("tbltable1","tbltable2")

0

我用這個代碼作爲Excel宏來解析選擇和提取tabl e名稱。

我的分析假設sintax未使用「從A,B,C中選擇」。

只要運行它針對你的SQL查詢,如果你不與結果sadisfied你應該只有幾行代碼從結果遠的你期望的那樣。只是調試,並相應地修改代碼。

子get_tables()

sql_query = Cells(5, 1).Value 

tables = "" 

'get all tables after from 

sql_from = sql_query 

While InStr(1, UCase(sql_from), UCase("from")) > 0 

    i = InStr(1, UCase(sql_from), UCase("from")) 

    sql_from = Mid(sql_from, i + 5, Len(sql_from) - i - 5) 

    i = InStr(1, UCase(sql_from), UCase(" ")) 

    While i = 1 

     sql_from = Mid(sql_from, 2, Len(sql_from) - 1) 

     i = InStr(1, UCase(sql_from), UCase(" ")) 

    Wend 

    i = InStr(1, sql_join, Chr(9)) 

    While i = 1 

     sql_join = Mid(sql_join, 2, Len(sql_join) - 1) 

     i = InStr(1, sql_join, Chr(9)) 

    Wend 

    a = InStr(1, UCase(sql_from), UCase(" ")) 

    b = InStr(1, sql_from, Chr(10)) 

    c = InStr(1, sql_from, Chr(13)) 

    d = InStr(1, sql_from, Chr(9)) 

    MinC = a 

    If MinC > b And b > 0 Then MinC = b 

    If MinC > c And c > 0 Then MinC = c 

    If MinC > d And d > 0 Then MinC = d 

    tables = tables + "[" + Mid(sql_from, 1, MinC - 1) + "]" 

Wend 

'get all tables after join 

sql_join = sql_query 

While InStr(1, UCase(sql_join), UCase("join")) > 0 

    i = InStr(1, UCase(sql_join), UCase("join")) 

    sql_join = Mid(sql_join, i + 5, Len(sql_join) - i - 5) 

    i = InStr(1, UCase(sql_join), UCase(" ")) 

    While i = 1 

     sql_join = Mid(sql_join, 2, Len(sql_join) - 1) 

     i = InStr(1, UCase(sql_join), UCase(" ")) 

    Wend 

    i = InStr(1, sql_join, Chr(9)) 

    While i = 1 

     sql_join = Mid(sql_join, 2, Len(sql_join) - 1) 

     i = InStr(1, sql_join, Chr(9)) 

    Wend 

    a = InStr(1, UCase(sql_join), UCase(" ")) 

    b = InStr(1, sql_join, Chr(10)) 

    c = InStr(1, sql_join, Chr(13)) 

    d = InStr(1, sql_join, Chr(9)) 

    MinC = a 

    If MinC > b And b > 0 Then MinC = b 

    If MinC > c And c > 0 Then MinC = c 

    If MinC > d And d > 0 Then MinC = d 

    tables = tables + "[" + Mid(sql_join, 1, MinC - 1) + "]" 

Wend 

tables = Replace(tables, ")", "") 

tables = Replace(tables, "(", "") 

tables = Replace(tables, " ", "") 

tables = Replace(tables, Chr(10), "") 

tables = Replace(tables, Chr(13), "") 

tables = Replace(tables, Chr(9), "") 

tables = Replace(tables, "[]", "") 

末次