创建一个不允许更新主键列的触发器

时间:2013-03-23 11:25:20

标签: sql-server triggers sql-update composite-primary-key

我的表有一个由3列组成的复合主键,比方说A,B,C。我想创建一个触发器,UPDATE将检查这三列是否会被更改。这是我到目前为止所做的,但它似乎不起作用:

CREATE TRIGGER TableTrigger
ON Table
AFTER INSERT, UPDATE AS
BEGIN
    IF (EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted))
    BEGIN
    -- Update Operation
    IF (SELECT COUNT(*) FROM inserted WHERE A IS NOT NULL OR B IS NOT NULL OR C IS NOT NULL) > 0
    BEGIN
        RAISERROR('Error, you cannot change Primary Key columns', 16, 1)
        ROLLBACK
        RETURN
    END
END

我期待如果我更新表中的某些值,在inserted中,列的值不会更新为NULL,但它不是那样的。我在某个地方读到了我需要查看inserteddeleted以查看这些值是否发生变化的情况。所以我的问题是这个,我可以不使用光标来检查吗?

谢谢。

1 个答案:

答案 0 :(得分:3)

你可以做到

CREATE TRIGGER TableTrigger
ON Table
AFTER UPDATE AS
BEGIN
IF UPDATE(A) OR UPDATE(B) OR UPDATE(C) 
    BEGIN
        RAISERROR('Error, you cannot change Primary Key columns', 16, 1)
        ROLLBACK
        RETURN
    END
END

或拒绝对这些列的更新权限。

两种方法都会拒绝任何更新PK列的尝试,无论这些值是否实际发生变化。 SQL Server没有行级触发器,除非表中有IDENTITY列(保证不可变),否则没有可靠的方法来告知触发器是否实际更新了PK。

例如,下表中INSERTED触发器中的DELETEDUPDATE表对于UPDATE语句都是相同的。

CREATE TABLE T(C INT PRIMARY KEY);

INSERT INTO T VALUES (1),(-1)

/*Both values swapped*/
UPDATE T SET C = -C

/*Both values left the same*/
UPDATE T SET C = C