【问题标题】:How to extract tables names in a SQL script?如何在 SQL 脚本中提取表名?
【发布时间】:2018-09-21 05:16:49
【问题描述】:

假设有一个sql脚本:

select *
from (
  select col1 from test.test_a join test.test_a1 on a.col1 = a1.col1) a
left join test.test_b b 
on a.col1 = b.col2
left join
    test.test_c c
on b.col2  = c.col3
left jon
   (select 
       col4 
    from
       test.test_d) d
on c.col3  = d.col4

我正在阅读 this question 并尝试使用 python 在上面的脚本中提取“from”或“join”之后的所有表名。 困难是我正在逐行处理脚本,但表名和关键字可能NOT在同一行。

那么如何从脚本中提取这样的表名呢?任何建议表示赞赏。

【问题讨论】:

  • 它和python有什么关系?

标签: python parsing


【解决方案1】:

如果你想使用核心python:

txt = """
select *
from (
  select col1 from test.test_a join test.test_a1 on a.col1 = a1.col1) a
left join test.test_b b 
on a.col1 = b.col2
left join
    test.test_c c
on b.col2  = c.col3
left jon
   (select 
       col4 
    from
       test.test_d) d
on c.col3  = d.col4"""

replace_list = ['\n', '(', ')', '*', '=']
for i in replace_list:
    txt = txt.replace(i, ' ')
txt = txt.split()
res = []
for i in range(1, len(txt)):
    if txt[i-1] in ['from', 'join'] and txt[i] != 'select': 
        res.append(txt[i])
print(res)

【讨论】:

  • 这病了……哈哈。我知道我们不应该发表赞美,但哇,这很简单。现在我要处理一些大的 SQL 文件,所以我们会看看它是如何提高性能的,但是哇!这么简单……
【解决方案2】:

只需将所有多个空格序列(包括换行符)转换为一个空格,就可以得到一行,然后 cat 使用正则表达式查找表名。

import re
sql = """select *
from (
  select col1 from test.test_a join test.test_a1 on a.col1 = a1.col1) a
left join test.test_b b 
on a.col1 = b.col2
left join
    test.test_c c
on b.col2  = c.col3
left join
   (select 
       col4 
    from
       test.test_d) d
on c.col3  = d.col4"""
sql_line = re.sub('\s+', ' ', sql)
tbl_re = re.compile(r'(?:\b(?:from)|(?:join)\b\s+)(\w+)\b')
tablenames = tbl_re.findall(sql_line)
print(tablenames)

请注意,表名提取正则表达式已简化,仅用作示例(您必须考虑可能的引用等)。

【讨论】:

    【解决方案3】:

    这是对@r.user.05apr 答案的快速改进。结合https://stackoverflow.com/a/46177004/82961中的一些位

    import re
    
    txt = """
    select *
    from (
      select col1 from  test.test_a join test.test_a1 on a.col1 = a1.col1) a
    left join test.test_b b 
    on a.col1 = b.col2
    left join
        test.test_c c -- from xxx
    on b.col2  = c.col3 /* join xxxxx */
    left jon
       (select 
           col4 
        from
           test.test_d) d
    on c.col3  = d.col4"""
    
    def get_tables(sql_str):
        # remove the /* */ comments
        sql_str = re.sub(r"/\*[^*]*\*+(?:[^*/][^*]*\*+)*/", "", sql_str)
    
        # remove whole line -- and # comments
        lines = [line for line in sql_str.splitlines() if not re.match("^\s*(--|#)", line)]
    
        # remove trailing -- and # comments
        sql_str = " ".join([re.split("--|#", line)[0] for line in lines])
    
        replace_list = ['\n', '(', ')', '*', '=']
        for i in replace_list:
            sql_str = sql_str.replace(i, ' ')
        sql_str = sql_str.split()
        res = []
        for i in range(1, len(sql_str)):
            if sql_str[i-1] in ['from', 'join'] and sql_str[i] != 'select': 
                res.append(sql_str[i])
        print(res)
        
    get_tables(txt)
    

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 2017-02-26
      • 2021-12-26
      • 2019-07-26
      • 2016-06-08
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多