Можно ли сделать один столбец доступным только для чтения?

25

Мне любопытно, возможно ли создать таблицу со столбцом, который никогда не может быть изменен, но другие столбцы таблицы могут.

Например, я мог бы представить CreatedByUserстолбец, который никогда не следует менять.

Есть ли для этого встроенные функции в SQL Server, или это возможно только через триггеры или что-то еще?

Филипп М
источник
Я не верю, что есть какой-то способ обойти это, кроме реализации триггеров и разрешения только создания / обновления / удаления операторов с помощью процедур.
Марк С. Расмуссен
@MartinSmith спасибо, за ссылку. Я думаю, что это будет ответом на мой вопрос. Так что сделайте ответ, и я приму это.
Филипп М

Ответы:

19

Нет встроенной декларативной поддержки не обновляемых столбцов (за исключением определенных предопределенных случаев, таких как IDENTITY)

Этот элемент подключения запросил его, но был отклонен. Добавьте DRI, чтобы обеспечить неизменность значений столбцов

UPDATEТриггер, вероятно , будет самым надежным способом достижения этой цели. Это может проверить IF UPDATE(CreatedByUser)и вызвать ошибку и откатить транзакцию, если истина.

Мартин Смит
источник
Ссылка Archive.org на старый элемент запроса на подключение, указанный выше: web.archive.org/web/20130402211121/http://connect.microsoft.com/…
Anssssss
7

Я реализовал 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. Таким образом, столбец может присутствовать в обновлении, и если значение не изменится, то оно пройдет. (Мне нужно было так)

jaraics
источник
1
Если для конкретной записи AssetTypeIDзадано ненулевое значение, и вы запускаете UPDATE Asset SET AssetTypeID = NULL WHERE Asset = the_id, что отката не будет, потому что WHERE i.AssetTypeID <> d.AssetTypeIDв триггере будет значение false, оставляя этот столбец редактируемым.
Кристиан Вестербик
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;
msi77
источник
Я не уверен, что ты имеешь в виду. Можете ли вы уточнить?
Филипп М
Но вы можете просто обновить таблицу и изменить ее значения
Philipp M
1
@Philipp M Но вы можете отозвать доступ к таблице и предоставить ее представлению. Не так ли?
msi77
-3

Почему вы обновляете созданную колонку?

У меня будет два столбца: [create_by] и столбец [ified_by], где при первой вставке будут вставлены все соответствующие столбцы в записи, а при любых последующих обновлениях будет просто обновляться столбец [ified_by] (через триггер в приложении. слой вы можете структурировать свое обновление, чтобы изменить только [updated_by], вместе с вашими соответствующими столбцами)

apachebeard
источник
3
Я думаю, что вы пропустили суть вопроса. Он спрашивал , есть ли встроенная поддержка для обеспечения точности , что столбец должен не быть обновляемым.
Мартин Смит
@MartinSmith Точно - у нас также есть измененный столбец, и мне было только интересно узнать, существует ли встроенная поддержка readonly
Philipp M