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

如何让SQLite在UNIQUE约束中视NULL为非不同值?

在SQLite中实现UNIQUE约束下NULL视为相同值的方案

SQLite默认将UNIQUE约束中的NULL值视为不同值,若要让特定约束下的NULL被识别为重复值,可通过以下两种方案实现:

方法1:使用生成列(Generated Column)

通过生成列将NULL替换为固定占位符,再对包含生成列的组合添加UNIQUE约束,让原字段为NULL时统一匹配占位符,触发重复约束。

CREATE TABLE Foo (
    Name TEXT NOT NULL,
    Nullable TEXT,
    -- 用空字符串作为NULL的占位符,可根据业务替换为其他无冲突值
    CoalescedNullable TEXT GENERATED ALWAYS AS (IFNULL(Nullable, '')) STORED,
    UNIQUE(Name, CoalescedNullable)
);

测试效果:

INSERT INTO Foo(Name, Nullable) VALUES('foo', 'bar');
INSERT INTO Foo(Name, Nullable) VALUES('foo', 'bar'); -- 报错:UNIQUE约束冲突(符合预期)

INSERT INTO Foo(Name) VALUES('baz');
INSERT INTO Foo(Name) VALUES('baz'); -- 报错:UNIQUE约束冲突(满足需求)

方法2:使用触发器(Trigger)

创建插入和更新前的触发器,手动检查是否存在相同Name且Nullable为NULL的记录,存在则抛出错误。

CREATE TABLE Foo (
    Name TEXT NOT NULL,
    Nullable TEXT,
    UNIQUE(Name, Nullable)
);

-- 插入前检查重复的NULL记录
CREATE TRIGGER Foo_Unique_Null_Insert_Check
BEFORE INSERT ON Foo
FOR EACH ROW
WHEN NEW.Nullable IS NULL
BEGIN
    SELECT RAISE(ABORT, 'UNIQUE constraint failed: Foo.Name, Foo.Nullable')
    WHERE EXISTS (
        SELECT 1 FROM Foo WHERE Name = NEW.Name AND Nullable IS NULL
    );
END;

-- 更新前检查重复的NULL记录(排除当前行)
CREATE TRIGGER Foo_Unique_Null_Update_Check
BEFORE UPDATE ON Foo
FOR EACH ROW
WHEN NEW.Nullable IS NULL
BEGIN
    SELECT RAISE(ABORT, 'UNIQUE constraint failed: Foo.Name, Foo.Nullable')
    WHERE EXISTS (
        SELECT 1 FROM Foo WHERE Name = NEW.Name AND Nullable IS NULL AND rowid != NEW.rowid
    );
END;

测试效果:

INSERT INTO Foo(Name) VALUES('baz');
INSERT INTO Foo(Name) VALUES('baz'); -- 触发触发器,抛出错误(满足需求)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:20:53