用途
pythia-table 用于创建或变更数据库表、列、约束、索引、序列和注释。它把表视为比任何读取它的程序都长寿的契约:列与报表、接口和存储过程紧密相关,而结构 DDL 几乎没有撤销余地——DROP COLUMN 是永久性的,重命名一列会同时破坏所有调用方。因此该技能要求在任何结构变更前先充分了解现状,再进行设计。
核心铁律
没有注释、约束和已知影响,就不建表或列(NO TABLE OR COLUMN WITHOUT ITS COMMENT, ITS CONSTRAINTS AND ITS IMPACT KNOWN)。
工作流程:学习 → 询问 → 执行
1. 学习表及其相邻对象
- 使用
pythia cols T、pythia comments T、pythia stats T查看现有列、已有注释以及哪些外键缺少索引。 - 在任何 ALTER 之前运行
pythia impact T,列出所有会重新编译的程序。 - 使用
pythia similar T_<NAME>和pythia ddl TABLE <NEIGHBOUR>了解本仓库既有的建表方式:主键风格、审计列、表空间、命名约定。阅读.pythia/conventions.md和pythia conventions。
2. 询问属于开发者的决策(通过 pythia-spec)
包括:哪些数据保留或删除、现有行的可空性与回填值、保留策略、谁写入该表(API 包、触发器、接口)、在仓库没有规则时使用 identity 列还是序列。绝不替 NOT NULL 列擅自编造业务默认值。
3. 编写单一有序脚本
参考 reference/ddl-standards.md 中的模板和数据类型规则:
- 为每个约束命名(PK_、FK_、UK_、CK_,除非仓库另有规定);每张表必须有主键;每个外键列必须有索引。
- 文本使用
VARCHAR2(n CHAR)——一个越南语字符可能占用 3 字节;金额使用NUMBER(p,s),绝不用 FLOAT;日期或时间戳按需选择 DATE 或 TIMESTAMP。 - 每个新表和新列都要有
COMMENT ON TABLE和COMMENT ON COLUMN,说明含义、单位、允许值和来源。此处可以使用越南语,因为COMMENT ... IS只接受字面量(不支持 unistr),pythia 会精确发送 UTF-8;如果字符集无法容纳,pythia doctor --db会发出警告。 - 用
pythia lint script.sql检查:缺失注释、未命名约束、未索引外键、没有默认值的ADD ... NOT NULL、字节语义文本、缺失的仓库标准列。错误必须修复,不能争辩。
4. 落地与验证
- 通过 pythia-deploy 落地(
pythia deploy script.sql):每条语句都会预览,一次审批,按顺序执行,遇到第一个失败即停止。单条语句可照常通过pythia apply执行。 - 结构变更默认被拒绝(structural is deny by default)——需转达该拒绝;由开发者决定(
pythia policy set structural confirm,或指定包含 structural 的 autopilot 租约)。 - 验证(pythia-verify):
pythia cols T、pythia comments T(0 缺失)、pythia invalid对照基线。
变更线上表:先扩展,后收缩
| 变更类型 | 安全做法 |
|---|---|
| 新增强制列 | ADD (c ... DEFAULT <agreed> NOT NULL)——一步完成,12c+ 上仅元数据操作。若无法商定默认值,则先加可空列,回填(data_dml),再 MODIFY c NOT NULL。 |
| 重命名 | 绝不在共享 schema 上原地重命名:新增列、复制数据、迁移调用方、稍后删除旧列——这是一个单独的、破坏性审批。 |
| 类型变更 | 加宽(VARCHAR2(50) → (100))可原地进行;任何收窄或转换:新增列、复制、切换。 |
| 在现有数据上添加外键 | 先 ENABLE NOVALIDATE,清理数据行,再 VALIDATE——并先建索引再建约束。 |
| 删除 | 破坏性操作:独立预览、独立审批,除非卡片明确说明,绝不放在 autopilot 租约内。检查回收站是否开启,未经要求绝不添加 PURGE。 |
大表(数百万行):带默认值的 ALTER TABLE ... ADD 是仅元数据操作,但 MODIFY、索引构建和回填不是——需要询问维护窗口,且 ONLINE 索引构建需要企业版。分区和压缩是单独授权的选项:提出前需说明这一点。
回滚是否真实存在?
| 语句 | 撤销方式 |
|---|---|
COMMENT ON |
可以——旧注释会被快照;pythia journal restore <entry>。 |
CREATE TABLE / INDEX / SEQUENCE |
一个 DROP——属于结构操作,需手写并像任何写入一样审批。 |
ALTER TABLE ADD |
ALTER TABLE ... DROP COLUMN——自添加以来写入的数据会丢失。 |
DROP、TRUNCATE、SET UNUSED |
不可以。Flashback 是 DBA 的工作,且需保留策略允许。 |
危险信号——如果出现以下想法,停下来
| 想法 | 现实 |
|---|---|
| “注释以后再加,先让它跑通” | “以后”永远不会来;数据字典是唯一能存活的文档。同一个脚本里加。 |
| “外键索引只是一种优化” | 没有它,删除父行会锁住整个子表。这是负载下的正确性问题。 |
| “VARCHAR2(100) 足够了” | 在 AL32UTF8 下 100 字节约等于 33 个越南语字符。要写明 CHAR。 |
| “我把 NOT NULL 列默认为 0 就行” | 那是静默做出的业务决策。要去问。 |
| “重命名就是一条语句” | 每处引用都会有一个调用方被破坏。先扩展,后收缩。 |
| “表是新的,影响为零” | 用 pythia impact 作为证据说出来——那时它才是事实,而不是猜测。 |
何时不使用本技能
- 修改读取该表的代码 → pythia-write / pythia-package。
- 现有表上的慢查询 → pythia-tune(调优要求时才在此设计索引)。
- 数据修复(UPDATE/DELETE)→ pythia-apply;它们属于 data_dml。
适用场景与限制
适用于需要安全管理数据库表结构的数据库开发人员和 DBA,尤其是 Oracle 环境下涉及注释规范、约束命名、外键索引和线上表安全变更的场景。限制:本技能只处理结构 DDL,不处理读取表的代码修改、性能调优或数据修复;结构性变更默认被拒绝,需要开发者显式确认;分区和压缩等选项需单独授权。