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

标签 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

我期望如果我更新表中的某些值,则在插入中,我不更新的列的值将为 NULL,但事实并非如此。我在某处读到,我需要同时查看 inserteddeleted 来查看这些值是否发生变化。所以我的问题是,我可以在不使用光标的情况下检查它吗?

谢谢。

最佳答案

你可以做

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 是否实际更新。

例如,下表中 UPDATE 触发器中的 INSERTEDDELETED 表对于 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

关于sql-server - 创建一个不允许更新主键列的触发器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15586192/

相关文章:

Postgresql插入触发器设置值

mysql - 我在哪里写MySQL触发器

java - 通配符转义 JPA 规范

sql - 在 SQL 中实现递归查询

c# - 存储在数据库中时图像的大小

button - 如何从 ui 操作触发 ServiceNow 工作流程?

sql - 在没有检查约束的情况下更改列长度

mysql - 如何更新MYSQL数据库所有表的公共(public)字段长度?

C# Winforms 控件 - DataGridView - 更新数据库

如果值不为空,则更新数据库的 SQL 查询?