2016-04-29 28 views
0

我正在嘗試創建一個多腳本工具,它將採用一個.sql文件的參數並執行它。閱讀.sql文件在Python中執行(pymysql)

我已經設置了一個簡單的測試,只是在一個數據庫上執行,但是語法每次都給我提出問題。

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工作。甚至不嘗試執行它,這很奇怪。

當我把DELIMETER $$放在一個單獨的行上時,它會在mysqlworkbench中執行。

這是其中一種情況,我覺得我可能會使這個越來越複雜。我很驚訝pymysql沒有直接執行sql文件的方法。我厭倦了試圖進行字符串操作,併爲這個特定的文件得到這個工作,因爲那時使得這個工具變得模糊和可重用的夢想成爲現實。

我是以完全不正確的方式解決這個問題嗎?

謝謝!

+0

這可能有所幫助:http://stackoverflow.com/questions/24572140/formatting-in-pymysql-multiline-statement – Quinn

回答

1

DELIMITER是由MySQL解釋器(例如命令行或工作臺)使用的命令,而不是實際的MySQL命令。

我結束了在一些邏輯的工作在我的Python應用程序時DELIMITER已經被定義爲禁用的MySQL查詢的執行,則執行時DELIMITER再次被定義爲:

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) 

這是一個有點哈克,但似乎工作得不錯。