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


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 实现数据库更新脚本的生成方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python with用法实例
Apr 14 Python
详解Python函数作用域的LEGB顺序
May 14 Python
python中实现迭代器(iterator)的方法示例
Jan 19 Python
Django + Uwsgi + Nginx 实现生产环境部署的方法
Jun 20 Python
Python根据文件名批量转移图片的方法
Oct 21 Python
利用Python正则表达式过滤敏感词的方法
Jan 21 Python
在Python 字典中一键对应多个值的实例
Feb 03 Python
python中自带的三个装饰器的实现
Nov 08 Python
pycharm 2019 最新激活方式(pycharm破解、激活)
Sep 22 Python
python numpy生成等差数列、等比数列的实例
Feb 25 Python
python字符串判断密码强弱
Mar 18 Python
python如何调用字典的key
May 25 Python
Python 实现数据库(SQL)更新脚本的生成方法
Jul 09 #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
You might like
PHP的一个基础知识 表单提交
2011/07/04 PHP
PHP实现视频文件上传完整实例
2014/08/28 PHP
javascript forEach通用循环遍历方法
2010/10/11 Javascript
JQuery动态给table添加、删除行 改进版
2011/01/19 Javascript
input 输入框获得/失去焦点时隐藏/显示文字(jquery版)
2013/04/02 Javascript
document.write的几点使用心得
2014/05/14 Javascript
Html5的placeholder属性(IE兼容)实现代码
2014/08/30 Javascript
js两种拼接字符串的简单方法(必看)
2016/09/02 Javascript
JavaScript中${pageContext.request.contextPath}取值问题及解决方案
2016/12/08 Javascript
jQuery实现模拟flash头像裁切上传功能示例
2016/12/11 Javascript
JS异步文件上传(兼容IE8+)
2017/04/02 Javascript
jQuery.Form实现Ajax上传文件同时设置headers的方法
2017/06/26 jQuery
webpack 打包压缩js和css的方法示例
2018/03/20 Javascript
微信小程序中添加客服按钮contact-button功能
2018/04/27 Javascript
JavaScript使用indexOf()实现数组去重的方法分析
2018/09/04 Javascript
koa-router源码学习小结
2018/09/07 Javascript
vue 解决兄弟组件、跨组件深层次的通信操作
2020/07/27 Javascript
Postman内建变量常用方法实例解析
2020/07/28 Javascript
Vue环境搭建+VSCode+Win10的详细教程
2020/08/19 Javascript
vue编写简单的购物车功能
2021/01/08 Vue.js
[00:48]完美“圣”典2016风云人物:xiao8宣传片
2016/11/30 DOTA
[38:39]KG vs Mineski 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
Python 处理数据的实例详解
2017/08/10 Python
对python创建及引用动态变量名的示例讲解
2018/11/10 Python
对IPython交互模式下的退出方法详解
2019/02/16 Python
python代码 FTP备份交换机配置脚本实例解析
2019/08/01 Python
HTML5打开本地app应用的方法
2016/03/31 HTML / CSS
为有想象力的人提供的生活方式商店:Firebox
2018/06/04 全球购物
小学生校园广播稿
2014/09/28 职场文书
检查机关党的群众路线个人整改措施
2014/10/04 职场文书
2014年纳税评估工作总结
2014/12/23 职场文书
2016年感恩节寄语
2015/12/07 职场文书
React + Threejs + Swiper 实现全景图效果的完整代码
2021/06/28 Javascript
python读取mnist数据集方法案例详解
2021/09/04 Python
python区块链实现简版工作量证明
2022/05/25 Python