使用Python 比較mysql數據庫中兩個數據庫的表結構,並導出差異部分的表結構

使用Python比較數據庫表結構和表字段

       廢話不多說,直接上代碼

# -*- coding: UTF-8 -*- 
# @Time    : 2018/8/31 8:23
# @Author  : wuming.wang
# @Email   : [email protected]
# @File    : DiffDatabase.py
# @Software: PyCharm

import MySQLdb
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

base_dir = os.path.abspath(os.path.dirname(__file__))


class Diff:
    def __init__(self):
        self.test_host = '192.168.**.***'
        self.test_user_name = '****'
        self.test_password = '****'
        self.test_port = '3306'
        self.test_dbname = '****'

        self.online_host = '192.***.**.**'
        self.online_user_name = '**'
        self.online_password = '***'
        self.online_port = '3306'
        self.online_dbname = '*****'

    def get_data(self, env, sql):
        if env == "test":
            conn = MySQLdb.connect(self.test_host, self.test_user_name, self.test_password, self.test_dbname,
                                   charset="utf8")
        else:
            conn = MySQLdb.connect(self.online_host, self.online_user_name, self.online_password, self.online_dbname,
                                   charset="utf8")

        cur = conn.cursor()
        cur.execute(sql)

        results = cur.fetchall()  # 搜取所有結果
        cur.close()
        conn.close()
        return results

    # 把返回的嵌套元素轉換爲列表
    def to_list(self, result):
        r_list = []
        for t in result:
            r_list.append(t[0])
        return r_list

    # test_table 裏面有的 online_table沒有
    def comp(self, test_table, online_table):
        ret = [i for i in test_table if i not in online_table]
        return ret

    # test_table online_table 都有的
    def both_list(self, L1, L2):
        both = [i for i in L1 if i in L2]
        return both

    def result(self, test, online):
        test_have = self.comp(test, online)
        online_have = self.comp(online, test)

        if len(test_have) + len(online_have) != 0:
            print "test環境有的table,online環境沒有: \r\n"

            for i in test_have:
                print "  ", i

            print "\r"

            print "online環境有的table,test環境沒有: \r\n"
            for i in online_have:
                print "  ", i

    def column_result(self, table_name, test, online):
        test_have = self.comp(test, online)
        online_have = self.comp(online, test)

        if len(test_have) + len(online_have) != 0:
            print "\r"
            print "    ", table_name, "表:test環境有的字段,online環境沒有: \r\n"
            for i in test_have:
                print "         ", i
            print "\r"
            print "    ", table_name, "表:online環境有的字段,test環境沒有: \r\n"
            for i in online_have:
                print "         ", i

    def export_table_structure(self, env, table_name):
        mysqldump_commad_params = {}
        mysqldump_commad_params['dumpcommad'] = 'mysqldump --no-data'
        if env == "test":
            mysqldump_commad_params['server'] = self.test_host
            mysqldump_commad_params['user'] = self.test_user_name
            mysqldump_commad_params['password'] = self.test_password
            mysqldump_commad_params['port'] = self.test_port
            mysqldump_commad_params['db'] = self.test_dbname
        else:
            mysqldump_commad_params['server'] = self.online_host
            mysqldump_commad_params['user'] = self.online_user_name
            mysqldump_commad_params['password'] = self.online_password
            mysqldump_commad_params['port'] = self.online_port
            mysqldump_commad_params['db'] = self.online_dbname

        file_name = """%s_have_%s.sql""" % (env, table_name)
        path = os.path.join(base_dir, 'sql', env, file_name)

        mysqldump_commad_sql = """%s -h%s -u%s -p%s -P%s %s %s > %s""" % (
            mysqldump_commad_params['dumpcommad'],
            mysqldump_commad_params['server'],
            mysqldump_commad_params['user'],
            mysqldump_commad_params['password'],
            mysqldump_commad_params['port'],
            mysqldump_commad_params['db'],
            table_name,
            path
        )

        # 必須切換到創建sql的文件夾下,才能執行命令!!!
        sql_file_path = os.path.join(base_dir, 'sql', env)
        if not os.path.exists(sql_file_path):
            os.makedirs(sql_file_path)

        os.chdir(sql_file_path)
        result = os.system(mysqldump_commad_sql)

        if result == 0:
            print """----------- 導出 %s 表結構成功!------------""" % (table_name)
        else:
            print """----------- 導出 %s 表結構失敗!------------""" % (table_name)

            # print mysqldump_commad_sql

    def drop_more_comment(self,file_path):
        os.chdir()


if __name__ == '__main__':
    diff = Diff()

    test_table_list = diff.to_list(diff.get_data('test', "show tables"))
    online_table_list = diff.to_list(diff.get_data('online', "show tables"))
    both_have_t = diff.both_list(test_table_list, online_table_list)

    print "-----------------  比較兩個database的table差異  begin --------------------------"
    print "\r"
    # 調用比較結果函數
    diff.result(test_table_list, online_table_list)
    print "\r"
    print "-----------------  比較兩個database的table差異  end --------------------------"

    print "\r\n"
    print "共有表個數:", both_have_t.__len__()
    print "共有表:", both_have_t
    print "\r"

    print "-----------------  比較共有表的字段差異  begin --------------------------"
    print "\r"

    for i in range(0, len(both_have_t)):
        test_field_sql = "SELECT column_name FROM information_schema.columns WHERE Table_name= '%s' and table_schema = '%s'" % (
            both_have_t[i], diff.test_dbname)
        test_field = diff.to_list(diff.get_data("test", test_field_sql))
        online_field_sql = "SELECT column_name FROM information_schema.columns WHERE Table_name= '%s' and table_schema = '%s'" % (
            both_have_t[i], diff.online_dbname)
        online_field = diff.to_list(diff.get_data("online", online_field_sql))
        print i + 1, both_have_t[i]
        diff.column_result(both_have_t[i], test_field, online_field)
    print "\r"
    print "-----------------  比較共有表的字段差異  end --------------------------"

    print "\r\n"
    print "-----------------  導出 表結構 begin  -------------------------------"
    # 導出表結構sql
    print "-----------------  導出 test 環境有的表,而 online 環境沒有的表 ----------"
    test_have = diff.comp(test_table_list, online_table_list)
    for table_name in test_have:
        diff.export_table_structure('test', table_name)
    print "\r\n"
    print "-----------------  導出 online 環境有的表,而 test 環境沒有的表 ----------"
    online_have = diff.comp(online_table_list, test_table_list)
    for table_name in online_have:
        diff.export_table_structure('online', table_name)
    print "-----------------  導出 表結構 end  -------------------------------"

這裏你需要設置你要比較的兩個數據庫的host,user,password等信息連接你的數據庫

代碼中主要有兩個功能:

  1. 找出兩個數據庫的表的差集和具體表字段的差集
  2. 導出表的差集的表結構創建sql語句

可以在此基礎上完善補充的功能:

  1. 去掉生成xx.sql的註解
  2. 導出相同表的表字段的差異sql部分

參考鏈接:

  1. https://www.cnblogs.com/aiyr/p/6735154.html
  2. https://blog.csdn.net/dm1314oooooooo/article/details/72818559
  3. https://www.linuxidc.com/Linux/2018-03/151390.htm
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章