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

MS SQL触发器实现数据完整性约束的正确性及优化咨询

问题1:抽象实体子表的唯一性校验

表结构

CREATE TABLE a (
 id int NOT NULL PRIMARY KEY,
 date datetime NOT NULL,
 client_id int NOT NULL -- 关联clients表
 -- 实体a的其他属性
);

表a为抽象实体,实际存在8张子表定义具体类型,示例如下:

CREATE TABLE b (
 id int NOT NULL PRIMARY FOREIGN KEY REFERENCES a (id)
 -- 实体b的其他属性
);

CREATE TABLE c (
 id int NOT NULL PRIMARY FOREIGN KEY REFERENCES a (id)
 -- 实体c的其他属性
);

需求与现有实现

需求为:同一客户每日只能拥有一条b类型或c类型记录(可同时拥有b和c)。由于属性分属不同表,无法使用UNIQUE约束,我采用触发器实现各子类型的唯一性校验:

CREATE TRIGGER trigger_b_upsert
ON b
AFTER INSERT, UPDATE
AS  
    IF EXISTS (
        SELECT 1
        FROM a a
        JOIN b b ON a.id = b.id
        WHERE a.client_id IN (
            SELECT client_id
            FROM a a
            JOIN inserted i ON a.id = i.id
        ) AND date IN (
            SELECT date
            FROM a a
            JOIN inserted i ON a.id = i.id
        )
        GROUP BY date, client_id
        HAVING count(*) > 1
    )
   BEGIN
      RAISERROR ('not allowed.', 10, 1)
      ROLLBACK TRANSACTION
   END

c表使用相同逻辑的触发器。

测试案例

案例1:同一客户同日插入两条b类型记录(应触发错误)

INSERT INTO a (id, date, client_id) VALUES (1, '2050-01-01', 1);
INSERT INTO b (id) VALUES (1);
INSERT INTO a (id, date, client_id) VALUES (2, '2050-01-01', 1);
INSERT INTO b (id) VALUES (2); -- 应抛出错误

案例2:同一客户同日插入b和c类型记录(应允许)

INSERT INTO a (id, date, client_id) VALUES (1, '2050-01-01', 1);
INSERT INTO b (id) VALUES (1);
INSERT INTO a (id, date, client_id) VALUES (2, '2050-01-01', 1);
INSERT INTO c (id) VALUES (2); -- 应执行成功

案例3:同一客户不同日期插入多条同类型记录(应允许)

INSERT INTO a (id, date, client_id) VALUES (1, '2050-01-01', 1);
INSERT INTO a (id, date, client_id) VALUES (2, '2050-01-02', 1);
INSERT INTO a (id, date, client_id) VALUES (3, '2050-01-01', 1);
INSERT INTO a (id, date, client_id) VALUES (4, '2050-01-02', 1);
INSERT INTO b (id) VALUES (1);
INSERT INTO b (id) VALUES (2); -- 应执行成功
INSERT INTO c (id) VALUES (3);
INSERT INTO c (id) VALUES (4); -- 应执行成功

疑问

由于我对MS SQL并不熟悉,想请教该方案是否正确,是否存在性能问题及优化方向。


问题2:关联表的client_id一致性校验

补充表结构

-- 另一张关联客户的表,与a无关
CREATE TABLE e (
 id int NOT NULL PRIMARY KEY,
 client_id int NOT NULL -- 关联clients表
 -- 实体e的其他属性
);

CREATE TABLE d (
 id int NOT NULL PRIMARY FOREIGN KEY REFERENCES a (id),
 e_id int NOT NULL PRIMARY FOREIGN KEY REFERENCES e (id)
 -- 实体d的其他属性
);

需求与现有实现

当前结构允许插入a、d关联e的记录,但a.client_id与e.client_id可能不一致,该场景需禁止。我编写了如下触发器:

CREATE TRIGGER trigger_d_upsert
ON d
AFTER INSERT, UPDATE
AS     
    IF EXISTS (
        SELECT 1
        FROM a a
        JOIN inserted i ON a.id = i.id
        JOIN e e on e.id = i.e_id
        WHERE e.client_id != a.client_id
    )
   BEGIN
      RAISERROR ('Conflict client_id.', 10, 1)
      ROLLBACK TRANSACTION
   END 

疑问

请问是否有更优的解决方案?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:17:34