自動化生成數據庫文檔,簡單的3個步驟即可完成,了解一下。
1 前言
平時工作中,大家應該都會遇到需要導出數據庫說明文檔(也叫數據字典)的情況,即把各數據表的字段信息整理成一個個的表說明,然后用 excel/word/html/md 等文檔格式進行保存。很多小伙伴還在用原始的手工方式,復制粘貼數據庫的字段說明(名稱、類型、長度、注釋等),不得不說這種方式效率實在太低。作為程序員,能用編程解決的問題,就不是問題。下面介紹的方法很簡單,只需要3個步驟。本文將對這3個步驟使用 python 進行編碼實現,把數據表信息說明輸出到 excel 文檔中。因此,主要包含以下內容:
- 生成數據庫文檔的3步驟說明
- 獲取數據庫表元信息
- 獲取數據表列的元信息
- 生成數據庫說明 excel 文檔
- (可選)設置 excel 文檔格式
2 生成數據庫說明文檔的3步驟
由於數據庫都會保存相應的元數據信息(即描述數據庫、數據表、數據字段本身的信息,如表名,字段表、類型等等),因此,總的來說,生成數據庫說明文檔的思路很簡單,分為3步:
- 1)根據數據庫名,從數據庫中獲取數據表元信息,主要是表名,表注釋等
- 2)根據數據表名,獲取數據字段的元信息,主要是字段名、字段類型、是否可空、字段注釋等
- 3)根據元數據信息生成文檔
根據這個思路,把這3個步驟通過編碼即可自動生成文檔。獲取元數據信息,各種數據庫會有不同的查詢語句,具體可以查詢相關官方文檔,下面簡單列一下 mysql 及 oracle 的:
# mysql 查詢表信息及字段信息
SELECT * FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = %db_name%
SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = %db_name% AND TABLE_NAME = %table_name%
# oracle 查詢表信息及字段信息
SELECT * FROM all_tables WHERE where owner= %db_name%
SELECT * FROM all_COL_COMMENTS WHERE owner = %db_name% and TABLE_NAME=%table_name%
實現方式也可以根據各人喜歡的編程語言來實現。在本文中,以 MySQL 為例,使用 python 編程實現,把數據信息輸出到 excel 文檔(具體 excel 操作,可參考我上一篇文章《 Python 處理 Excel 文件》)。輸出效果如下所示:
下面就跟着我進行實現吧。
3 獲取數據庫表元信息
3.1 客戶端 pymysql 基本使用
使用 python 進行 MySQL 讀寫操作,使用的是 pymysql,讀者可以訪問它的官方文檔了解它的安裝和使用。簡單來說,對數據庫進行讀數據,需要以下幾步:
- 連接數據庫:
connect
- 獲取讀數據的游標( cursor ):
connection.cursor()
- 執行 SQL 語句獲取數據:
cursor.execute(sql,args)
,cursor.fetchall()
,cursor.fetchone()
,cursor.fetchmany()
- 關閉游標和連接:
connection.close()
- 獲取正在使用的工作表:
workbook.active
,cursor.close()
因此,我們在類的初始化( __init__
)和關閉(__del__
)時,進行數據庫連接和關閉操作。代碼如下:
def __init__(self, host, port, user, password, db_name, charset):
# 初始化數據庫操作
self.db = pymysql.connect(host=host, port=port, user=user,password=password, database=db_name, charset=charset)
self.cursor = self.db.cursor()
def __del__(self):
# 關閉數據庫連接
self.db.close()
self.cursor.close()
3.2 獲取數據庫表元信息
根據上面說的 pymysql 的基本操作,只需要執行查詢數據表元信息的 SQL 即可。前面已經提到,MySQL 的查詢表元信息的 SQL 語句是SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = %db_name%
,而我們只需要表名及表注釋即可。因此實現如下:
def get_table_info(self, db_name):
# 獲取數據表信息
sql = '''SELECT table_schema, table_name, table_comment FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = %s order by table_name'''
params = [db_name]
# 查詢數據
self.cursor.execute(sql, params)
return self.cursor.fetchall()
此函數功能:傳入數據庫名,返回所有表信息。
4 獲取數據表字段的元信息
獲取到表信息后,同樣的道理,需要遍歷每一個表,根據表名獲取每個表的字段信息。前面已經到,MySQL 獲取表的字段是查詢表 information_schema.COLUMNS
即可,而對於字段信息, 我們主要關注字段名、字段類型、 是否允許為空、字段的注釋描述等信息。代碼如下:
def get_table_column_info(self, database_name, table_name):
# 獲取數據表列信息
params = [database_name, table_name]
sql = '''SELECT
TABLE_SCHEMA AS '庫名',TABLE_NAME AS '表名',
COLUMN_NAME AS '列名',ORDINAL_POSITION AS '列的排列順序',
COLUMN_DEFAULT AS '默認值',IS_NULLABLE AS '是否為空',
DATA_TYPE AS '數據類型',CHARACTER_MAXIMUM_LENGTH AS '字符最大長度',
NUMERIC_PRECISION AS '數值精度(最大位數)',NUMERIC_SCALE AS '小數精度',
COLUMN_TYPE AS '列類型',COLUMN_COMMENT AS '注釋'
FROM information_schema.`COLUMNS`
WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s
ORDER BY TABLE_NAME, ORDINAL_POSITION'''
# 查詢數據
self.cursor.execute(sql, params)
return self.cursor.fetchall()
此函數功能,根據數據庫名及表名,獲取此表的字段信息。
5 生成 excel 文檔
5.1 輸出表字段信息到 excel 文檔
對於 excel 的操作,我們使用 openpyxl 進行讀寫操作,具體 excel 操作,可參考我上一篇文章《 Python 處理 Excel 文件》。而現在我們需要實現的功能是把每個表的字段信息,以表格的方式寫入到 excel 表中,並按字段名、允許為空、字段類型、字段描述進行輸出。
還有一點就是,我們經常在設計表的的過程中,基本都會有一些公共的字段,比如 id ,創建時間、創建人、修改時間、修改人等,這些我們在導出字典時,可以選擇過濾掉。因此,使用如下代碼進行實現:
def create_file(self, file_path):
# 獲取文件,若文件不存在則創建,存在則刪除后重新創建
if os.path.exists(file_path):
os.remove(file_path)
wb = Workbook()
wb.save(file_path)
def save_column_info_to_excel(self, table_name, table_comment, column_info, file_path, col_names_skip):
# 寫入表信息到excel文件
workbook = openpyxl.load_workbook(file_path)
# 根據下標獲取(下標從0開始)
sheet = workbook.worksheets[0]
row_data = [table_name]
if table_comment:
row_data = [table_name + "(" + table_comment + ")"]
sheet.append(row_data)
rurrent_max_row = sheet.max_row
# 空行分隔
sheet.insert_rows(rurrent_max_row)
# 列名
col_name_data = ["字段名", "允許為空", "類型", "字段描述"]
sheet.append(col_name_data)
for row in column_info:
# 需要過濾的
if col_names_skip and row[2].lower() in col_names_skip:
print("#" * 10, "跳過此字段:", row[2])
continue
print(row[2] + "," + row[5] + "," + row[10] + "," + row[11])
row_data = [row[2], row[5], row[10], row[11]]
sheet.append(row_data)
# 保存文檔
workbook.save(file_path)
此處包含兩個函數,create_file
功能主要是創建文檔,若文檔存在則先刪除。save_column_info_to_excel
功能是根據表字段信息及需要過濾的字段名,使用 for 語句按行輸出到 excel 中,輸出過程中,若有需要過濾的字段則跳過,最后把文檔保存到指定的路徑中。
5.2 把各功能連接起來
前面已經實現數據庫表元信息獲取、數據表字段元信息獲取及字段信息輸出到 excel 文檔三個功能。現在把這三個功能連接起來,就可以形成完整的數據庫文檔導出功能了。思路是遍歷生成的表元信息( get_table_info ),根據表元信息獲取表的字段信息( gen_table_column_info ),然后輸出 excel 文檔( save_column_info_to_excel ),如下所示:
def gen_db_table_info_skip_col(self, db_name, file_path, col_names_skip):
# 過濾指定列,導出數據表信息到文檔
table_info_rows = self.get_table_info(db_name)
for table_row in table_info_rows:
print("\n", "*" * 10, "生成表信息:", table_row[1])
self.gen_table_column_info(table_row, file_path, col_names_skip)
def gen_table_column_info(self, table_info_row, file_path, col_names_skip=None):
# 導出字段信息表到文檔
database_name = table_info_row[0]
table_name = table_info_row[1]
table_comment = table_info_row[2]
# 從數據庫獲取表信息
column_info = self.get_table_column_info(database_name, table_name)
# 寫入excel文件
self.save_column_info_to_excel(table_name, table_comment, column_info, file_path, col_names_skip)
此處包含兩個函數,gen_db_table_info_skip_col
功能是根據數據庫名、文件保存路徑、需要過濾的字段名導出表元信息,然后使用 for 語句進行遍歷。gen_table_column_info
是根據表信息及需要過濾的字段,先讀表字段信息,然后寫入到 excel 文檔。注意,此處col_names_skip
默認值為 None ,即如果不需要過濾,不輸入此參數即可。至此,我們自動生成數據庫文檔的功能已完成。在__main__
中執行看一下輸出情況:
if __name__ == '__main__':
# 輸出文檔地址
excel_path = "E:/pythontest/test_tableinfo.xlsx"
# 數據庫連接信息
host = "localhost"
port = 3306
user = "root"
password = "123456"
db_name = "test"
charset = 'utf8'
# 需要過濾的字段
col_names_to_skip = ["id", "sys_create_time", "sys_create_user", "sys_update_time", "sys_update_user", "record_version"]
# 初始化類,創建文件,生成數據庫說明文檔
dbInfoGenerator = DbInfoGenerator(host, port, user, password, db_name, charset)
dbInfoGenerator.create_file(excel_path)
dbInfoGenerator.gen_db_table_info_skip_col(db_name, excel_path, col_names_to_skip)
結果如下:
表的字段說明已輸出到 excel 文檔中,對應的字段也已過濾。只是格式不是很好看,因此,有需要的可以用 openpyxl 對 excel 文檔的格式進行設置即可。
6 (可選)設置 excel 文檔格式
如果需要對 excel 文檔進行格式設置,以下是我的一個基本格式設置,有需要的可以參考一下,制作適合自己的文檔格式。格式的設置思路主要如下:
- 設置各列的寬度
- 遍歷 excel 表每一行,如果是表名,則合並為一行作為表頭,設置表頭格式為加粗、加黑色邊框、居中對齊、填充背景色。
- 如果表字段信息內容,則設置黑色邊框即可。
def set_file_format(self, file_path):
# 設置表格式
if not os.path.exists(file_path):
print("文件不存在,不處理")
return
workbook = openpyxl.load_workbook(file_path)
sheet = workbook.worksheets[0]
# 設置各列寬
sheet.column_dimensions["A"].width = 16
sheet.column_dimensions["B"].width = 10
sheet.column_dimensions["C"].width = 20
sheet.column_dimensions["D"].width = 40
# 設置表名格式
max_row = sheet.max_row
for i in range(1, max_row + 1):
col1_value = sheet.cell(i, 1).value
col2_value = sheet.cell(i, 2).value
# 首列有數據,第2列無數據,則為表名
if col1_value and not col2_value:
# 合並表名
sheet.merge_cells(start_row=i, start_column=1, end_row=i, end_column=4)
# 加粗字體
font = Font(name="微軟雅黑", size=12, bold=True, italic=False, color="000000")
# 黑色邊框
side_style = Side(style="thin", color="000000")
border = Border(left=side_style, right=side_style, top=side_style, bottom=side_style)
# 居中對齊
cell_alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
# 填充背景色
p_fill = PatternFill(fill_type="solid", fgColor="BFBFBF")
# 表名cell格式
for j in range(1, 5):
sheet.cell(i, j).font = font
sheet.cell(i, j).border = border
sheet.cell(i, j).alignment = cell_alignment
sheet.cell(i, j).fill = p_fill
# 若首列和第2列都有數據,則是表內容
if col1_value and col2_value:
# 黑色邊框
side_style = Side(style="thin", color="000000")
border = Border(left=side_style, right=side_style, top=side_style, bottom=side_style)
# 表名cell格式
for j in range(1, 5):
sheet.cell(i, j).border = border
# 保存文檔
workbook.save(file_path)
當生成數據庫說明文檔后,調用此函數,即可修改其文檔格式,效果如下:
7 總結
本文主要針對數據庫說明文檔(數據字典)的自動化生成進行講解。通過使用 SQL 讀取數據庫表及字段元信息,然后輸出到 excel 文檔的思路,以 python 的實現方式完成自動生成文檔功能。如果你還在手工生成數據庫說明文檔,可以試試這種方法,一定讓你效率大增。希望可以幫助到有需要的人。如果想看完整的代碼,可到我 github 地址中查看:https://github.com/mianshenglee/my-example/tree/master/python/tool-gen-db-doc
根據本文實現的思路,最后可以留幾個思考題給大家,想想如何做:
- 不使用 python ,用其它你熟悉的語言來實現此功能。
- 如何只需要生成指定表的字段信息或者過濾指定表,怎么做?
- 數據庫表名一般都會有前綴或后綴,能否根據前綴或后綴來過濾生成或者過濾,怎么做?
- 本文是生成 excel 文檔,如果需要生成 word 、html 、md 、pdf 等格式的文檔,怎么做?
參考資料
- openpyxl官方文檔:
https://openpyxl.readthedocs.io/
- pymysql官方文檔:
https://pymysql.readthedocs.io/en/latest/
往期文章
- Python 處理 Excel 文件
- python基本操作-文件、目錄及路徑
- MinIO 的分布式部署
- 利用MinIO輕松搭建靜態資源服務
- 搞定SpringBoot多數據源(3):參數化變更源
- 搞定SpringBoot多數據源(2):動態數據源
- 搞定SpringBoot多數據源(1):多套源策略
- java開發必學知識:動態代理
- 2019 讀過的好書推薦
我的公眾號(搜索Mason技術記錄
),獲取更多技術記錄: