У меня есть входная строка, которая является SQL-запросом. Мне нужно получить все таблицы, которые использует запрос (например, FROM стол или Таблица 1 INNER JOIN Таблица 2). Но запрос не соответствует ни одному стандарту. Поэтому мой вопрос заключается в том, есть ли какой-либо способ форматирования запроса, чтобы упростить поиск этих имен таблиц.
Мой метод прямо сейчас состоит в том, чтобы искать ключевые слова из и соединять и брать любую строку после ключевого слова (или перед в случае соединения), но есть исключения в запросах, где из нет новой строки после него и Я должен обрабатывать каждое исключение таким образом. Я не думаю, что регулярное выражение работает, потому что хотя имя таблицы {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 или другой метод для извлечения имен таблиц из запроса.
Если и foo, и x не являются временными таблицами, мне нужны и foo, и x.
это был риторический вопрос! x — это CTE, следовательно, это не «настоящая» таблица, но она может быть интересна в зависимости от того, что вы пытаетесь сделать. foo — это фрагмент текста, встроенный в строку, поэтому его почти наверняка следует игнорировать любым разумным инструментом. если вы пишете код для разбора SQL, это стандартные проблемы, о которых вам нужно подумать и решить
Я создаю приложение, которое находит зависимости таблиц в других базах данных. В одной из таблиц есть метаданные, включая столбец с запросами sql и невременные таблицы после ключевого слова from/join, которые рассматриваются как зависимости, поэтому мне нужно анализировать SQL.






Вы должны использовать инструмент ORM, чтобы делать более чистые запросы (см. https://en.wikipedia.org/wiki/Object-relational_mapping). Или, по крайней мере, некоторые модули построения запросов.
Недавно я нашел ремейк laravels "reloquent" orm здесь https://pypi.org/project/eloquent/.
Другие ORM, такие как PeeWee, также довольно распространены.
Я не делаю запросы. У меня нет возможности их изменить.
Я думаю, что более простым подходом было бы использование регулярные выражения:
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) как таблицу.
Кажется, это ответ. Работает намного лучше, чем мой алгоритм. Спасибо.
Затем вы должны пометить ответ как «принятый», если и когда вы считаете, что это уместно. См. Что мне делать, когда кто-то отвечает на мой вопрос?.
почему ты хочешь сделать это? это очень неудобно в общем случае, например. что вы должны получить в ответ
WITH x AS (SELECT 'SELECT 1 FROM foo' AS y) SELECT * FROM x;?