Как я могу разобрать sql файл из Python?

Есть ли способ выполнить некоторые команды SQL в файле .sql из Python, но не все команды SQL в файле? Предположим, у меня есть следующий .sql файл:

DROP TABLE IF EXISTS `tableA`;
CREATE TABLE `tableA`(
some_code
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `tableB`;
CREATE TABLE `tableB`(
some_code
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `tableC`;
CREATE TABLE `tableC`(
some_code
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
...to be continued...

В этом файле я хочу разобрать и запустить только tableB -связанную команду (т.е. отбросить и создать tableB), но не люблю выполнять какие-либо команды SQL на других таблицах из Python. У меня есть некоторые знания о том, как выполнить .sql файл из Python, но не знаю, как выполнять только некоторые определенные команды в файле .sql, как указано в приведенном выше примере. Первое, что бросается в глаза, - использовать регулярное выражение. Но после небольшого количества споров я не смог придумать правильный синтаксис регулярных выражений, чтобы получить от меня то, что я ожидал из-за моего плохого знания и опыта в регулярном выражении.

Итак, мой вопрос:

1) Правильно ли здесь использовать регулярное выражение для получения только желаемых команд, и если да, можете ли вы показать мне правильный синтаксис для его анализа?

2) Если регулярное выражение здесь не лучший, то какое альтернативное решение?

3) Я нашел несколько онлайн-инструментов для тестирования регулярных выражений, но все они должны указывать как выражение, так и тестовые строки и выделять согласованные данные в строке. Я считаю, что отлично, если есть некоторые инструменты, которые сначала меняют тестовые строки, а затем выделяют нужные данные внутри строки вручную, а затем возвращают некоторый соответствующий синтаксис/выражение неблагоприятно. Если вы знаете такие инструменты (никаких ограничений на онлайн-инструменты! Я также рад, если это приложение для Macintosh), пожалуйста, скажите мне...

Спасибо.

3 ответа

В то время как регулярное выражение не может быть правильным инструментом, вы все равно можете его использовать.

>>> statements = """
... DROP TABLE IF EXISTS `tableA`;
...
... CREATE TABLE `tableA`(
... some_code
... ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
...
... DROP TABLE IF EXISTS `tableB`;
...
... CREATE TABLE `tableB`(
... some_code
... ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
...
... DROP TABLE IF EXISTS `tableC`;
...
... CREATE TABLE `tableC`(
... some_code
... ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
... """
>>> regex = r"((?:CREATE|DROP) TABLE (?:IF (?:NOT )?EXISTS )?`tableB`(?:[^;]|(?:'.*?'))*;)"
>>> re.findall(regex, statements, re.I)
['DROP TABLE IF EXISTS `tableB`;', 'CREATE TABLE `tableB`(\nsome_code\n) ENGINE=MyISAM DEFAULT CHARSET=latin1;']
>>>

Если вам интересно, что

`(?:[^;]|(?:'.*?'))*`

для, он просто используется для сопоставления любого символа, кроме ;, любого количества раз, в том числе none

или

строковый литерал, то есть он позволит ; соответствовать внутри строки, например 'this is a ;value; for a varchar field'.


Вы можете опробовать библиотеку sqlparse, которая облегчит вашу работу путем анализа SQL-операторов и даст вам возможность запрашивать и работать с токенов в выражении SQL. Это может быть базой goos для фильтрации операторов, содержащих определенный токен, например tableB в вашем случае


Хотя я лично считаю, что вы должны использовать некоторую парсинг-библиотеку для анализа АСТ для SQL, просмотр кода также делает этот вариант жизнеспособным:

my_sql_code = '''DROP TABLE...''' #big long string, multiline
statements = my_sql_code.split(';')
statements = [s for s in statements if 'tableB' in s]
for s in statements:
 execute_sql(s)

licensed under cc by-sa 3.0 with attribution.