zoukankan      html  css  js  c++  java
  • Python 实现数据库更新脚本的生成

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

      主要操作如下:

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

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

      2.编写对比的Python脚本

      1 '''
      2 数据库迁移脚本, 目前支持一下几种功能:
      3     1.生成旧数据库中没有的数据库表执行 SQL 脚本(支持是否带表数据),生成的 SQL 脚本在 temp 目录下(表名.sql)。
      4     2.生成添加列 SQL 脚本,生成的 SQL 脚本统一放在 temp 目录下的 depoyed.sql 中。
      5     3.生成修改列属性 SQL 脚本,生成的 SQL 脚本统一放在 temp 目录下的 depoyed.sql 中。
      6     4.生成删除列 SQL 脚本,生成的 SQL 脚本统一放在 temp 目录下的 depoyed.sql 中。
      7 注意事项:
      8     1.系统必须配置 mysql 的环境变量,确保 mysqldump 指令能执行。
      9     2.数据库表必须带有主键。
     10 '''
     11 import json, os, sys
     12 from basedao import BaseDao
     13 
     14 temp_path = sys.path[0] + "/temp"
     15 if not os.path.exists(temp_path):
     16     os.mkdir(temp_path)
     17 
     18 def main(old, new, has_data=False):
     19     '''
     20     @old 旧数据库(目标数据库)
     21     @new 最新的数据库(源数据库)
     22     @has_data 是否生成结构+数据的sql脚本 
     23     '''
     24     clear_temp()    # 先清理 temp 目录
     25     old_config, old_struts = old
     26     new_config, new_struts = new
     27     for new_table, new_fields in new_struts.items():
     28         if old_struts.get(new_table) is None:
     29             gc_sql(new_config["user"], new_config["password"], new_config["database"], new_table, has_data)
     30         else:
     31             cmp_table(old_struts[new_table], new_struts[new_table], new_table)
     32 
     33 def cmp_table(old, new, table):
     34     '''
     35     对比表结构生成 sql
     36     '''
     37     old_fields = old
     38     new_fields = new
     39 
     40     sql_add_column = "ALTER TABLE `{TABLE}` ADD COLUMN `{COLUMN_NAME}` {COLUMN_TYPE} COMMENT '{COLUMN_COMMENT}';
    "
     41     sql_change_column = "ALTER TABLE `{TABLE}` CHANGE `{COLUMN_NAME}` `{COLUMN_NAME}` {COLUMN_TYPE} COMMENT '{COLUMN_COMMENT}';
    "
     42     sql_del_column = "ALTER TABLE `{TABLE}` DROP {COLUMN_NAME};"
     43 
     44     if old_fields != new_fields:
     45         f = open(sys.path[0] + "/temp/deploy.sql", "a", encoding="utf8")
     46         content = ""
     47         for new_field, new_field_dict in new_fields.items():
     48             old_filed_dict = old_fields.get(new_field)
     49             if old_filed_dict is None:
     50                 # 生成添加列 sql
     51                 content += sql_add_column.format(TABLE=table, **new_field_dict)
     52             else:
     53                 # 生成修改列 sql
     54                 if old_filed_dict != new_field_dict:
     55                     content += sql_change_column.format(TABLE=table, **new_field_dict)
     56                 pass
     57         # 生成删除列 sql
     58         for old_field, old_field_dict in old_fields.items():
     59             if new_fields.get(old_field) is None:
     60                 content += sql_del_column.format(TABLE=table, COLUMN_NAME=old_field)
     61                 
     62         f.write(content)
     63         f.close()
     64 
     65 def gc_sql(user, pwd, db, table, has_data):
     66     '''
     67     生成 sql 文件
     68     '''
     69     if has_data:
     70         sys_order = "mysqldump -u%s -p%s %s %s > %s/%s.sql"%(user, pwd, db, table, temp_path, table)
     71     else:
     72         sys_order = "mysqldump -u%s -p%s -d %s %s > %s/%s.sql"%(user, pwd, db, table, temp_path, table)
     73     try:
     74         res = os.system(sys_order)
     75         if res == 0:
     76             print("生成%s表sql文件。"%table)
     77     except Exception as e:
     78         print(e)
     79 
     80 def clear_temp():
     81     '''
     82     每次执行的时候调用这个,先清理下temp目录下面的旧文件
     83     '''
     84     if os.path.exists(temp_path):
     85         files = os.listdir(temp_path)
     86         for file in files:
     87             f = os.path.join(temp_path, file)
     88             if os.path.isfile(f):
     89                 os.remove(f)
     90     print("临时文件目录清理完成")
     91 
     92 if __name__ == "__main__":
     93     test1_config = {
     94         "user" : "root", 
     95         "password" : "root",
     96         "database" : "test1", 
     97     }
     98     test2_config = {
     99         "user" : "root", 
    100         "password" : "root",
    101         "database" : "test2", 
    102     }
    103     
    104     test1_dao = BaseDao(**test1_config)
    105     test1_struts = test1_dao.select_database_struts()
    106     
    107     test2_dao = BaseDao(**test2_config)
    108     test2_struts = test2_dao.select_database_struts()
    109 
    110     main(test2_struts, test1_struts)
    View Code

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

      如果有感兴趣一起学习、讨论Python的可以加QQ群:626787819,有啥意见或者建议的可以发我邮箱:410093793@qq.com。

  • 相关阅读:
    Nginx进程信号管理
    Nginx配置缓存服务器
    访问Nginx显示目录
    kubeadm快速安装k8s
    《构建之法》读书笔记(一)
    Android Studio连接SQLite数据库与SQLite Studio实时同步的实现
    关于sqlite数据库与sqlite studio
    AS之去掉顶部标题栏
    今日学习
    AS之AlertDialog使用
  • 原文地址:https://www.cnblogs.com/rcddup/p/7141248.html
Copyright © 2011-2022 走看看