python实现将mysql数据表导出指定格式的文档

import pymysql
from typing import List, Dict, Tuple
import os

class MySQLTableExporter:
    def __init__(self, host: str, port: int, user: str, password: str, db_name: str):
        """
        初始化数据库连接
        :param host: 数据库主机
        :param port: 数据库端口
        :param user: 数据库用户名
        :param password: 数据库密码
        :param db_name: 要导出的数据库名
        """
        self.host = host
        self.port = port
        self.user = user
        self.password = password
        self.db_name = db_name
        self.conn = None
        self.cursor = None
        # 新增:定义需要忽略的表前缀列表
        self.ignore_prefixes = ['jimu_', 'onl_', 'qrtz_', 'rep_demo', 'test_','jeecg_','demo']

    def connect(self) -> None:
        """建立数据库连接"""
        try:
            self.conn = pymysql.connect(
                host=self.host,
                port=self.port,
                user=self.user,
                password=self.password,
                db=self.db_name,
                charset='utf8mb4',
                cursorclass=pymysql.cursors.DictCursor
            )
            self.cursor = self.conn.cursor()
            print(f"成功连接到数据库:{self.db_name}")
        except Exception as e:
            raise ConnectionError(f"数据库连接失败:{str(e)}")

    def get_all_tables(self) -> List[str]:
        """获取数据库中所有表名(过滤掉指定前缀的表)"""
        try:
            sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = %s ORDER BY TABLE_NAME"
            self.cursor.execute(sql, (self.db_name,))
            all_tables = [item['TABLE_NAME'] for item in self.cursor.fetchall()]
            
            # 新增:过滤掉指定前缀的表
            filtered_tables = []
            for table in all_tables:
                # 检查表名是否以忽略前缀开头
                if not any(table.startswith(prefix) for prefix in self.ignore_prefixes):
                    filtered_tables.append(table)
                else:
                    print(f"忽略表:{table}(匹配前缀{[p for p in self.ignore_prefixes if table.startswith(p)][0]})")
            
            return filtered_tables
        except Exception as e:
            raise Exception(f"获取表名失败:{str(e)}")

    def get_table_cn_name(self, table_name: str) -> str:
        """
        获取表的中文名称(优先数据库注释→预定义映射→英文表名)
        :param table_name: 英文表名
        :return: 表的中文名称(无则返回英文表名)
        """
        try:
            # 1. 先从数据库获取表注释(优先使用)
            sql = """
            SELECT TABLE_COMMENT 
            FROM INFORMATION_SCHEMA.TABLES 
            WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s
            """
            self.cursor.execute(sql, (self.db_name, table_name))
            result = self.cursor.fetchone()
            db_comment = result['TABLE_COMMENT'] if result and result['TABLE_COMMENT'] else ""
            
            if db_comment:
                return db_comment
            
            # 2. 数据库无注释时,使用预定义的中文映射
            predefined_cn_names = {
                "delegation_mode": "委托方式表",
                "active_arrange_order": "活动安排表",
                "review_condition": "评审条件表",
                "study_certificate": "学习管理证书表"
                # 可在此添加其他表的中文映射(键:英文表名,值:中文表名)
            }
            return predefined_cn_names.get(table_name, table_name)
        
        except Exception as e:
            raise Exception(f"获取表{table_name}中文名称失败:{str(e)}")

    def get_table_columns(self, table_name: str) -> List[Dict]:
        """获取表的列信息(字段名、类型、主键、非空、注释等)"""
        try:
            sql = """
            SELECT 
                COLUMN_NAME AS 代码,
                COLUMN_NAME AS 名称,  -- 若字段有中文名称可修改此处查询逻辑
                COLUMN_TYPE AS 数据类型,
                CASE WHEN COLUMN_KEY = 'PRI' THEN 'TRUE' ELSE 'FALSE' END AS 主要的,
                CASE WHEN IS_NULLABLE = 'NO' THEN 'TRUE' ELSE 'FALSE' END AS 强制,
                COLUMN_COMMENT AS 注释
            FROM INFORMATION_SCHEMA.COLUMNS 
            WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s
            ORDER BY ORDINAL_POSITION
            """
            self.cursor.execute(sql, (self.db_name, table_name))
            columns = self.cursor.fetchall()
            return columns
        except Exception as e:
            raise Exception(f"获取表{table_name}列信息失败:{str(e)}")

    def generate_markdown(self, tables: List[str]) -> str:
        """生成Markdown格式的文档内容(核心:只保留三级标题「表 中文(英文)」)"""
        # 1. 表清单部分(完全还原原始模板格式)
        markdown_content = "# 1表清单\n\n## 1.1表清单\n\n"
        markdown_content += "|名称|代码|注释|\n|---|---|---|\n"
        
        for table in tables:
            table_cn_name = self.get_table_cn_name(table)
            # 名称列显示中文(无则英文),代码列英文表名,注释列与名称列一致
            markdown_content += f"|{table_cn_name}|{table}|{table_cn_name}|\n"
        
        # 2. 表列清单部分(核心改动:只保留三级标题,格式为「表 中文名称(英文表名)」)
        markdown_content += "\n# 2表列清单\n\n"
        
        for table in tables:
            columns = self.get_table_columns(table)
            table_en_name = table  # 英文表名
            table_display_name = self.get_table_cn_name(table)  # 中文(无则英文)
            
            # 只保留三级标题:### 表 中文名称(英文表名)(完全匹配要求)
            markdown_content += f"### {table_display_name}({table_en_name})\n\n"
            
            # 列清单表格(完全还原原始模板:代码列带,列结构一致)
            markdown_content += "|代码|名称|数据类型|主要的|强制|注释|\n"
            markdown_content += "|---|---|---|---|---|---|\n"
            
            for col in columns:
                markdown_content += (
                    f"|{col['代码']}|{col['名称']}|{col['数据类型']}|"
                    f"{col['主要的']}|{col['强制']}|{col['注释'] or ''}|\n"
                )
            markdown_content += "\n"  # 表之间空行,优化可读性
        
        return markdown_content

    def export(self, output_file: str = "数据库表结构文档.md") -> None:
        """执行导出操作"""
        try:
            self.connect()
            tables = self.get_all_tables()
            
            if not tables:
                print("数据库中没有找到符合条件的表(已过滤指定前缀表)")
                return
            
            markdown_content = self.generate_markdown(tables)
            
            # 写入文件
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write(markdown_content)
            
            print(f"导出成功!共导出{len(tables)}张表,文件保存至:{os.path.abspath(output_file)}")
        
        except Exception as e:
            print(f"导出失败:{str(e)}")
        finally:
            # 关闭连接
            if self.cursor:
                self.cursor.close()
            if self.conn:
                self.conn.close()

if __name__ == "__main__":
    # -------------------------- 配置参数 --------------------------
    CONFIG = {
        "host": "localhost",       # 数据库主机(默认localhost)
        "port": 3306,              # 数据库端口(默认3306)
        "user": "root",            # 数据库用户名
        "password": "root",# 数据库密码
        "db_name": "db-name" # 要导出的数据库名
    }
    # -------------------------- 配置参数 --------------------------
    
    # 创建导出实例
    exporter = MySQLTableExporter(
        host=CONFIG["host"],
        port=CONFIG["port"],
        user=CONFIG["user"],
        password=CONFIG["password"],
        db_name=CONFIG["db_name"]
    )
    
    # 执行导出(可指定输出文件名)
    exporter.export(output_file="数据库表结构文档.md")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燕山石头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值