背景
.sql文件存放的是数据库的建表,插入,查询等sql,现在需要python连接数据库去执行sql文件中的所有操作。通过数据库客户端工具或者查询窗口可以批量执行。但是使用pymysql没有直接执行sql文件的方法。替代路线是解析sql文件内容成每条可单独执行的sql语句。然后一次循环excute。所以这里的核心问题是如何解析sql文件。
首先根据;切分显然不适合,不能正确解析插入内容中带有;的sql。还有一些建表语句是换行存在sql文件中的,简单的按行处理也不适合。为了适配这些情况,直接上代码。
给一个sql文件样例,内容如下:
-- ----------------------------
-- Table structure for t_dg_mdatt_catalog
-- ----------------------------
DROP TABLE IF EXISTS t_catalog;
CREATE TABLE t_catalog (
MD_ID varchar(32) NOT NULL COMMENT '元数据id',
DEFAULT_CHARACTER_SETNAME varchar(1000) DEFAULT NULL COMMENT '默认字符集名',
DEFAULT_COLLATION_NAME varchar(1000) DEFAULT NULL COMMENT '默认校检名称',
IP varchar(1000) DEFAULT NULL COMMENT 'IP地址',
CREATE_TIME varchar(16) DEFAULT NULL COMMENT '创建时间',
UPDATE_TIME varchar(16) DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (MD_ID)
) COMMENT='目录属性表';
insert into TEST_TB (ID, CODE, NAME, PARENT_ID, REFERENCE_STANDARDS, DESCRIBES, SORT, DELETE_FLAG, CREATE_TIME, CREATE_USER, UPDATE_TIME, UPDATE_USER,TENANT_ID)
values ('00000000675e54b401675e5765550003', '01', '国标;\n', '0', '国标;\n', '国标', 1, '0', '20181129152045', 'sadmin', '20181129152045', 'sadmin','1');
-- commit;
commit;
处理的代码如下:
def readsql_from_file(sqlfile_path):
try:
mylogger.info("sql文件%s,开始内容转化" % (sqlfile_path))
print("sql文件%s,开始内容转化" % (sqlfile_path))
fp = open(sqlfile_path, 'r', encoding='utf-8')
sql_str = fp.readlines()
# results_list = sql_str.split(";")
results, results_list = [], []
##去除\n\r
if sql_str[-1].endswith(";"):
sql_str[-1] = sql_str[-1] + "\n"
for sql in sql_str:
if sql.startswith( "\n") or sql == "\r":
continue
if sql.startswith("--"):
continue
# 去除数据中的“\n”和“\r”字符
# if sql.endswith("\n"):
# sql = sql[::-1].replace("\n", "",1)[::-1]
# if sql.endswith("\r"):
# sql = sql[::-1].replace("\r", "",1)[::-1]
# sql = sql.replace("\n", "").replace("\r", "")
# 获取不是“--”开头且不是“--”结束的数据
if not sql.startswith("--") and not sql.endswith("--"):
if not sql.startswith("/*"):
results.append(sql)
trmp_res_sql_list, res_sql_list = [], []
while len(results) > 0:
for i in range(len(results)):
if results[i].endswith(";\n"):
tem_str = "".join(results[:i + 1])
trmp_res_sql_list.append(tem_str)
del results[:i + 1]
break
# print(len(trmp_res_sql_list))
for i in trmp_res_sql_list:
if i.endswith(";\n"):
i = i.strip()
# i= i.replace(";\n","",1)
i = i[::-1].replace(";", "", 1)[::-1]
# i = i[::-1].replace(";\n", "", 1)[::-1]
# print(str(i))
res_sql_list.append(i)
mylogger.info("sql文件%s,内容转化成功,转化待执行sql共%s条" % (sqlfile_path, str(len(res_sql_list))))
print("sql文件%s,内容转化成功,转化待执行sql共%s条" % (sqlfile_path, str(len(res_sql_list))))
return res_sql_list
except Exception as ex:
mylogger.error("sql文件%s,内容转化失败,错误信息%s" % (sqlfile_path, str(ex)))
print("ERROR,sql文件%s,内容转化失败,失败信息%s" % (sqlfile_path, str(ex)))
return None
if __name__ == "__main__":
sql_list = readsql_from_file('./try.sql')
for sql_str in range(len(sql_list)):
print("第%s条SQL"%(str(sql_str)),sql_list[sql_str])
调用结果如下
sql文件./try.sql,开始内容转化
sql文件./try.sql,内容转化成功,转化待执行sql共4条
第0条SQL DROP TABLE IF EXISTS t_catalog
第1条SQL CREATE TABLE t_catalog (
MD_ID varchar(32) NOT NULL COMMENT '元数据id',
DEFAULT_CHARACTER_SETNAME varchar(1000) DEFAULT NULL COMMENT '默认字符集名',
DEFAULT_COLLATION_NAME varchar(1000) DEFAULT NULL COMMENT '默认校检名称',
IP varchar(1000) DEFAULT NULL COMMENT 'IP地址',
CREATE_TIME varchar(16) DEFAULT NULL COMMENT '创建时间',
UPDATE_TIME varchar(16) DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (MD_ID)
) COMMENT='目录属性表'
第2条SQL insert into TEST_TB (ID, CODE, NAME, PARENT_ID, REFERENCE_STANDARDS, DESCRIBES, SORT, DELETE_FLAG, CREATE_TIME, CREATE_USER, UPDATE_TIME, UPDATE_USER,TENANT_ID)
values ('00000000675e54b401675e5765550003', '01', '国标;\n', '0', '国标;\n', '国标', 1, '0', '20181129152045', 'sadmin', '20181129152045', 'sadmin','1')
第3条SQL commit