Python 实现数据库(SQL)更新脚本的生成方法


Posted in Python onJuly 09, 2017

我在工作的时候,在测试环境下使用的数据库跟生产环境的数据库不一致,当我们的测试环境下的数据库完成测试准备更新到生产环境上的数据库时候,需要准备更新脚本,真是一不小心没记下来就会忘了改了哪里,哪里添加了什么,这个真是非常让人头疼。因此我就试着用Python来实现自动的生成更新脚本,以免我这烂记性,记不住事。

主要操作如下:

1.在原先 basedao.py 中添加如下方法,这样旧能很方便的获取数据库的数据,为测试数据库和生产数据库做对比打下了基础。

def select_database_struts(self):
  '''
  查找当前连接配置中的数据库结构以字典集合
  '''
  sql = '''SELECT COLUMN_NAME, IS_NULLABLE, COLUMN_TYPE, COLUMN_KEY, COLUMN_COMMENT
    FROM information_schema.`COLUMNS` 
    WHERE TABLE_SCHEMA="%s" AND TABLE_NAME="{0}" '''%(self.__database)
  struts = {}
  for k in self.__primaryKey_dict.keys():
   self.__cursor.execute(sql.format(k))
   results = self.__cursor.fetchall()
   struts[k] = {}
   for result in results:
    struts[k][result[0]] = {}
    struts[k][result[0]]["COLUMN_NAME"] = result[0]
    struts[k][result[0]]["IS_NULLABLE"] = result[1]
    struts[k][result[0]]["COLUMN_TYPE"] = result[2]
    struts[k][result[0]]["COLUMN_KEY"] = result[3]
    struts[k][result[0]]["COLUMN_COMMENT"] = result[4]
  return self.__config, struts

2.编写对比的Python脚本

'''
数据库迁移脚本, 目前支持一下几种功能:
1.生成旧数据库中没有的数据库表执行 SQL 脚本(支持是否带表数据),生成的 SQL 脚本在 temp 目录下(表名.sql)。
2.生成添加列 SQL 脚本,生成的 SQL 脚本统一放在 temp 目录下的 depoyed.sql 中。
3.生成修改列属性 SQL 脚本,生成的 SQL 脚本统一放在 temp 目录下的 depoyed.sql 中。
4.生成删除列 SQL 脚本,生成的 SQL 脚本统一放在 temp 目录下的 depoyed.sql 中。
'''
import json, os, sys
from basedao import BaseDao

temp_path = sys.path[0] + "/temp"
if not os.path.exists(temp_path):
 os.mkdir(temp_path)

def main(old, new, has_data=False):
 '''
 @old 旧数据库(目标数据库)
 @new 最新的数据库(源数据库)
 @has_data 是否生成结构+数据的sql脚本 
 '''
 clear_temp() # 先清理 temp 目录
 old_config, old_struts = old
 new_config, new_struts = new
 for new_table, new_fields in new_struts.items():
  if old_struts.get(new_table) is None:
   gc_sql(new_config["user"], new_config["password"], new_config["database"], new_table, has_data)
  else:
   cmp_table(old_struts[new_table], new_struts[new_table], new_table)

def cmp_table(old, new, table):
 '''
 对比表结构生成 sql
 '''
 old_fields = old
 new_fields = new

 sql_add_column = "ALTER TABLE `{TABLE}` ADD COLUMN `{COLUMN_NAME}` {COLUMN_TYPE} COMMENT '{COLUMN_COMMENT}';\n"
 sql_change_column = "ALTER TABLE `{TABLE}` CHANGE `{COLUMN_NAME}` `{COLUMN_NAME}` {COLUMN_TYPE} COMMENT '{COLUMN_COMMENT}';\n"
 sql_del_column = "ALTER TABLE `{TABLE}` DROP {COLUMN_NAME};"

 if old_fields != new_fields:
  f = open(sys.path[0] + "/temp/deploy.sql", "a", encoding="utf8")
  content = ""
  for new_field, new_field_dict in new_fields.items():
   old_filed_dict = old_fields.get(new_field)
   if old_filed_dict is None:
    # 生成添加列 sql
    content += sql_add_column.format(TABLE=table, **new_field_dict)
   else:
    # 生成修改列 sql
    if old_filed_dict != new_field_dict:
     content += sql_change_column.format(TABLE=table, **new_field_dict)
    pass
  # 生成删除列 sql
  for old_field, old_field_dict in old_fields.items():
   if new_fields.get(old_field) is None:
    content += sql_del_column.format(TABLE=table, COLUMN_NAME=old_field)
    
  f.write(content)
  f.close()

def gc_sql(user, pwd, db, table, has_data):
 '''
 生成 sql 文件
 '''
 if has_data:
  sys_order = "mysqldump -u%s -p%s %s %s > %s/%s.sql"%(user, pwd, db, table, temp_path, table)
 else:
  sys_order = "mysqldump -u%s -p%s -d %s %s > %s/%s.sql"%(user, pwd, db, table, temp_path, table)
 os.system(sys_order)

def clear_temp():
 '''
 每次执行的时候调用这个,先清理下temp目录下面的旧文件
 '''
 if os.path.exists(temp_path):
  files = os.listdir(temp_path)
  for file in files:
   f = os.path.join(temp_path, file)
   if os.path.isfile(f):
    os.remove(f)
 print("临时文件目录清理完成")

if __name__ == "__main__":
 test1_config = {
  "user" : "root", 
  "password" : "root",
  "database" : "test1", 
 }
 test2_config = {
  "user" : "root", 
  "password" : "root",
  "database" : "test2", 
 }
 
 test1_dao = BaseDao(**test1_config)
 test1_struts = test1_dao.select_database_struts()
 
 test2_dao = BaseDao(**test2_config)
 test2_struts = test2_dao.select_database_struts()

 main(test2_struts, test1_struts)

目前只支持了4种SQL脚本的生成。

总结

以上所述是小编给大家介绍的Python 实现数据库(SQL)更新脚本的生成方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Python 相关文章推荐
python基础教程之获取本机ip数据包示例
Feb 10 Python
Python使用cookielib模块操作cookie的实例教程
Jul 12 Python
Django中的CBV和FBV示例介绍
Feb 25 Python
python装饰器-限制函数调用次数的方法(10s调用一次)
Apr 21 Python
Python图像处理之直线和曲线的拟合与绘制【curve_fit()应用】
Dec 26 Python
pyqt远程批量执行Linux命令程序的方法
Feb 14 Python
Python opencv实现人眼/人脸识别以及实时打码处理
Apr 29 Python
详解Python利用random生成一个列表内的随机数
Aug 21 Python
PyTorch实现更新部分网络,其他不更新
Dec 31 Python
Python 使用office365邮箱的示例
Oct 29 Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
Jan 05 Python
python基于opencv批量生成验证码的示例
Apr 28 Python
解决python文件字符串转列表时遇到空行的问题
Jul 09 #Python
python3 shelve模块的详解
Jul 08 #Python
Python基于scapy实现修改IP发送请求的方法示例
Jul 08 #Python
Python开发微信公众平台的方法详解【基于weixin-knife】
Jul 08 #Python
python 中random模块的常用方法总结
Jul 08 #Python
Python调用微信公众平台接口操作示例
Jul 08 #Python
HTML中使用python屏蔽一些基本功能的方法
Jul 07 #Python
You might like
php 网上商城促销设计实例代码
2012/02/17 PHP
CodeIgniter集成smarty的方法详解
2016/05/26 PHP
PHP实现基于3DES算法加密解密字符串示例
2018/08/24 PHP
解决Laravel blade模板转义html标签的问题
2019/09/03 PHP
Js中sort()方法的用法
2006/11/04 Javascript
jquery 多行文本框(textarea)高度变化
2013/07/03 Javascript
JavaScript正则表达式之multiline属性的应用
2015/06/16 Javascript
js实现人才网站职位选择功能的方法
2015/08/14 Javascript
jQuery插件实现多级联动菜单效果
2015/12/01 Javascript
jQuery+HTML5实现弹出创意搜索框层
2016/12/29 Javascript
BootStrap3中模态对话框的使用
2017/01/06 Javascript
解决webpack打包速度慢的解决办法汇总
2017/07/06 Javascript
bootstrap-table.js扩展分页工具栏(增加跳转到xx页)功能
2017/12/28 Javascript
vue devtools的安装与使用教程
2018/08/08 Javascript
vue服务端渲染操作简单入门实例分析
2019/08/28 Javascript
详解JavaScript中的数据类型,以及检测数据类型的方法
2020/09/17 Javascript
[03:15]2014DOTA2国际邀请赛 专访国士无双信心满满
2014/07/12 DOTA
Python实现全角半角字符互转的方法
2016/11/28 Python
python 日志增量抓取实现方法
2018/04/28 Python
python组合无重复三位数的实例
2018/11/13 Python
Python3.5 + sklearn利用SVM自动识别字母验证码方法示例
2019/05/10 Python
python 公共方法汇总解析
2019/09/16 Python
python web框架Flask实现图形验证码及验证码的动态刷新实例
2019/10/14 Python
使用Python生成200个激活码的实现方法
2019/11/22 Python
python Zmail模块简介与使用示例
2020/12/19 Python
python 制作本地应用搜索工具
2021/02/27 Python
工程采购员岗位职责
2014/03/09 职场文书
2014年骨干教师工作总结
2014/12/19 职场文书
股东合作协议书模板2篇
2019/11/05 职场文书
CSS实现漂亮的时钟动画效果的实例代码
2021/03/30 HTML / CSS
vue基于Teleport实现Modal组件
2021/05/31 Vue.js
详解Java线程池是如何重复利用空闲线程的
2021/06/26 Java/Android
PHP使用QR Code生成二维码实例
2021/07/07 PHP
疑《守望先锋2》A测截图泄露 或将推出新模式、新界面
2022/04/03 其他游戏
Go语言入门exec的基本使用
2022/05/20 Golang
pandas中pd.groupby()的用法详解
2022/06/16 Python