Форматирование запроса SQL - PullRequest
0 голосов
/ 24 июня 2019

У меня есть входная строка, которая является запросом SQL.Мне нужно получить все таблицы, которые использует запрос (например, FROM table или table1 INNER JOIN table2 ).Но запрос не соответствует никаким стандартам.Поэтому мой вопрос заключается в том, существует ли какой-либо метод для форматирования запроса, чтобы упростить поиск по этим именам таблиц.

В настоящее время мой метод состоит в том, чтобы искать ключевые слова из и объединять их и брать любую строку после ключевого слова.(или раньше в случае объединения), но в запросах есть исключения, в которых у символа from нет новой строки после него, и я должен рассматривать каждое исключение следующим образом.Я не думаю, что регулярное выражение работает, потому что, хотя имя таблицы {schema_name.table_name}, есть и такие столбцы.

for row in text:
    to_append = None
    split_row = row.strip('\r').strip(' ').strip('\r').split(' ')
    if split_row[-1].lower() == "from" and len(split_row) > 1:
        from_indexes.append(text.index(row))
    if ("join" in split_row or "JOIN" in split_row) and (split_row[-1] != "join" and split_row[-1]
                                                         != "JOIN"):
        for ind in range(len(split_row)):
            if split_row[ind].lower() == "join":
                to_append = split_row[ind + 1:]
                row = split_row[:ind + 1]
                row = ' '.join(row)
    rows.append(row.strip('\r').strip(' ').strip('\t'))
    if to_append is not None:
        rows.append(' '.join(to_append))

Поэтому я ищу какой-то метод, который может стандартизировать SQL-запрос или другойметод извлечения имен таблиц из запроса.

Ответы [ 2 ]

0 голосов
/ 24 июня 2019

Я думаю, что более простым подходом было бы использование регулярных выражений :

import re

sql = """select t1.*, t2.y, sq.z, table3.q from table1 t1 join
    table2 t2 on t1.x = t2.x left join
    (select 5 as x, 9 as z) sq JOIN
    table3 on sq.x = table3.x
;"""

matches = re.findall(r'(\s+(from|join)\s+)(\w+)', sql, re.DOTALL|re.IGNORECASE)
for match in matches:
    print(match[2])

Обратите внимание, что он не будет рассматривать (выберите 5 как x, 9 как z) как таблицу.

0 голосов
/ 24 июня 2019

Вы должны использовать инструмент ORM, чтобы делать более чистые запросы (см. https://en.wikipedia.org/wiki/Object-relational_mapping). или, по крайней мере, некоторые модули построителя запросов.

Я недавно нашел римейк "красноречивых" орков Ларавеллов здесь https://pypi.org/project/eloquent/.

Другие ORM, такие как PeeWee, тоже довольно распространены.

...