2008-11-11 109 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, "[]", "") 

末次