Как извлечь имена таблиц в sql-скрипт?

Предполагая, что есть 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

Я читаю этот вопрос и пытаюсь извлечь все ИМЕНА ТАБЛИЦ после «from» или «join» в приведенном выше сценарии с использованием python. Трудность в том, что я обрабатываю сценарий построчно, но имя таблицы и ключевое слово могут быть НЕТ в одной строке.

Так как же извлечь такие имена таблиц из скрипта? Любое предложение приветствуется.

Как это связано с питоном?

Mehrdad Pedramfar 11.04.2018 12:47
1
1
3 659
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Просто преобразуйте все несколько последовательностей пробелов (включая новые строки) в один пробел, тогда вы получите одну строку, и кошка будет искать имена ваших таблиц, используя регулярное выражение.

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)

Обратите внимание, что регулярное выражение для извлечения имени таблицы упрощено и предназначено только в качестве примера (вы должны учитывать возможное цитирование и т. Д.).

Ответ принят как подходящий

Если вы хотите использовать основной питон:

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)

Вот быстрое улучшение поверх ответа @ 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)

Другие вопросы по теме