使用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等信息連接你的數據庫
代碼中主要有兩個功能:
- 找出兩個數據庫的表的差集和具體表字段的差集
- 導出表的差集的表結構創建sql語句
可以在此基礎上完善補充的功能:
- 去掉生成xx.sql的註解
- 導出相同表的表字段的差異sql部分
參考鏈接: