6

Python内から.sqlファイルでいくつかのSQLコマンドを実行する方法はありますが、ファイル内のすべての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このファイルでは、関連するコマンド (つまり、 drop と create )のみを解析して実行したいのですが、tableBPython 内から他のテーブルで SQL コマンドを実行するのは好きではありません。Python 内から .​​sql ファイルを実行する方法についてある程度の知識はありますが、上記の例で述べたように、.sql ファイル内の特定のコマンドのみを実行する方法がわかりません。最初に頭に浮かんだのは、正規表現を使用することです。しかし、少し格闘した後、正規表現の知識と経験が乏しいため、正しい正規表現構文を思いつくことができませんでした。

だから私の質問は、

1) 正規表現を使用して目的のコマンドのみを取得するのは正しい方法ですか? もしそうなら、それを解析するための正しい構文を教えてもらえますか?

2) ここで正規表現が最善の方法ではない場合、代替ソリューションは何ですか?

3) オンラインの正規表現テスト ツールをいくつか見つけましたが、それらはすべて、式とテスト文字列の両方を指定し、文字列内の一致するデータを強調表示するものです。最初にテスト文字列を指定し、次に文字列内の目的のデータを手動で強調表示してから、適切な構文/式を逆に返すツールがあれば素晴らしいと思います。そのようなツール(オンラインツールに限りません!Macintoshアプリなら嬉しいです)をご存知でしたら教えてください...

ありがとう。

4

3 に答える 3

6

SQL ステートメントを解析することで作業を容易にし、SQL ステートメント内でトークンをクエリして操作する機能を提供するsqlparseライブラリを試すことができます。tableBあなたの場合のように、特定のトークンを含むステートメントを除外することは、グースベースになる可能性があります

于 2013-05-27T12:18:18.097 に答える
1

正規表現は適切なツールではないかもしれませんが、それでも使用できます。

>>> 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;']
>>>

何だろうと思ったら

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

は for です。単に を除く任意の文字に一致するために使用されます。none;を含む任意の回数

また

文字列リテラル。つまり、;のような文字列内で一致できるようになり'this is a ;value; for a varchar field'ます。

于 2013-05-27T11:45:03.747 に答える
1

個人的には、何らかの解析ライブラリを使用して SQL の AST を解析する必要があると考えていますが、コードを調べると、このオプションも実行可能になります。

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)
于 2013-05-27T12:37:50.920 に答える