我正在尝试创建一个多脚本工具,它将接受一个 .sql 文件的参数并执行它。
我已经设置了一个简单的测试,只在一个数据库上执行,但是语法每次都会给我带来问题。
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 workbench 工作。
我在另一个网站上看到了这种解决方案:
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 文件的方法。我厌倦了尝试进行字符串操作并让它为这个特定文件工作,因为那样的话,让这个工具变得模棱两可和可重用的梦想就破灭了。
我是否以完全错误的方式处理此问题?
谢谢!
最佳答案
这是我使用 SQL 文件和 PyMySQL
的解决方案。这些文件包含许多以 ;
结尾的请求,用于拆分列表中的请求。因此,请注意列表中缺少的 ;
。
我决定添加缺少的 ;
不在函数中以保留 for 循环。也许有更好的方法。
创建-db-loff.sql
:
DROP DATABASE IF EXISTS loff;
CREATE DATABASE loff CHARACTER SET 'utf8';
USE loff;
CREATE TABLE product(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`code` BIGINT UNSIGNED NOT NULL UNIQUE,
`name` VARCHAR(200),
`nutrition_grades` VARCHAR(1)
);
CREATE TABLE category(
`id`INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(200)
);
CREATE TABLE asso_prod_cat(
`category_id` INT UNSIGNED NOT NULL,
`product_id` INT UNSIGNED NOT NULL,
CONSTRAINT `fk_asso_prod_cat_category`
FOREIGN KEY(category_id)
REFERENCES category(id)
ON DELETE CASCADE,
CONSTRAINT `fk_asso_prod_cat_product`
FOREIGN KEY(product_id)
REFERENCES product(id)
ON DELETE CASCADE
);
db.py
:
DB_CONFIG = {
'host': 'localhost',
'user': 'loff',
'pass': 'loff',
'db': 'loff',
'char': 'utf8',
'file': 'create-db-loff.sql'
}
def get_sql_from_file(filename=DB_CONFIG['file']):
"""
Get the SQL instruction from a file
:return: a list of each SQL query whithout the trailing ";"
"""
from os import path
# File did not exists
if path.isfile(filename) is False:
print("File load error : {}".format(filename))
return False
else:
with open(filename, "r") as sql_file:
# Split file in list
ret = sql_file.read().split(';')
# drop last empty entry
ret.pop()
return ret
request_list = self.get_sql_from_file()
if request_list is not False:
for idx, sql_request in enumerate(request_list):
self.message = self.MSG['request'].format(idx, sql_request)
cursor.execute(sql_request + ';')
关于python - 读取 .sql 文件以在 Python 中执行 (pymysql),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36946444/