Czy można zrobić tylko jedną kolumnę?

25

Jestem ciekawy, czy można utworzyć tabelę z kolumną, której nigdy nie można zmienić, ale inne kolumny tabeli mogą.

Na przykład mogę sobie wyobrazić CreatedByUserkolumnę, której nigdy nie należy zmieniać.

Czy jest w tym wbudowana funkcja SQL Server, czy jest to możliwe tylko za pomocą wyzwalaczy lub czegoś innego?

Philipp M.
źródło
Nie sądzę, aby istniało inne rozwiązanie poza wdrażaniem wyzwalaczy i zezwalaniem na tworzenie / aktualizację / usuwanie instrukcji tylko poprzez procedury.
Mark S. Rasmussen
@MartinSmith dzięki za link. To chyba odpowiedź na moje pytanie. Zrób więc odpowiedź, a ja ją zaakceptuję.
Philipp M

Odpowiedzi:

19

Nie ma wbudowanej obsługi deklaratywnej dla kolumn, których nie można aktualizować (z wyjątkiem określonych wcześniej zdefiniowanych przypadków, takich jak IDENTITY)

Ten element Connect zażądał tego, ale został odrzucony. Dodaj DRI, aby wymusić niezmienne wartości kolumn

UPDATEWyzwalania będzie prawdopodobnie najbardziej niezawodny sposób na osiągnięcie tego celu. Może to sprawdzić IF UPDATE(CreatedByUser)i zgłosić błąd i wycofać transakcję, jeśli jest to prawda.

Martin Smith
źródło
Link do Archive.org do starego elementu żądania Connect, do którego link znajduje się powyżej: web.archive.org/web/20130402211121/http://connect.microsoft.com/…
Anssssss
7

Wprowadziłem UPDATE TRIGGERpodejście sugerowane w odpowiedzi Martina Smitha w następujący sposób:

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     

(Uwaga: tabela ma kolumnę Klucz podstawowy, o nazwie ID).

Odrzucam aktualizację tylko wtedy, gdy zmienia się wartość AssetTypeID. Tak więc kolumna może być obecna w aktualizacji, a jeśli wartość się nie zmieni, to przejdzie. (Potrzebowałem w ten sposób)

jaraics
źródło
1
Jeśli dla określonego rekordu AssetTypeIDzostanie ustawiona wartość inna niż null, a uruchomisz, UPDATE Asset SET AssetTypeID = NULL WHERE Asset = the_idże nie będzie wycofania, ponieważ WHERE i.AssetTypeID <> d.AssetTypeIDw wyzwalaczu zostanie ustawiona wartość false, pozostawiając tę ​​kolumnę edytowalną.
Christiaan Westerbeek
3

Możesz użyć widoku z kolumną pochodną. Spróbuj tego

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
źródło
Nie jestem pewny co masz na myśli. Czy możesz rozwinąć?
Philipp M,
Ale możesz po prostu zaktualizować tabelę i zmienić jej wartości
Philipp M
1
@Philipp M Ale możesz odwołać dostęp do tabeli i przyznać ją widokowi. Nieprawdaż?
msi77
-3

Dlaczego aktualizujesz utworzoną kolumnę?

Miałbym dwie kolumny: kolumnę [utworzono przez] i [zmodyfikowano przez], gdzie pierwsza wstawka wstawiłaby wszystkie odpowiednie kolumny w rekordzie, a wszelkie kolejne aktualizacje po prostu zaktualizowałyby kolumnę [zmodyfikowano przez] (poprzez włączenie wyzwalacza w aplikacji warstwę, którą możesz tak skonstruować, aby zmienić tylko [zmodyfikowany_by] wraz z odpowiednimi kolumnami)

Apachebeard
źródło
3
Myślę, że nie trafiłeś w sedno pytania. Pytano, czy istnieje jakieś wbudowane wsparcie, które wymuszałoby właśnie to, że kolumna nie powinna być aktualizowana.
Martin Smith
@MartinSmith Dokładnie - mamy również zmodyfikowaną kolumnę, a ja byłem tylko ciekawy, czy istnieje wbudowane wsparcie dla readonly
Philipp M