7.8 KiB
7.8 KiB
以下是为提供的 Jinja2 模板代码编写的 Markdown 格式技术文档,用于描述该 PostgreSQL DDL 生成模板的功能、结构和使用方式。
PostgreSQL DDL 生成模板技术文档
概述
postgresql_ddl_tmpl 是一个基于 Jinja2 模板引擎的字符串模板,用于自动生成符合 PostgreSQL 语法的 数据定义语言 (DDL) 脚本。它可以根据表结构元数据(如字段类型、长度、是否可为空、主键、索引等)动态生成完整的 CREATE TABLE 语句,包括:
- 表的创建与删除
- 字段定义及其数据类型映射
- 主键约束
- 索引(普通或唯一)
- 表和字段的注释
该模板适用于自动化建模工具、ETL 流程或数据库同步系统中,实现从元数据到物理表结构的自动转换。
模板源码
postgresql_ddl_tmpl = """{% macro typeStr(type,len,dec) %}
{%- if type=='str' -%}
VARCHAR({{len}})
{%- elif type=='char' -%}
CHAR({{len}})
{%- elif type=='long' or type=='int' or type=='short' -%}
NUMERIC(30,0)
{%- elif type=='float' or type=='double' or type=='ddouble' -%}
NUMERIC({{len}},{{dec}})
{%- elif type=='date' -%}
DATE
{%- elif type=='time' -%}
TIME
{%- elif type=='timestamp' -%}
TIMESTAMP
{%- else -%}
{{type}}
{%- endif %}
{%- endmacro %}
{% macro nullStr(nullable) %}
{%- if nullable=='no' -%}
NOT NULL
{%- endif -%}
{% endmacro %}
{% macro primary() %}
,PRIMARY KEY({{','.join(summary[0].primary)}})
{% endmacro %}
DROP TABLE IF EXISTS {{summary[0].name}};
CREATE TABLE {{summary[0].name}}
(
{% for field in fields %}
{{field.name}} {{typeStr(field.type,field.length,field.dec)}} {{nullStr(field.nullable)}}{%- if not loop.last -%},{%- endif -%}
{% endfor %}
{% if summary[0].primary and len(summary[0].primary)>0 %}
{{primary()}}
{% endif %}
);
{% for v in indexes %}
CREATE {% if v.idxtype=='unique' %}UNIQUE{% endif %} INDEX {{summary[0].name}}_{{v.name}} ON {{summary[0].name}}({{",".join(v.idxfields)}});
{%- endfor -%}
COMMENT ON TABLE {{summary[0].name}} IS '{{summary[0].title}}';
{% for field in fields %}
COMMENT ON COLUMN {{summary[0].name}}.{{field.name}} is '{{field.title}}';
{% endfor %}
"""
模板变量说明
| 变量名 | 类型 | 描述 |
|---|---|---|
summary[0] |
对象 | 包含表级别的元信息对象,必须是列表且第一个元素有效 |
.name |
字符串 | 表名(如 "users") |
.title |
字符串 | 表的中文/描述性标题,用于 COMMENT |
.primary |
列表 | 主键字段名称列表(如 ["id"] 或 ["user_id", "tenant_id"]) |
fields |
列表 | 字段对象列表,每个对象代表一列 |
.name |
字符串 | 字段名(如 "username") |
.type |
字符串 | 字段逻辑类型(见下文“类型映射”) |
.length |
整数 | 字段长度(对字符串和数值类型有意义) |
.dec |
整数 | 小数位数(decimal scale) |
.nullable |
字符串 | 是否允许为空:"yes" 表示可空,"no" 表示 NOT NULL |
.title |
字符串 | 字段的中文/描述性标题,用于 COMMENT |
indexes |
列表 | 索引定义对象列表 |
.name |
字符串 | 索引名称标识(将用于生成索引名) |
.idxtype |
字符串 | 索引类型,若为 "unique" 则创建唯一索引 |
.idxfields |
列表 | 索引包含的字段名列表(如 ["email"] 或 ["status", "created_time"]) |
内置宏(Macros)
typeStr(type, len, dec)
根据字段的逻辑类型映射为 PostgreSQL 实际数据类型。
| 逻辑类型 | 映射结果 |
|---|---|
'str' |
VARCHAR(len) |
'char' |
CHAR(len) |
'long', 'int', 'short' |
NUMERIC(30,0) (高精度整数) |
'float', 'double', 'ddouble' |
NUMERIC(len, dec) |
'date' |
DATE |
'time' |
TIME |
'timestamp' |
TIMESTAMP |
| 其他未知类型 | 原样输出 {{type}}(可用于扩展) |
⚠️ 注意:浮点类型统一使用
NUMERIC以保证精度;如需性能优化可后续调整为REAL/DOUBLE PRECISION。
nullStr(nullable)
生成 NOT NULL 约束。
- 若
nullable == 'no'→ 输出NOT NULL - 否则不输出任何内容(即允许为空)
primary()
生成主键约束子句。
- 使用
summary[0].primary中的字段名,通过逗号拼接 - 示例:主键为
["id"]→ 输出,PRIMARY KEY(id) - 注意:前面有一个英文逗号,依赖前一行结尾,因此必须确保前面有换行和逗号处理
生成的 DDL 结构说明
-
删除旧表
DROP TABLE IF EXISTS table_name;避免重复建表错误。
-
创建新表
CREATE TABLE table_name (...);- 包含所有字段定义
- 自动添加主键约束(如果存在)
- 支持多字段联合主键
-
创建索引
CREATE [UNIQUE] INDEX table_name_idxname ON table_name(field1, field2);- 支持普通索引和唯一索引
- 索引命名规则:
{table_name}_{index_name}
-
添加注释
COMMENT ON TABLE table_name IS '用户信息表'; COMMENT ON COLUMN table_name.username IS '用户名';- 提升数据库可读性和文档性
使用示例
假设输入上下文如下(Python 字典形式):
context = {
"summary": [{
"name": "users",
"title": "用户信息表",
"primary": ["id"]
}],
"fields": [
{"name": "id", "type": "long", "length": 30, "dec": 0, "nullable": "no", "title": "用户ID"},
{"name": "username", "type": "str", "length": 50, "dec": 0, "nullable": "no", "title": "用户名"},
{"name": "email", "type": "str", "length": 100, "dec": 0, "nullable": "yes", "title": "邮箱地址"},
{"name": "created_time", "type": "timestamp", "length": 0, "dec": 0, "nullable": "no", "title": "创建时间"}
],
"indexes": [
{"name": "email_idx", "idxtype": "unique", "idxfields": ["email"]}
]
}
渲染后输出 SQL:
DROP TABLE IF EXISTS users;
CREATE TABLE users
(
id NUMERIC(30,0) NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
created_time TIMESTAMP NOT NULL,
PRIMARY KEY(id)
);
CREATE UNIQUE INDEX users_email_idx ON users(email);
COMMENT ON TABLE users IS '用户信息表';
COMMENT ON COLUMN users.id is '用户ID';
COMMENT ON COLUMN users.username is '用户名';
COMMENT ON COLUMN users.email is '邮箱地址';
COMMENT ON COLUMN users.created_time is '创建时间';
扩展建议
- ✅ 支持默认值:可在字段中增加
.default属性,并在模板中扩展。 - ✅ 外键支持:当前未处理外键,可根据需要添加
FOREIGN KEY子句。 - ✅ 字符集/排序规则:PostgreSQL 通常使用数据库级设置,也可显式指定。
- ✅ 分区表支持:复杂场景下可扩展模板支持
PARTITION BY。
注意事项
primary()宏前会自动加,,因此必须确保前面字段定义已正确结束并换行。- 所有字段的
length和dec必须提供,即使某些类型不需要(可用占位值如0)。 summary必须是一个非空列表,summary[0]是实际使用的表元数据。- 索引名应避免冲突,推荐命名清晰(如
idx_status)。
总结
postgresql_ddl_tmpl 是一个功能完整、结构清晰的 DDL 自动生成模板,适合集成进元数据驱动的数据平台。其优势在于:
- 类型抽象良好,便于业务人员理解
- 支持常见约束与注释
- 易于维护和扩展
通过此模板,可以高效地将模型设计转化为可执行的数据库脚本,提升开发效率与一致性。
✅ 文档版本:1.0
📅 最后更新:2025年4月5日