不可变的SQL列

时间:2012-08-28 19:50:02

标签: sql sql-server sql-server-2008 ddl

是否可以在MSSQL中标记列immutable

似乎它将是一个有用的DDL功能;一旦在一行中设置了一个值('row'被定义为一个特定的主键值关系),如果没有删除该行就无法更改。

显然(像大多数事情一样)这在应用程序层中是可行的,但SQL DDL的一半乐趣是错误检查应用程序代码。

5 个答案:

答案 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 可以为所有三列插入行和供应值。他还可以更新idcol2列,但不能更新col1列。

db_owner(可能是表的创建者/所有者)总是可以更新所有列。我不知道是否有办法撤销这些特权。

答案 1 :(得分:5)

不,SQL Server中没有这样的功能。

我能想到的最接近的是表上的更新触发器,它检查特定列中的值是否与INSERTEDDELETED逻辑表相同,并拒绝更改的更新行。

答案 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)

另一种方法是拒绝对表的更新权限,并创建一个不更新不可变字段的存储过程(用户确实有权执行)。