postgreSQL 數據庫字典導出工具

為滿足項目驗收文檔需求,開發了一個基于Python的PostgreSQL數據字典導出工具。

廢話不多說,先分享一下

軟件截圖

數據字典文件樣式,文件格式為docx

軟件源碼

基于python開發,

import tkinter as tk
from tkinter import ttk, messagebox
from PIL import Image, ImageTk
import psycopg2
from docx import Documentclass ProfessionalDBConnector:def __init__(self, root):self.root = rootself.root.title("數據字典導出工具 v1.0")self.root.geometry("500x550")self.root.resizable(False, False)self.root.configure(bg="#f5f5f5")# 加載logotry:self.logo_img = ImageTk.PhotoImage(Image.open("logo.png").resize((100, 40)))logo_label = tk.Label(root, image=self.logo_img, bg="#f5f5f5")logo_label.grid(row=0, column=0, columnspan=2, pady=(20, 30))except:title_label = tk.Label(root, text="PostgreSql數據字典導出工具", font=("微軟雅黑", 16, "bold"), bg="#f5f5f5", fg="#333")title_label.grid(row=0, column=0, columnspan=2, pady=(20, 30))# 輸入框樣式style = ttk.Style()style.configure("TLabel", background="#f5f5f5", font=("微軟雅黑", 10))style.configure("TEntry", font=("微軟雅黑", 10), padding=5)style.configure("TButton", font=("微軟雅黑", 10, "bold"), padding=5)# 輸入框標簽fields = ["主機:", "端口:", "用戶名:", "密碼:", "數據庫名:"]self.entries = {}for i, field in enumerate(fields):ttk.Label(root, text=field).grid(row=i + 1, column=0, padx=20, pady=5, sticky="e")entry = ttk.Entry(root)if field == "密碼:":entry = ttk.Entry(root, show="*")entry.grid(row=i + 1, column=1, padx=10, pady=5, sticky="ew")self.entries[field[:-1]] = entry# 連接按鈕self.connect_test_btn = tk.Button(root, text="測試連接", command=self.connect_test_db,# 設置按鈕的背景顏色為綠色bg="#4CAF50",# 設置按鈕的前景(文本)顏色為白色fg="white",# 設置按鈕在按下狀態時的背景顏色activebackground="#45a049",# 設置按鈕文本的字體和樣式font=("微軟雅黑", 10, "bold"),# 設置按鈕內部x軸方向的填充padx=15,# 設置按鈕內部y軸方向的填充pady=5,# 設置按鈕的邊框樣式為平的,無邊框relief="flat",# 設置按鈕的邊框寬度為0,與relief參數共同作用實現無邊框效果bd=0,# 設置鼠標懸停在按鈕上時的光標樣式為手型cursor="hand2")# 創建導出按鈕組件# 該按鈕用于觸發導出數據庫功能,其具體功能通過command參數關聯的self.export_db方法實現self.export_dictionary_btn = tk.Button(root, text="導出數據字典", command=self.export_dictionary,bg="#4CAF50",fg="white",activebackground="#45a049",font=("微軟雅黑", 10, "bold"),padx=15,pady=5,relief="flat",bd=0,cursor="hand2")self.connect_test_btn.grid(row=6, column=0, columnspan=2, pady=20)self.export_dictionary_btn.grid(row=7, column=0, columnspan=2, pady=20)# 底部署名和版權信息footer_frame = tk.Frame(root, bg="#e0e0e0")footer_frame.grid(row=9, column=0, columnspan=2, sticky="ew", pady=(10, 0))tk.Label(footer_frame, text="? 2025 數據庫工具 | 開發人員: guozs",bg="#e0e0e0", fg="#666", font=("微軟雅黑", 8)).pack(pady=5)# 配置網格權重root.columnconfigure(1, weight=1)def connect_test_db(self):try:conn = self.getConn()cursor = conn.cursor()cursor.execute("select version()")result = cursor.fetchall()if result is not None:messagebox.showinfo("連接成功", f"數據庫版本:{result}")conn.close()else:messagebox.showinfo("連接失敗")except Exception as e:messagebox.showerror("連接失敗", f"錯誤: {str(e)}")def getConn(self):self.database = self.entries["數據庫名"].get()if self.database == "":self.database = "abc"self.user = self.entries["用戶名"].get()if self.user == "":self.user = "postgres"self.password = self.entries["密碼"].get()if self.password == "":self.password = "123456"self.host = self.entries["主機"].get()if self.host == "":self.host = "127.0.0.1"self.port = self.entries["端口"].get()if self.port == "":self.port = "5432"conn = psycopg2.connect(database=self.database,user=self.user,password=self.password,host=self.host,port=int(self.port))return conndef export_dictionary(self):doc = Document()try:self.exportTableInfoToDocx(doc)messagebox.showinfo("成功", f"數據字典已導出")except Exception as e:messagebox.showerror("失敗", f"錯誤: {str(e)}")def getTableList(self):conn = self.getConn()cur = conn.cursor()query = '''select A.schemaname,A.relname,obj_description ( B.relfilenode, 'pg_class' ) AS tablenamefrom pg_stat_user_tables as A,pg_class as BWHERE B.relname = A.relname  ORDER BYA.schemaname,A.relname'''cur.execute(query)tableList = cur.fetchall()conn.commit()cur.close()conn.close()return tableListdef getTableColumnByTableName(self, tableName):conn = self.getConn()cur = conn.cursor()tableName = "'" + tableName + "'"query = f'''SELECTd.relname AS relname,obj_description ( relfilenode, 'pg_class' ) AS tablename,attname AS field,CASEtypname WHEN '_bpchar' THEN'char' WHEN '_varchar' THEN'varchar' WHEN '_date' THEN'date' WHEN '_float8' THEN'float8' WHEN '_int4' THEN'int4' WHEN '_int8' THEN'int8' WHEN '_interval' THEN'interval' WHEN '_numeric' THEN'numeric' WHEN '_float4' THEN'float4' WHEN '_int2' THEN'smallint' WHEN '_text' THEN'text' WHEN '_time' THEN'time' WHEN '_timestamp' THEN'timestamp' WHEN '_timestamptz' THEN'timestamptz' END AS TYPE,CASEtypname WHEN '_bpchar' THENatttypmod - 4 WHEN '_varchar' THENatttypmod - 4 WHEN '_numeric' THEN( atttypmod - 4 ) / 65536 ELSE attlen END AS LENGTH,CASEtypname WHEN '_numeric' THEN( atttypmod - 4 ) % 65536 ELSE 0 END AS xs,CASEWHEN b.attnotnull = 't' THEN'不能為空' ELSE'' END AS NOTNULL,CASEWHEN ( SELECT COUNT ( * ) FROM pg_constraint WHERE conrelid = b.attrelid AND conkey [ 1 ]= attnum AND contype = 'p' ) > 0 THEN'主鍵' ELSE'' END AS zj,col_description ( b.attrelid, b.attnum ) AS COMMENT FROMpg_stat_user_tables AS A,pg_class AS d,pg_tables AS P,pg_attribute AS b,pg_type AS C WHEREA.relid = b.attrelid AND b.attnum > 0 AND b.atttypid = C.typelem AND substr( typname, 1, 1 ) = '_' AND P.tablename = d.relname AND d.relname = A.relname AND A.relname NOT LIKE'c%' AND A.relname NOT LIKE'S%' AND P.tablename = {tableName}ORDER BYA.schemaname,A.relname,attnum'''cur.execute(query)data = cur.fetchall()conn.commit()cur.close()conn.close()return datadef exportTableInfoToDocx(self, doc):tableList = self.getTableList()p = doc.add_paragraph('')table_explain = "數據字典"p.add_run(table_explain, style="Heading 1 Char")p = doc.add_paragraph('')table_explain = "數據庫名:%s" % (self.database)p.add_run(table_explain, style="Heading 1 Char")p = doc.add_paragraph('')table_explain = "表匯總"p.add_run(table_explain, style="Heading 1 Char")table = doc.add_table(rows=1, cols=3)table.style = 'TableGrid'hdr_cells = table.rows[0].cellshdr_cells[0].text = '模式'hdr_cells[1].text = '表名'hdr_cells[2].text = '表注釋'for tableInfo in tableList:new_cells = table.add_row().cellsnew_cells[0].text = tableInfo[0]new_cells[1].text = tableInfo[1]# 判斷注釋是否為空new_cells[2].text = getStr(tableInfo[2])  # if tableInfo[2] is None else tableInfo[2]p = doc.add_paragraph('')p = doc.add_paragraph('')p = doc.add_paragraph('')table_explain = "表詳情"p.add_run(table_explain, style="Heading 1 Char")try:for tableInfo in tableList:tableName = tableInfo[1]tableComment = getStr(tableInfo[2])p = doc.add_paragraph('')table_explain = "表名:%s, 注解:%s" % (tableName, getStr(tableComment))  # tableName + ",注解:" + getInfo(tableComment) + ",對應數據庫的表:"p = doc.add_paragraph('')p.add_run(table_explain, style="Heading 1 Char")table = doc.add_table(rows=1, cols=5)table.style = 'TableGrid'hdr_cells = table.rows[0].cellshdr_cells[0].text = '字段名'hdr_cells[1].text = '字段類型'hdr_cells[2].text = '允許為空'hdr_cells[3].text = 'PK'hdr_cells[4].text = '字段說明'tableColumnList = self.getTableColumnByTableName(tableInfo[1])for tableColumn in tableColumnList:new_cells = table.add_row().cellsnew_cells[0].text = getStr(tableColumn[2])new_cells[1].text = getStr(tableColumn[3])new_cells[2].text = getStr(tableColumn[6])new_cells[3].text = getStr(tableColumn[7])new_cells[4].text = getStr(tableColumn[8])except Exception as e:messagebox.showerror("失敗", f"錯誤: {str(e)}")p = doc.add_paragraph('')doc.save('./' + self.database + '_數據字典.docx')def getStr(param):if param is None:return ""else:return paramif __name__ == "__main__":root = tk.Tk()app = ProfessionalDBConnector(root)root.mainloop()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/86379.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/86379.shtml
英文地址,請注明出處:http://en.pswp.cn/web/86379.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【AI解析】 CppNumericalSolvers:一個現代化的 C++17 純頭文件優化庫 示例代碼解析

一個輕量級僅頭文件的 C17 庫,提供針對(無)約束非線性函數及表達式模板的數值優化方法 https://github.com/PatWie/CppNumericalSolvers CppNumericalSolvers 庫 include 目錄下的文件及其功能說明 根目錄文件 文件名功能說明function.h(主函…

第3篇:Gin的請求處理——獲取客戶端數據(Gin文件上傳,接收JSON數據)

引言:Context是Gin的"瑞士軍刀" 在Gin框架中,Context就像一把多功能的瑞士軍刀,封裝了所有與請求相關的操作。新手開發者常犯的錯誤是只把它當作參數傳遞的工具,卻忽略了它強大的數據處理能力。 想象一個場景&#xf…

啟動hardhat 項目,下載依賴的npm問題

Windows 環境 Hardhat 依賴安裝問題排查指南 🚨 問題描述 在 Windows 環境下安裝 Hardhat 項目依賴時,遇到以下錯誤: npm ERR! code ETARGET npm ERR! notarget No matching version found for nomicfoundation/edr^0.11.1. npm ERR! nota…

大數據里的拉鏈表:數據版本管理的時間膠囊

哈嘍各位數據打工人~今天咱們來聊聊大數據領域一個超實用的神器 ——拉鏈表!聽起來像時尚單品?NoNoNo,它可是數據倉庫里管理歷史數據的寶藏工具? 就算你是剛入門的小白也能輕松聽懂,咱們全程少玩比喻多講人話&#xf…

docker執行yum報錯Could not resolve host: mirrorlist.centos.org

解決辦法: -- 依次執行以下命令cd /etc/yum.repos.d/sed -i s|#baseurlhttp://mirror.centos.org|baseurlhttp://vault.centos.org|g /etc/yum.repos.d/CentOS-*sed -i s/mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOS-*yum update -yecho "export LC_ALL…

JVM OutOfMemoryError原因及排查解決方案

在Java后端開發中,java.lang.OutOfMemoryError(簡稱OOM)是一個令開發者頭疼的異常。它通常意味著Java虛擬機(JVM)在嘗試分配新對象時,發現堆中沒有足夠的空間來容納該對象,或者其他內存區域耗盡…

吐槽之前后端合作開發

大家好,我是佳瑞,從事10多年java開發程序員,爆照一張,存活互聯網。 也做過vue開發自己的網站,覺得前端是真比后端開發輕松很多,就是畫頁面調樣式,打包發布,當然不說是高級源碼修改…

Oracle LogMiner日志分析工具介紹

Oracle LogMiner日志分析工具介紹 LogMiner使用須知LogMiner字典使用online catalog作為日志挖掘字典使用redo日志文件作為日志挖掘字典使用文本文件作為日志挖掘字典Redo日志文件自動獲取日志文件手動獲取日志文件啟動LogMiner進行分析V$LOGMNR_CONTENTS視圖LogMiner使用須知 …

2-4 Dockerfile指令(個人筆記)

以下指令基于 ubuntu Dockerfile整體示例 From:設置基礎鏡像 Maintainer :鏡像維護者信息 COPY/ADD:添加本地文件到鏡像中 WorkDir:設置工作目錄 Run:執行命令 CMD/EntryPoint:配置容器啟動時執行的命令

Redis主從架構哨兵模式

文章目錄 概述一、主從搭建實例二、主從同步原理三、哨兵架構3.1、搭建哨兵架構3.2、演示故障恢復3.3、哨兵日志 概述 在生產環境下,Redis通常不會單機部署,為了保證高可用性,通常使用主從模式或集群架構,同時也面臨著一些問題&am…

基于深度學習yolov5的安全帽實時識別檢測系統

摘要:在現代工業和建筑行業中,確保員工的安全是至關重要的一環。安全帽作為一項基礎的個人防護設備,對于降低頭部受傷的風險發揮著關鍵作用。然而,確保工作人員在施工現場始終正確佩戴安全帽并非易事。傳統的人工檢查方法不僅效率…

GitLab 18.1 發布 Runner、無效的個人訪問令牌查看等功能,可升級體驗!

GitLab 是一個全球知名的一體化 DevOps 平臺,很多人都通過私有化部署 GitLab 來進行源代碼托管。極狐GitLab 是 GitLab 在中國的發行版,專門為中國程序員服務。可以一鍵式部署極狐GitLab。 學習極狐GitLab 的相關資料: 極狐GitLab 官網極狐…

量子計算與AI融合 - 企業級安全威脅應對

量子計算(QC)雖帶來萬億級市場機遇(2025-2035年),但潛藏重大安全風險:可能破解現有加密系統,催生"現在竊取,未來解密"攻擊。美國NIST已啟動后量子加密標準,但技…

Excel:filter函數實現動態篩選的方法

filter的意思是“過濾、篩選”,動態篩選,FILTER()函數可以將對篩選區域內容,并將結果自動溢出生成一個新區域,以下是函數的使用方法: (一)情景:給定兩列數據,我需要根據…

蘭洋科技上合組織論壇發表專題分享,全球液冷布局引領綠色算力未來

2025年6月17-19日,中國—上海合作組織數字技術合作發展論壇在新疆克拉瑪依市舉辦。作為第四次上海合作組織成員國信息通信技術發展部門負責人會議的配套會議,論壇以“數字化轉型助力可持續發展,數字包容促進上合共同繁榮”為主題,…

LED-Merging: 無需訓練的模型合并框架,兼顧LLM安全和性能!!

摘要:對預訓練大型語言模型(LLMs)進行微調以適應特定任務,會帶來巨大的計算和數據成本。雖然模型合并提供了一種無需訓練的解決方案,用于整合多個特定任務的模型,但現有方法存在安全性與效用性之間的沖突&a…

火山引擎向量數據庫 Milvus 版正式開放

資料來源:火山引擎-開發者社區 隨著AI技術的不斷演進發展,非結構化數據也迎來了爆發式的增長。Milvus作為一款為大規模向量相似度搜索和 AI 應用開發設計的開源向量數據庫系統,目前已在業界占據領導地位。當前 Milvus 已經被 5,000 家企業所…

SQL SERVER存儲過程

什么是存儲過程 SQL 存儲過程(Stored Procedure)是一個在數據庫中預編譯并存儲的一組 SQL 語句。它們可以包含查詢、插入、更新、刪除等數據庫操作,甚至包括控制流語句(如條件判斷、循環等)。存儲過程可以通過調用來執…

Lombok注解 - 提高Java開發效率

01 繁瑣編碼 初入 Java 開發領域時,編寫實體類的瑣碎經歷想必各位都深有感觸。 每當創建一個實體類,鋪天蓋地的 getter、setter、toString 方法接踵而至,手指在鍵盤上頻繁敲擊,酸痛不已。 而 Lombok 這一神器的出現&#xff0c…

Linux修改uboot啟動延時方法詳細攻略,觸覺智能RK3568開發板演示

修改uboot延時 首先查找defconfig文件 ./build.sh uboot #通過編譯日志查看使用的defconfig文件ls u-boot/configs/*3568* #在SDK根目錄下執行該操作 如圖標注處就是所使用的u-boot配置文件。 然后修改延時數: vim u-boot/configs/rk3568_defconfig 將CONFIG_BOO…