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

发布时间 - 2026-01-11 02:15:14    点击率:

我在工作的时候,在测试环境下使用的数据库跟生产环境的数据库不一致,当我们的测试环境下的数据库完成测试准备更新到生产环境上的数据库时候,需要准备更新脚本,真是一不小心没记下来就会忘了改了哪里,哪里添加了什么,这个真是非常让人头疼。因此我就试着用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实现的简单模板引擎功能示例  # shell命令行  # 一键创建 python 模板文件脚本方法  # 使用pycharm生成代码模板的实例  # Python实现自动添加脚本头信息的示例代码  # 对python实现模板生成脚本的方法详解  # 放在  # 目录下  # 给大家  # 我就  # 就会  # 让人  # 我在  # 我这  # 下了  # 希望能  # 几种  # 当我们  # 这篇  # 试着  # 来实现  # 改了  # 很方便  # 数据库中  # 小编  # 大家多多 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: JavaScript如何实现倒计时_时间函数如何精确控制  如何用西部建站助手快速创建专业网站?  Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】  java ZXing生成二维码及条码实例分享  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  南京网站制作费用,南京远驱官方网站?  香港服务器网站卡顿?如何解决网络延迟与负载问题?  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  php json中文编码为null的解决办法  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】  Laravel如何创建自定义Facades?(详细步骤)  黑客如何通过漏洞一步步攻陷网站服务器?  如何选择可靠的免备案建站服务器?  Laravel怎么使用Intervention Image库处理图片上传和缩放  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  ,南京靠谱的征婚网站?  香港服务器如何优化才能显著提升网站加载速度?  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  HTML 中动态设置元素 name 属性的正确语法详解  如何在IIS中配置站点IP、端口及主机头?  Android中AutoCompleteTextView自动提示  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  MySQL查询结果复制到新表的方法(更新、插入)  猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】  武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?  如何破解联通资金短缺导致的基站建设难题?  大同网页,大同瑞慈医院官网?  如何快速搭建高效服务器建站系统?  Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程  Python文本处理实践_日志清洗解析【指导】  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  香港服务器WordPress建站指南:SEO优化与高效部署策略  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  如何快速搭建安全的FTP站点?  如何快速搭建二级域名独立网站?  文字头像制作网站推荐软件,醒图能自动配文字吗?  教你用AI润色文章,让你的文字表达更专业  如何在新浪SAE免费搭建个人博客?  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  JavaScript模板引擎Template.js使用详解  浅谈Javascript中的Label语句  什么是JavaScript解构赋值_解构赋值有哪些实用技巧  Python文件操作最佳实践_稳定性说明【指导】  iOS验证手机号的正则表达式  如何在建站宝盒中设置产品搜索功能?