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

8.9 KiB
Raw Blame History

SQL Server DDL 模板技术文档Jinja2 模板)


简介

sqlserver_ddl_tmpl 是一个基于 Jinja2 模板引擎 的 SQL Server 数据定义语言DDL生成模板。该模板用于根据元数据动态生成创建表、索引以及添加字段描述的完整 T-SQL 脚本。

支持功能包括:

  • 字段类型映射
  • 主键定义
  • 唯一/普通索引创建
  • 使用 sp_addextendedproperty 添加中文注释MS_Description
  • 自动删除旧表(可选)

模板结构概览

{% macro typeStr(type, len, dec) %}...{% endmacro %}
{% macro nullStr(nullable) %}...{% endmacro %}
{% macro primary() %}...{% endmacro %}

drop table dbo.{{summary[0].name}};
CREATE TABLE dbo.{{summary[0].name}}
(
  ...
)
-- 创建索引
-- 添加表和列的描述信息

Macros说明

typeStr(type, len, dec)

将通用字段类型转换为 SQL Server 对应的数据类型。

输入参数 类型 说明
type string 字段逻辑类型(如 'str', 'int' 等)
len int 长度或精度(适用于字符串、数值等)
dec int 小数位数(适用于浮点数)

映射规则:

逻辑类型 SQL Server 类型 说明
str NVARCHAR(len) 变长 Unicode 字符串
char CHAR(len) 定长字符
long/int/short NUMERIC 整数类型统一用 NUMERIC(无精度限制)
float/double/ddouble numeric(len, dec) 精确数值类型,支持小数
date/time DATE 日期类型
timestamp TIMESTAMP 时间戳(行版本号),注意:非 datetime 类型
text NVARCHAR(MAX) 大文本字段
bin IMAGE 二进制大对象(已弃用,建议使用 VARBINARY(MAX)
其他未知类型 原样输出 {{type}} 扩展兼容性

⚠️ 注意SQL Server 的 TIMESTAMP 实际是 rowversion 类型,若需时间记录请使用 DATETIME2


nullStr(nullable)

控制字段是否允许为空。

参数 值示例 输出结果
nullable 'no' NOT NULL
其他值(如 'yes', 空等) —— (空字符串,即允许 NULL

primary()

生成主键约束语句。

  • 使用 summary[0].primary 中定义的字段列表。
  • 输出格式:, primary key (col1, col2, ...)
  • 仅在存在主键字段时插入。

主体 DDL 逻辑

1. 删除原表

drop table dbo.{{summary[0].name}};

⚠️ 此操作会 无条件删除现有表及其数据,生产环境慎用。


2. 创建表

CREATE TABLE dbo.{{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 %}
)

字段循环说明:

  • 遍历 fields 列表中每个字段对象。
  • 生成字段名 + 类型 + 是否非空。
  • 使用 {%- if not loop.last %},{% endif %} 控制逗号不加在最后一行。

主键添加条件:

  • summary[0].primary 存在且长度 > 0 时,调用 primary() 宏添加主键定义。

3. 创建索引

{% 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 %}

支持索引类型:

v.idxtype 生成语句
'unique' CREATE UNIQUE INDEX ...
其他(如 'normal', 空值等) CREATE INDEX ...

索引命名规则:

<表名>_<索引名>

例如:user_idx_email 表示表 user 上名为 idx_email 的索引。


4. 添加表与字段描述MS_Description

利用系统存储过程 sys.sp_addextendedproperty 添加注释。

表级描述:

EXEC sys.sp_addextendedproperty 
  @name=N'MS_Description', 
  @value=N'{{summary[0].title}}',
  @level0type=N'SCHEMA', @level0name=N'dbo',
  @level1type=N'TABLE', @level1name=N'{{summary[0].name}}'

字段级描述(逐个循环):

{% for field in fields %}
EXEC sys.sp_addextendedproperty 
  @name=N'MS_Description', 
  @value=N'{{field.title}}',
  @level0type=N'SCHEMA', @level0name=N'dbo',
  @level1type=N'TABLE', @level1name=N'{{summary[0].name}}',
  @level2type=N'COLUMN', @level2name=N'{{field.name}}'
{% endfor %}

这些描述可在 SSMS 的“属性”面板或通过查询 sys.extended_properties 查看。


输入变量要求(上下文 Context

模板运行需要以下变量注入:

变量名 类型 必须 说明
summary list[dict] 表基本信息列表,通常只取 [0]
fields list[dict] 字段列表
indexes list[dict] 索引配置列表(可为空)

summary[0] 结构示例:

{
  "name": "user_info",           # 表名
  "title": "用户基本信息表"       # 表中文名/描述
  "primary": ["id"]              # 主键字段数组
}

fields 元素结构示例:

[
  {
    "name": "id",
    "type": "long",
    "length": 19,
    "dec": 0,
    "nullable": "no",
    "title": "用户ID"
  },
  {
    "name": "username",
    "type": "str",
    "length": 50,
    "dec": 0,
    "nullable": "no",
    "title": "用户名"
  }
]

indexes 元素结构示例:

[
  {
    "name": "idx_email",
    "idxtype": "unique",
    "idxfields": ["email"]
  },
  {
    "name": "idx_dept",
    "idxtype": "normal",
    "idxfields": ["dept_id", "status"]
  }
]

示例输出(渲染后)

假设输入如下元数据:

summary = [{
    "name": "user",
    "title": "用户表",
    "primary": ["id"]
}]
fields = [
    {"name": "id", "type": "long", "length": 19, "dec": 0, "nullable": "no", "title": "用户ID"},
    {"name": "name", "type": "str", "length": 100, "dec": 0, "nullable": "yes", "title": "姓名"},
    {"name": "email", "type": "str", "length": 255, "dec": 0, "nullable": "no", "title": "邮箱"}
]
indexes = [
    {"name": "uk_email", "idxtype": "unique", "idxfields": ["email"]}
]

渲染结果:

drop table dbo.user;
CREATE TABLE dbo.user
(
  id NUMERIC NOT NULL,
  name NVARCHAR(100),
  email NVARCHAR(255) NOT NULL,
  primary key(id)
)

CREATE UNIQUE INDEX user_uk_email ON user(email);

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户表' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'user'

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'user', @level2type=N'COLUMN',@level2name=N'id'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'姓名' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'user', @level2type=N'COLUMN',@level2name=N'name'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'邮箱' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'user', @level2type=N'COLUMN',@level2name=N'email'

使用建议与注意事项

  1. 🔐 谨慎使用 DROP TABLE
    生产环境中应避免直接删除表。建议改为判断是否存在再操作,或提供开关控制。

  2. 💡 推荐扩展:增加 IF NOT EXISTS 判断表是否存在:

    IF OBJECT_ID('dbo.{{summary[0].name}}', 'U') IS NOT NULL
        DROP TABLE dbo.{{summary[0].name}};
    
  3. 🛠 替代 IMAGE 类型:
    IMAGE 已被弃用,推荐替换为:

    {%- elif type=='bin' -%}
    VARBINARY(MAX)
    
  4. 📅 时间戳类型澄清:
    若需存储时间,请使用 DATETIME2 并修改模板中 timestamp 分支。

  5. 🔍 支持更多类型:可根据项目需求扩展 typeStr 宏以支持 xml, hierarchyid, geometry 等高级类型。

  6. 🧪 测试建议:
    在自动化脚本中集成此模板前,务必进行单元测试验证类型映射正确性。


总结

本模板是一个高效、灵活的 SQL Server 表结构自动生成工具适用于代码生成器、ETL 工具、模型同步系统等场景。结合元数据驱动设计,可大幅提升数据库开发效率并保证一致性。

优点

  • 类型自动映射
  • 支持注释与索引
  • 结构清晰易维护

⚠️ 风险提示

  • 包含 DROP TABLE,使用需谨慎
  • TIMESTAMPIMAGE 类型需按实际需求调整

📅 最后更新2025-04-05
📦 所属模块:数据建模 / DDL 自动生成