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入门篇之正则表达式
Oct 20 Python
python如何使用正则表达式的前向、后向搜索及前向搜索否定模式详解
Nov 08 Python
Python面向对象程序设计之继承与多继承用法分析
Jul 13 Python
pandas使用apply多列生成一列数据的实例
Nov 28 Python
基于python实现KNN分类算法
Apr 23 Python
python3 批量获取对应端口服务的实例
Jul 25 Python
执行Django数据迁移时报 1091错误及解决方法
Oct 14 Python
Python嵌套函数,作用域与偏函数用法实例分析
Dec 26 Python
Python编程快速上手——强口令检测算法案例分析
Feb 29 Python
python关于变量名的基础知识点
Mar 03 Python
解决python父线程关闭后子线程不关闭问题
Apr 25 Python
python和node.js生成当前时间戳的示例
Sep 29 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获得文件扩展名三法
2006/11/25 PHP
php处理单文件、多文件上传代码分享
2016/08/24 PHP
Yii2创建多界面主题(Theme)的方法
2016/10/08 PHP
全面解析PHP面向对象的三大特征
2017/06/10 PHP
php使用pecl方式安装扩展操作示例
2019/08/12 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
javaScript parseInt字符转化为数字函数使用小结
2009/11/05 Javascript
JS文本框默认值处理详解
2013/07/10 Javascript
js和php如何获取当前url的内容
2013/09/22 Javascript
js中的时间转换—毫秒转换成日期时间的示例代码
2014/01/26 Javascript
JavaScript中的Primitive对象封装介绍
2014/12/31 Javascript
jQuery中[attribute!=value]选择器用法实例
2014/12/31 Javascript
js简单判断移动端系统的方法
2016/02/25 Javascript
使用Vue做一个简单的todo应用的三种方式的示例代码
2018/10/20 Javascript
vue 父组件给子组件传值子组件给父组件传值的实例代码
2019/04/15 Javascript
手写Vue弹窗Modal的实现代码
2019/09/11 Javascript
VSCode插件安装完成后的配置(常用配置)
2020/08/24 Javascript
js实现弹幕飞机效果
2020/08/27 Javascript
Pyramid添加Middleware的方法实例
2013/11/27 Python
python中将字典形式的数据循环插入Excel
2018/01/16 Python
python学习——内置函数、数据结构、标准库的技巧(推荐)
2019/04/18 Python
python自动点赞功能的实现思路
2020/02/26 Python
普通大学毕业生自荐信
2013/11/04 职场文书
体育教育专业毕业生自荐信
2013/11/15 职场文书
自主招生自荐书
2013/11/29 职场文书
个人素质的自我评价分享
2013/12/16 职场文书
工程专业毕业生自荐信范文
2013/12/25 职场文书
中学生班主任评语
2014/01/30 职场文书
承兑汇票转让证明怎么写?
2014/11/30 职场文书
二胎满月酒致辞
2015/07/29 职场文书
红领巾广播站广播稿
2015/08/19 职场文书
银行服务理念口号
2015/12/25 职场文书
2016机关干部作风建设心得体会
2016/01/21 职场文书
AI:如何训练机器学习的模型
2021/04/16 Python
手把手教你导入Go语言第三方库
2021/08/04 Golang
css弧边选项卡的项目实践
2023/05/07 HTML / CSS