我很好奇是否可以创建一个表,该表的列永远都不能更改,但是该表的其他列可以。

例如,我可以想象一个CreatedByUser列应该永远不会被更改。已更改。

SQL Server中是否为此提供了内置功能,还是只能通过触发器或其他方式实现?

#1 楼

对于不可更新的列,没有内置的声明性支持(特定的预定义情况(例如IDENTITY除外))

此Connect项请求它但被拒绝。添加DRI以强制使用不可变的列值

UPDATE触发器可能是实现此目的的最可靠方法。它可能会检查IF UPDATE(CreatedByUser)并引发错误,如果为true,则回滚事务。

#2 楼

我已经实现了马丁·史密斯的答案所建议的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的值更改,则拒绝更新。因此,该列可能存在于更新中,如果该值未更改,则该列将通过。 (我需要这样)

评论


如果对于特定记录,AssetTypeID设置为非空值,并且您运行UPDATE Asset SET AssetTypeID = NULL WHERE Asset = the_id,则不会回滚,因为触发器中的WHERE i.AssetTypeID <> d.AssetTypeID的计算结果为false,使该列可编辑。

–克里斯蒂安·韦斯特贝克(Christiaan Westerbeek)
16-3-21在4:35

#3 楼

您可以使用带有派生列的视图。试试这个

create table ro_test(id int primary key, CreatedByUser int)
go
create view v_ro_test
as
select id, CreatedByUser*1 CreatedByUser from ro_test
go

insert into ro_test values(1,10);
update ro_test
set CreatedByUser =11
where id =1;
select * from v_ro_test;
go
--ERROR--
update v_ro_test
set CreatedByUser =10
where id =1;

--BUT--
update v_ro_test
set id =2
where id =1;
select * from v_ro_test;


评论


但是您可以只更新表并更改其值

– Philipp M
13年10月10日在10:06

@Philipp M但是您可以撤消对该表的访问并将其授予视图。不是吗

–msi77
13 Mar 10 '13 at 20:48



#4 楼

我知道这已经很老了,但是有一种方法可以防止列被更新,这就是为什么SQL不需要不可变架构的原因,也是与Microsoft SQL Server从未实现过链接的原因相同的原因。 @Martin Smith。

以下行将阻止您的表被更新或更改。

GRANT INSERT ON database.immutable TO 'user'@'localhost' IDENTIFIED BY 'password';


您可以授予每个每个数据库和表都具有许可权,但仅在需要伪不可变表的地方保留“ INSERT”。希望这可以帮助。

评论


这不能回答问题。 OP要求防止更新单个列。并且您显示了插入,而不是更新。

–安东尼·热诺维斯(Anthony Genovese)
19/12/30在15:14

#5 楼

为什么要更新createdby列?

我将有两列[created_by]和[modified_by]列,其中第一个插入将在记录中插入所有相应的列,而任何后续更新将只更新[modified_by]列(通过应用程序层中的触发器,您可以将更新结构化为仅更改[modified_by]以及相应的列)。

评论


我认为您错过了问题的重点。有人问是否有任何内置支持来强制实施该专栏不应更新。

–马丁·史密斯
2013年3月7日15:21



确实,@ MartinSmith-我们也有一个修改过的列,我只是很好奇是否存在对只读的内置支持

– Philipp M
2013年3月7日16:18