You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite3如何实现值在多列间的全局唯一约束?

SQLite实现跨多列全局唯一约束的方案

SQLite 本身没有提供直接实现多列共享唯一校验规则的原生语法,可通过以下两种方式实现需求:

方案一:基于现有表结构使用触发器校验

不需要调整现有表结构,通过INSERT、UPDATE触发器做前置校验即可:

-- 插入链路前校验点是否已被占用
CREATE TRIGGER check_link_point_unique_before_insert
BEFORE INSERT ON links
FOR EACH ROW
BEGIN
    SELECT RAISE(FAIL, '目标点已被其他链路占用')
    WHERE EXISTS (
        SELECT 1 FROM links
        WHERE point_a = NEW.point_a OR point_b = NEW.point_a
        OR point_a = NEW.point_b OR point_b = NEW.point_b
    );
END;

-- 更新链路前校验点是否已被占用(排除当前修改的链路自身)
CREATE TRIGGER check_link_point_unique_before_update
BEFORE UPDATE ON links
FOR EACH ROW
BEGIN
    SELECT RAISE(FAIL, '目标点已被其他链路占用')
    WHERE EXISTS (
        SELECT 1 FROM links
        WHERE id != NEW.id
        AND (point_a = NEW.point_a OR point_b = NEW.point_a
        OR point_a = NEW.point_b OR point_b = NEW.point_b)
    );
END;

该方案的劣势是触发器逻辑隐式,后续维护表结构时容易遗漏校验规则,且插入/更新时需要全表扫描两个字段,性能略低。

方案二:优化表结构(更推荐)

调整表结构把点和链路的归属关系显性化,天然保证每个点只能属于一条链路,逻辑更清晰、性能更好:

CREATE TABLE links (
    id INTEGER PRIMARY KEY AUTOINCREMENT
    -- 可按需添加链路的属性,比如创建时间、链路类型、带宽等
);

CREATE TABLE points (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    x INTEGER NOT NULL,
    y INTEGER NOT NULL,
    link_id INTEGER REFERENCES links(id),
    -- 保证每个点最多关联一条链路,NULL表示未关联任何链路
    UNIQUE(id, link_id)
);

-- 补充约束:单条链路最多关联2个点,避免异常数据
CREATE TRIGGER check_link_point_count
BEFORE INSERT ON points
FOR EACH ROW
WHEN NEW.link_id IS NOT NULL
BEGIN
    SELECT RAISE(FAIL, '单条链路最多关联2个点')
    WHERE (SELECT COUNT(*) FROM points WHERE link_id = NEW.link_id) >= 2;
END;

该方案的优势:

  • 约束直观,查询点是否被占用直接读取points表对应行的link_id字段即可
  • 不需要维护复杂的跨列校验逻辑,出错概率低
  • 关联查询链路对应的点位性能和原有方案一致,插入/更新校验的性能更高

内容的提问来源于stack exchange,提问作者Hubro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 02:54:03