12

immutable是否可以在 MSSQL中标记列?

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

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

4

5 回答 5

14

如果执行 DML 的用户不是对象的所有者,也不是数据库本身中的“db_owner”,您可以只授予“插入”权限,但不授予该表的更新权限:

假设一张桌子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(也可能是表的创建者/所有者)始终可以更新所有列。我不知道是否有办法从这些角色中撤销该特权。

于 2012-08-28T20:27:19.403 回答
9

这是可能的,使用这样的 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 的值发生变化,我只会拒绝更新。因此,该列可能存在于更新中,并且如果它指定了旧值,那么它将通过。(我需要这种方式)

于 2014-03-25T12:40:54.890 回答
8

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

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

于 2012-08-28T19:54:59.037 回答
3

据我所知,这对于 DDL 是不可能的。但是,您可以实现 BEFORE UPDATE 触发器以满足您的要求。在 BEFORE UPDATE 触发器中,您可以引发异常或做任何您想做的事情,而不是更新行。

于 2012-08-28T19:54:21.613 回答
2

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

于 2012-08-28T22:29:22.523 回答