2016-04-29 12 views
0

.sqlファイルの引数をとり、それを実行するマルチスクリプトツールを作成しようとしています。Pythonでの実行のための.sqlファイルの読み込み(pymysql)

私はシンプルなテストを設定しましたが、ただ1つのデータベースで実行していますが、構文は毎回問題を出しています。

DELIMITER $$ 
CREATE DEFINER=`a_user`@`%` PROCEDURE `a_procedure`(
    IN DirectEmployeeID TEXT, 
    IN StartRange DATE, 
    IN EndRange DATE 
) 
BEGIN 
SELECT aColumn 
WHERE thisThing = 1; 
END$$ 
DELIMITER ; 

明確にするため、このスクリプトはテストされ、同様に渡されたときに動作されています:

mysql -uuser -p -hhost -Pport databaseName < file.sql 

ともMySQLのワークベンチを介して動作します。

私は別のサイトにこのタイプのソリューションを見た:

with conn.cursor() as cursor: 
    f = sys.argv[1] 
    file = open(f, 'r') 
    sql = " ".join(file.readlines()) 
    cursor.execute(sql) 

私のMySQLの構文エラーを与える:

pymysql.err.ProgrammingError: (1064, u"You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right 
syntax to use near 'DELIMITER $$\n CREATE DEFINER=`a_user`@`%` PROCEDURE 
`MyCommissionsDirect`(\n \tIN ' at line 1") 

あなたが見ることができるように、そのmysqlのスクリプト内で改行文字があります好きではありません。

私は、この試みた:

with conn.cursor() as cursor: 
    f = sys.argv[1] 
    file = open(f, 'r') 
    sql = '' 
    line = file.readline() 
    while line: 
     sql += ' ' + line.strip('\n').strip('\t') 
     line = file.readline() 
    print sql 
    cursor.execute(sql) 

をし、別の構文の問題を取得し、印刷は、これがmysqlworkbenchで動作していないすべての1行、であることを示しています。それを実行しようとしない、それは奇妙です。

DELIMETER $$を最初に別の行に置くと、mysqlworkbenchで実行されます。

これは、私がこれをますます複雑にしているような状況の1つです。私は非常にpymysqlにSQLファイルを直接実行する方法がないことに非常に驚いています。私は文字列の操作をしようとするのが苦労し、この特定のファイルのためにこれを働かせます。なぜなら、このツールをあいまいで再利用可能なものにするという夢が出て行くからです。

私は完全に間違った方法でこれについて説明しますか?

ありがとうございます!

+0

これは役立ちます:http://stackoverflow.com/questions/24572140/formatting-in-pymysql-multiline-statement – Quinn

答えて

1

DELIMITERは、実際のMySQLコマンドではなく、コマンドラインやWorkbenchなどのMySQLインタプリタによって使用されるコマンドです。

私はDELIMITERが再び定義されているときに実行するために、DELIMITERが定義されている場合、MySQLのクエリの実行を無効にするには、私のPythonアプリケーションにいくつかのロジックで働くことになった:

import MySQLdb 
import re 

file = 'somesql.sql' 
conn = MySQLdb.Connection(mysqlserver, mysqluser, mysqlpass, mysqldb) 
curs = conn.cursor() 
ignorestatement = False # by default each time we get a ';' that's our cue to execute. 
statement = "" 
for line in open(file): 
    if line.startswith('DELIMITER'): 
     if not ignorestatement: 
      ignorestatement = True # disable executing when we get a ';' 
      continue 
     else: 
      ignorestatement = False # re-enable execution of sql queries on ';' 
      line = " ;" # Rewrite the DELIMITER command to allow the block of sql to execute 
    if re.match(r'--', line): # ignore sql comment lines 
     continue 
    if not re.search(r'[^-;]+;', line) or ignorestatement: # keep appending lines that don't end in ';' or DELIMITER has been called 
     statement = statement + line 
    else: # when you get a line ending in ';' then exec statement and reset for next statement providing the DELIMITER hasn't been set 
     statement = statement + line 
     # print "\n\n[DEBUG] Executing SQL statement:\n%s" % (statement) 
     try: 
      curs.execute(statement) 
      conn.commit() 
      statement = "" 
     except curs.Error, e: 
      print(file + " - Error applying (" + str(e) + ")\nTerminating.") 
      sys.exit(1) 

にですが、少しハックが、十分にうまくいくようです。

関連する問題