是否可以在MSSQL中标记列immutable
?
似乎它将是一个有用的DDL功能;一旦在一行中设置了一个值('row'被定义为一个特定的主键值关系),如果没有删除该行就无法更改。
显然(像大多数事情一样)这在应用程序层中是可行的,但SQL DDL的一半乐趣是错误检查应用程序代码。
答案 0 :(得分:9)
如果执行DML的用户不是对象的所有者而不是数据库本身的“db_owner”,则只能授予“insert”权限,但不能为该表授予更新权限:
假设一张表id, col1, col2
grant insert, select, delete on the_table to the_user;
grant update (id, col2) on the_table to the_user;
使用这些授权 the_user 可以为所有三列插入行和供应值。他还可以更新id
和col2
列,但不能更新col1
列。
db_owner(可能是表的创建者/所有者)总是可以更新所有列。我不知道是否有办法撤销这些特权。
答案 1 :(得分:5)
不,SQL Server中没有这样的功能。
我能想到的最接近的是表上的更新触发器,它检查特定列中的值是否与INSERTED
和DELETED
逻辑表相同,并拒绝更改的更新行。
答案 2 :(得分:4)
可以,使用这样的UPDATE TRIGGER:
CREATE TRIGGER trgAfterUpdateAsset ON dbo.Asset
FOR UPDATE AS
IF UPDATE(AssetTypeID) AND EXISTS (SELECT * FROM inserted i JOIN deleted d ON i.ID = d.ID WHERE i.AssetTypeID <> d.AssetTypeID)
BEGIN
RAISERROR ('AssetTypeID cannot change.', 16, 1);
ROLLBACK TRAN
END
(注意:该表有一个主键列,称为ID)。
如果AssetTypeID的值发生变化,我只会拒绝更新。因此,列可以存在于更新中,如果它指定了旧值,则它将通过。 (我需要这样的方式)
答案 3 :(得分:3)
据我所知,DDL无法做到这一点。但是,您可以实现BEFORE UPDATE触发器以满足您的要求。在BEFORE UPDATE触发器中,您可以引发异常或执行任何操作而不是更新行。
答案 4 :(得分:2)
另一种方法是拒绝对表的更新权限,并创建一个不更新不可变字段的存储过程(用户确实有权执行)。