SQL 服务器中的 FD 保留触发器出错

Error in FD-preserving trigger in SQL Server

考虑函数依赖 B->C 的 R(A,B,C)。 我写了下面的触发器来保存 FD。

create trigger t1 on R after insert
as
if exists(select B from R
group by B 
having count(distinct C)>1 
)
print 'B->C FD does not permit!'
rollback;

它工作正常但出现错误:

The transaction ended in the trigger. The batch has been aborted.

如何catch/resolve这个错误?

您可以使用INSTEAD OF触发器:

CREATE TRIGGER t1 on R
INSTEAD OF INSERT
AS
BEGIN
    IF EXISTS(
        SELECT B 
        FROM (
        SELECT B, C 
        FROM R 
        UNION ALL 
        SELECT B, C 
        FROM INSERTED) AS T 
        GROUP BY B 
        HAVING COUNT(DISTINCT C) > 1
    )
    PRINT 'B->C FD does not permit!'
    ELSE
    INSERT INTO R SELECT * FROM inserted
END;
GO

另一种方式:

CREATE TRIGGER t1 on R
AFTER INSERT
AS
        IF EXISTS(
            SELECT B 
            FROM (
            SELECT B, C 
            FROM R 
            UNION ALL 
            SELECT B, C 
            FROM INSERTED) AS T 
            GROUP BY B 
            HAVING COUNT(DISTINCT C) > 1
        )
BEGIN
PRINT 'B->C FD does not permit!'
ROLLBACK TRANSACTION;
RETURN 
END;
GO

触发器中的查询与您插入的内容无关 inserted table.

create trigger t1 on R after insert
as
if exists(select B from R
where B  in (select B from inserted) --"is" was mistype
group by B 
having count( C)>1 --distinct allows to insert same (B,C) pairs
)
begin
print 'B->C FD does not permit!'
rollback;
end

-- insert fresh data 
insert R (A,B,C)
values
(1,'ab','cd'),
(2,'cd','ef')
--passed
-- insert more
insert R (A,B,C)
values
(3,'abc','cd'),
(4,'cde','ef'),
(5,'ab','qq')
-- failed with message:
B->C FD does not permit!
Msg 3609, Level 16, State 1, Line 16
The transaction ended in the trigger. The batch has been aborted.
-- As Expected