Est-il possible de faire une seule colonne en lecture seule?

25

Je suis curieux de savoir s'il est possible de créer une table avec une colonne qui ne peut jamais être modifiée, mais les autres colonnes de la table le peuvent.

Par exemple, je pourrais imaginer une CreatedByUsercolonne qui ne devrait jamais être modifiée.

Y a-t-il une fonctionnalité intégrée dans SQL Server pour cela, ou est-ce uniquement possible via des déclencheurs ou autre chose?

Philipp M
la source
Je ne crois pas qu'il existe d'autre moyen que d'implémenter des déclencheurs et de n'autoriser la création / mise à jour / suppression d'instructions que par le biais de procédures.
Mark S. Rasmussen
@MartinSmith merci, pour le lien. Je suppose que ce serait la réponse à ma question. Alors faites-en une réponse et je l'accepterai.
Philipp M

Réponses:

19

Il n'y a pas de prise en charge déclarative intégrée pour les colonnes non modifiables (sauf pour des cas prédéfinis spécifiques tels que IDENTITY)

Cet élément Connect l'a demandé mais a été rejeté. Ajouter DRI pour appliquer des valeurs de colonne immuables

Un UPDATEdéclencheur serait probablement le moyen le plus robuste d'y parvenir. Il pourrait vérifier IF UPDATE(CreatedByUser)et déclencher une erreur et annuler la transaction s'il est vrai.

Martin Smith
la source
Lien Archive.org vers l'ancien élément de demande Connect lié ci-dessus: web.archive.org/web/20130402211121/http://connect.microsoft.com/…
Anssssss
7

J'ai mis en œuvre l' UPDATE TRIGGERapproche suggérée par la réponse de Martin Smith comme suit:

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     

(Remarque: la table a une colonne de clé primaire, appelée ID).

Je ne rejette la mise à jour que si la valeur de AssetTypeID change. Ainsi, la colonne pourrait être présente dans une mise à jour, et si la valeur ne changeait pas, elle passerait. (J'avais besoin de cette façon)

jaraics
la source
1
Si pour un enregistrement particulier, le AssetTypeIDest défini sur une valeur non nulle et que vous exécutez UPDATE Asset SET AssetTypeID = NULL WHERE Asset = the_idqu'il n'y aurait pas de restauration, car WHERE i.AssetTypeID <> d.AssetTypeIDdans le déclencheur serait évalué à faux, laissant cette colonne modifiable.
Christiaan Westerbeek
3

Vous pouvez utiliser une vue avec une colonne dérivée. Essaye ça

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
la source
Je ne sais pas ce que tu veux dire. Peux-tu élaborer?
Philipp M
Mais vous pouvez simplement mettre à jour le tableau et modifier ses valeurs
Philipp M
1
@Philipp M Mais vous pouvez révoquer l'accès à la table et l'octroyer à la vue. N'est ce pas?
msi77
-3

Pourquoi mettez-vous à jour la colonne createdby?

J'aurais deux colonnes, une [created_by] et une colonne [modified_by], où la première insertion insérerait toutes les colonnes respectives dans l'enregistrement, et toutes les mises à jour ultérieures mettraient simplement à jour la colonne [modified_by] (via un déclencheur dans l'application) couche, vous pouvez structurer votre mise à jour pour ne changer que le [modified_by], ainsi que vos colonnes respectives)

apachebeard
la source
3
Je pense que vous avez manqué le point de la question. Il demandait s'il y avait un support intégré pour imposer précisément que la colonne ne devrait pas être modifiable.
Martin Smith
@MartinSmith Exactement - nous avons également une colonne modifiée et j'étais seulement curieux de savoir s'il existe un support intégré pour readonly
Philipp M