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 help()函数用法详解
Mar 11 Python
Python多线程编程(三):threading.Thread类的重要函数和方法
Apr 05 Python
请不要重复犯我在学习Python和Linux系统上的错误
Dec 12 Python
Python 实现数据库(SQL)更新脚本的生成方法
Jul 09 Python
python邮件发送smtplib使用详解
Jun 16 Python
PyTorch的Optimizer训练工具的实现
Aug 18 Python
python画微信表情符的实例代码
Oct 09 Python
使用tqdm显示Python代码执行进度功能
Dec 08 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
Feb 28 Python
python Matplotlib模块的使用
Sep 16 Python
python 决策树算法的实现
Oct 09 Python
关于python中导入文件到list的问题
Oct 31 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仿博客园 个人博客(2) 数据库增添改删
2013/07/05 PHP
php获取汉字首字母的函数
2013/11/07 PHP
PHP排序算法类实例
2015/06/17 PHP
PHP多态代码实例
2015/06/26 PHP
PHP遍历目录文件的常用方法小结
2017/02/03 PHP
Laravel实现autoload方法详解
2017/05/07 PHP
XAMPP升级PHP版本实现步骤解析
2020/09/04 PHP
用JS实现的一个include函数
2007/07/21 Javascript
javascript温习的一些笔记 基础常用知识小结
2011/06/22 Javascript
浅谈如何实现easyui的datebox格式化
2016/06/12 Javascript
JQuery学习总结【一】
2016/12/01 Javascript
使用jQuery操作DOM的方法小结
2017/02/27 Javascript
微信小程序的生命周期的详解
2017/10/19 Javascript
vue实现购物车抛物线小球动画效果的方法详解
2019/02/13 Javascript
vue以组件或者插件的形式实现throttle或者debounce
2019/05/22 Javascript
微信小程序使用websocket通讯的demo,含前后端代码,亲测可用
2019/05/22 Javascript
vue请求数据的三种方式
2020/03/04 Javascript
微信小程序中使用 async/await的方法实例分析
2020/05/06 Javascript
[16:56]教你分分钟做大人:司夜刺客
2014/10/30 DOTA
[02:12]探秘2016国际邀请赛中国区预选赛选手房间
2016/06/25 DOTA
高性能web服务器框架Tornado简单实现restful接口及开发实例
2014/07/16 Python
python获取从命令行输入数字的方法
2015/04/29 Python
Python与人工神经网络:使用神经网络识别手写图像介绍
2017/12/19 Python
Python使用Pickle库实现读写序列操作示例
2018/06/15 Python
python提取具有某种特定字符串的行数据方法
2018/12/11 Python
python区分不同数据类型的方法
2019/10/14 Python
基于python实现检索标记敏感词并输出
2020/05/07 Python
html5 拖拽上传图片实例演示
2013/04/01 HTML / CSS
本科毕业生专业自荐书范文
2014/02/05 职场文书
优秀班主任事迹材料
2014/12/16 职场文书
新员工试用期工作总结2015
2015/05/28 职场文书
修辞手法有哪些?
2019/08/29 职场文书
JavaScript实现贪吃蛇游戏
2021/06/16 Javascript
Java获取e.printStackTrace()打印的信息方式
2021/08/07 Java/Android
详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑
2021/12/06 MySQL
MySQL 自动填充 create_time 和 update_time
2022/05/20 MySQL