sqlor/aidocs/ddl_template_mysql.md
2025-10-05 11:24:24 +08:00

6.5 KiB
Raw Permalink Blame History

以下是为提供的 Jinja2 模板代码编写的 Markdown 格式技术文档,适用于数据库建模或自动化 DDL 生成场景。


MySQL DDL 自动生成模板技术文档

概述

本模板是一个基于 Jinja2 的 SQL DDL数据定义语言生成模板用于根据元数据自动生成 MySQL 表的 CREATE TABLE 和相关索引语句。支持字段类型映射、默认值、非空约束、主键、注释以及普通/唯一索引的创建。

该模板可用于数据建模工具、ETL 流程配置、数据库初始化脚本等自动化场景。


模板变量说明

模板依赖以下上下文变量:

变量名 类型 说明
summary 列表 表结构摘要信息列表,通常只包含一个元素(当前表),如:summary[0].name, summary[0].primary, summary[0].title
fields 列表 字段列表,每个字段包含名称、类型、长度、小数位、是否可为空、默认值、标题(注释)等属性
indexes 列表 索引定义列表,每个索引包含名称、类型(indexunique)、字段列表

summary[0] 结构示例

{
  "name": "user_info",
  "primary": ["id"],
  "title": "用户基本信息表"
}

field 结构示例

{
  "name": "age",
  "type": "int",
  "length": 11,
  "dec": 0,
  "nullable": "no",
  "default": "0",
  "title": "年龄"
}

index 结构示例

[
  {
    "name": "idx_email",
    "idxtype": "unique",
    "idxfields": ["email"]
  },
  {
    "name": "idx_status",
    "idxtype": "index",
    "idxfields": ["status", "create_time"]
  }
]

宏函数Macros

模板中定义了多个辅助宏函数,用于格式化 SQL 片段。

typeStr(type, len, dec)

将高级字段类型转换为对应的 MySQL 数据类型。

输入类型(type 输出 MySQL 类型
str VARCHAR(len)
char CHAR(len)
int, long, short int
long(单独判断) bigint
float, double, ddouble double(len, dec)
date date
time time
datetime datetime
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
text longtext
bin longblob
其他未知类型 原样输出 {{type}}

⚠️ 注意:long 类型在第一个条件中被映射为 int,但在后续又被单独判断为 bigint —— 这可能导致逻辑冲突,见下方【注意事项】。

defaultValue(defaultv)

生成字段的默认值子句。

  • defaultv 存在,则输出:DEFAULT 'value'
  • 若为空,则不输出任何内容

所有默认值均以字符串形式包裹(使用单引号),适合文本和数字;时间类型需确保传入格式正确。

nullStr(nullable)

控制字段是否允许为空。

  • nullable == 'no' → 输出 NOT NULL
  • 否则不输出

推荐约定:yes/no 表示可空性,也可扩展为布尔值处理。

primary()

生成主键定义语句。

  • 使用 summary[0].primary 中的字段名列表,用逗号连接
  • 输出:, primary key (col1,col2,...)

注意:此宏前会自动换行并缩进,需配合字段列表使用。


生成的 SQL 内容结构

1. 删除已有表

DROP TABLE IF EXISTS {{summary[0].name}};

2. 创建新表

CREATE TABLE table_name (
  `field1` type ... [NOT NULL] [DEFAULT '...'] [COMMENT '...'],
  ...
  [PRIMARY KEY (pk_fields)]
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8
[COMMENT='表注释'];

3. 创建索引

遍历 indexes 数组,生成:

CREATE [UNIQUE] INDEX index_name ON table_name(field1, field2);

示例输出

假设输入如下元数据:

summary = [{
    "name": "user",
    "primary": ["id"],
    "title": "用户表"
}]

fields = [
    {
        "name": "id",
        "type": "long",
        "length": 20,
        "dec": 0,
        "nullable": "no",
        "default": "",
        "title": "用户ID"
    },
    {
        "name": "username",
        "type": "str",
        "length": 50,
        "dec": 0,
        "nullable": "no",
        "default": "",
        "title": "用户名"
    },
    {
        "name": "created_at",
        "type": "timestamp",
        "length": 0,
        "dec": 0,
        "nullable": "yes",
        "default": "",
        "title": "创建时间"
    }
]

indexes = [
    {
        "name": "uk_username",
        "idxtype": "unique",
        "idxfields": ["username"]
    }
]

生成的 SQL

DROP TABLE IF EXISTS user;
CREATE TABLE user
(
  `id` bigint NOT NULL,
  `username` VARCHAR(50) NOT NULL,
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP 
)
engine=innodb 
default charset=utf8 
comment '用户表';

CREATE UNIQUE INDEX user_uk_username ON user(username);

注意事项与建议

  1. 类型判断逻辑问题

    {% elif type=='long' or type=='int' or type=='short' %}
    int
    {% elif type=='long' %}
    bigint
    

    上述逻辑中,long 已在第一个分支被捕获为 int,因此永远不会进入 bigint 分支!
    修复建议

    {%- if type == 'long' -%}
    bigint
    {%- elif type in ['int', 'short'] -%}
    int
    
  2. 🔤 所有字符串默认值都加了单引号,若需支持数值型默认值(如 DEFAULT 0),应做类型区分。

  3. 🧩 summary 设计为列表形式,但实际仅使用 summary[0],可考虑简化为直接对象传参。

  4. 💬 注释建议统一使用 UTF-8 编码,避免中文乱码。

  5. 🔐 生产环境建议增加 SQL 注入风险校验(如字段名、表名合法性验证)。


使用方式Python 示例)

from jinja2 import Template

# 加载模板
tpl = Template(mysql_ddl_tmpl)

# 渲染 SQL
sql = tpl.render(summary=summary, fields=fields, indexes=indexes)

print(sql)

版本历史

版本 日期 描述
1.0 2025-04 初始版本,支持基础字段类型与索引生成

许可与维护

  • 作者Auto-generated
  • 用途:内部系统 / 数据仓库建模
  • 维护建议:结合 Schema JSON 配置驱动模板渲染,提升可维护性。

文档结束