CREATE TABLE app.cf_lesson (
id BIGSERIAL PRIMARY KEY,
track_id BIGINT NOT NULL
REFERENCES app.cf_track (id) ON DELETE CASCADE,
slug VARCHAR(64) NOT NULL,
title VARCHAR(255) NOT NULL,
order_index INT NOT NULL DEFAULT 0,
content_md TEXT,
status VARCHAR(16) NOT NULL DEFAULT 'draft',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_lesson_track_slug UNIQUE (track_id, slug)
);
INSERT INTO app.cf_lesson (track_id, slug, title, order_index, status)
SELECT id, 'pg-intro', 'PostgreSQL 是什么', 1, 'published'
FROM app.cf_track WHERE slug = 'postgresql-essentials';
再试插入一个不存在的 track_id(如 999999),应被外键拒绝。
步骤 5:ALTER 与布尔列
ALTER TABLE app.cf_track
ADD COLUMN IF NOT EXISTS is_member BOOLEAN NOT NULL DEFAULT FALSE;
UPDATE app.cf_track
SET is_member = TRUE
WHERE slug = 'postgresql-essentials';
SELECT slug, is_member FROM app.cf_track ORDER BY sort_order;
PG 用真正的布尔,不要写 1/0 当习惯(虽常可强制转换,风格上应 TRUE/FALSE)。
步骤 6(可选):IDENTITY 写法对照
-- PG 10+ 更「标准 SQL」的自增写法(新表可用)
CREATE TABLE app.demo_identity (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name TEXT NOT NULL
);
BIGSERIAL 仍广泛出现在教程与存量库;新项目可优先 IDENTITY。二者都依赖序列对象。
讲清楚要点
因为 多个业务域共用一个数据库,所以 用 schema(如 app)分区,比全堆在 public 清晰。
主键稳定、业务键可暴露:id 给关联与 ORM;slug 给 URL,并加 UNIQUE。
约束要命名:CONSTRAINT uq_… 让报错可读,迁移与排错更快。
外键 ON DELETE CASCADE 表示删课程时级联删课时——适合强归属;若要保留历史,改用 RESTRICT 或软删。