Python编写PostgreSQL数据库结构比

本文介绍了使用Python编写的PostgreSQL数据库结构对比程序,包括表结构、视图、函数和外部表的比较,以及生成差异更新脚本的功能。通过展示代码目录结构、配置文件和核心源代码,详细阐述了如何实现数据库的全面比对和升级操作。
摘要由CSDN通过智能技术生成

前言
随着PostgreSQL数据库越来越被广泛的应用,它的优势也逐渐被广泛的认可。但针对该数据库的工具却较少。由于工作需要,经常有对PostgreSQL数据库进行比对生成升级脚本的需求,故本人使用python编写了一个PostgreSQL数据库比对程序和大家共同交流学习。(文章的最后将提供源程序的下载地址)

一、功能介绍
比对程序实现了对两个数据库的结构进行比较并生成差异化更新脚本。
比对的内容如下:
1、表结构比比较:包含表、字段、字段注释、序列、约束、索引、触发器的比较。
2、视图比较:包含普通视图和物化视图的比较,并生成创建或者修改脚本。
3、函数比较:函数(存储过程)的比较,并生成新建或者修改脚本。
4、外部表比较:外部表进行比较,并生成新建或者修改脚本。

二、代码目录结构
1、下图为代码的目录结构展开截图及说明


2、下面为程序运行界面

三、核心源代码解析
1、bin目录下main.py

import core.schemaSync as core
import PySimpleGUI as sg
import time

# 定义需要执行的任务
my_list = ['表', '视图', '函数', '外部表']
# 定义进度条
progressbar = [[sg.ProgressBar(len(my_list), orientation='h', size=(51, 10), bar_color=('#f47920', '#46485f'), key='progressbar')]]
# 定义输出窗口尺寸
output_win = [[sg.Output(size=(78, 20))]]
# 窗口布局
layout = [[sg.Frame('执行进度', layout=progressbar)],
          [sg.Frame('输出信息', layout=output_win)],
          [sg.Submit('开 始'), sg.Cancel('退 出')]]
window = sg.Window('PostgreSQL数据库比较程序', layout)
progress_bar = window['progressbar']
while True:
    event, values = window.read(timeout=10)
    # 点击按钮退出
    if event == '退 出' or event is None:
        break
    # 点击按钮开始
    elif event == '开 始':
        file_name = ''
        # 循环要执行的任务
        for i, item in enumerate(my_list):
            if i == 0:
                print(item + ' 比对开始...')
                file_name = core.sync_table()
                print(item+' 比对完成!(含字段及注释、序列、约束、索引、触发器的比对)\n')
            if i == 1:
                print(item + ' 比对开始...')
                core.sync_view()
                print(item+' 比对完成!(含普通视图、物化视图)\n')
            if i == 2:
                print(item + ' 比对开始...')
                core.sync_function()
                print(item+' 比对完成!\n')
            if i == 3:
                print(item + ' 比对开始...')
                core.sync_foreign_table()
                print(item+' 比对完成!\n')
            time.sleep(1)
            # 更新进度条
            progress_bar.UpdateBar(i + 1)
        # 输出生成脚本的路径
        print('差异脚本路径:' + file_name)
 
2、conf目录下config.ini

[database]
#postgre_src
pg_host_src=192.168.10.70
pg_port_src=5432
pg_user_src=postgres
pg_pwd_src=***
pg_db_src=data_use

#postgre_dst
pg_host_dst = 192.168.10.71
pg_port_dst=5432
pg_user_dst=postgres
pg_pwd_dst=***
pg_db_dst=data_use

[common]
output_file_name=updScript.sql
log_dir=

 
3、core目录下的schemaSync.py

import os
from util.connDB import getConn
from util.logger import log
import sqlConfig
from util.commonFunction import commonFunction
import util.readConfig as readConfig


# 对比表、字段及注释、序列、约束、索引、触发器
def sync_table():
    try:
        # 获取源数据库连接
        global sourceConn,targetConn,sourceCursor,targetCursor
        sourceConn, sourceCursor = getConn('postgre_src')
        # 获取目标数据库连接
        targetConn, targetCursor = getConn('postgre_dst')
        # 求源和目标表的差集
        sourceCursor.execute(sqlConfig.selectTable)
        targetCursor.execute(sqlConfig.selectTable)
        sourceTable = sourceCursor.fetchall()
        targetTable = targetCursor.fetchall()
        tableReslut=set(sourceTable) - set(targetTable)
        tableName = ''
        for item in tableReslut:
            tableName=tableName+','+item[0]
        tableName=str(tableName[1:])
        # print(tableName)
        # 导出新增表
        cf=commonFunction()
        file_name=cf.dumpTable(tableName)

        # 对比序列
        # 求源和目标序列的差集
        sourceCursor.execute(sqlConfig.selectSequence % tableName.replace(",", "','"))
        targetCursor.execute(sqlConfig.selectSequence % tableName.replace(",", "','"))
        sourceSequence = sourceCursor.fetchall()
        targetSequence = targetCursor.fetchall()
        sequenceReslut = list(set(sourceSequence) - set(targetSequence))
        # print(sequenceReslut)
        for itemReslut in sequenceReslut:
            sequence_name = itemReslut[0]
            if (sequence_name != ''):
                str_sql = "create sequence " + sequence_name + ";"
                # print(str_sql)
                # 追加写入到指定文件
                with open(file_name, mode='a+', encoding="utf-8") as w:
                    w.write("-- Sequence compares" + "\n" + str_sql + "\n")

        # 对比字段
        # 求源和目标字段的差集
        sourceCursor.execute(sqlConfig.selectColumn % tableName.replace(",","','"))
        targetCursor.execute(sqlConfig.selectColumn % tableName.replace(",","','"))
        sourceColumn = sourceCursor.fetchall()
        targetColumn = targetCursor.fetchall()
        columnReslut = list(set(sourceColumn) - set(targetColumn))
        # 对列表根据表名称和字段名称排序
        columnReslut.sort()
        #print(columnReslut)
        if(len(columnReslut)>0):
            # 追加写入到指定文件
            with open(file_name, mode='a+', encoding="utf-8") as w:
                w.write("\n--\n-- Column compares\n--\n" + "\n")
        # 外循环,对比后的差集字段
        for itemReslut in columnReslut:
            table_name = itemReslut[0]
            column_name = itemReslut[1]
            column_type = itemReslut[2]
            column_default = itemReslut[3]
            description = itemReslut[4]
            # print(itemReslut[0],itemReslut[1],itemReslut[2],itemReslut[3],itemReslut[4],itemReslut[5])
            # 内循环,目标库的字段
            column_exists = 0
            for itemTarget in targetColumn:
                # 表名称和字段名称相等
                if(table_name == itemTarget[0] and column_name == itemTarget[1]):
                    column_exists = column_exists+1
             

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值