Używam programu SQL Server 2005. Chcę ograniczyć wartości w kolumnie, aby były unikalne, jednocześnie zezwalając na wartości NULLS.
Moje obecne rozwiązanie obejmuje unikalny indeks takiego widoku:
CREATE VIEW vw_unq WITH SCHEMABINDING AS
SELECT Column1
FROM MyTable
WHERE Column1 IS NOT NULL
CREATE UNIQUE CLUSTERED INDEX unq_idx ON vw_unq (Column1)
Jakieś lepsze pomysły?
sql
sql-server
indexing
constraints
unique
Nuno G
źródło
źródło
Odpowiedzi:
Jestem prawie pewien, że nie możesz tego zrobić, ponieważ narusza to cel unikatów.
Jednak ta osoba wydaje się dobrze obejść: http://sqlservercodebook.blogspot.com/2008/04/multiple-null-values-in-unique-index-in.html
źródło
Korzystając z SQL Server 2008, można utworzyć filtrowany indeks: http://msdn.microsoft.com/en-us/library/cc280372.aspx . (Widzę, że Simon dodał to jako komentarz, ale pomyślałem, że zasługuje na własną odpowiedź, ponieważ komentarz łatwo przeoczyć.)
Inną opcją jest wyzwalacz do sprawdzenia niepowtarzalności, ale może to wpłynąć na wydajność.
źródło
create unique index UIX on MyTable (Column1) where Column1 is not null
ANSI_NULLS
jestON
, w przeciwnym razie podczas próby wstawienia danych wystąpi błąd.Ta sztuczka z kolumną obliczeniową jest powszechnie znana jako „nullbuster”; moje notatki uznają Steve Kass:
źródło
Ściśle mówiąc, unikatowa kolumna dopuszczająca wartość null (lub zestaw kolumn) może mieć wartość NULL (lub rekord wartości NULL) tylko raz, ponieważ posiadanie tej samej wartości (i obejmuje to NULL) więcej niż raz w oczywisty sposób narusza ograniczenie unikalności.
Nie oznacza to jednak, że koncepcja „unikatowych kolumn dopuszczających wartość null” jest prawidłowa; aby faktycznie zaimplementować go w dowolnej relacyjnej bazie danych, musimy tylko pamiętać, że tego rodzaju bazy danych mają być znormalizowane, aby poprawnie działać, a normalizacja zwykle obejmuje dodanie kilku (nie-encji) dodatkowych tabel w celu ustalenia relacji między jednostkami .
Spójrzmy na podstawowy przykład, biorąc pod uwagę tylko jedną „unikalną kolumnę dopuszczającą wartość null”, łatwo jest ją rozszerzyć na więcej takich kolumn.
Załóżmy, że mamy informacje reprezentowane przez taką tabelę:
Możemy to zrobić, oddzielając wartość uniqnull i dodając drugą tabelę, aby ustanowić relację między wartościami unikatowymi i the_entity (zamiast mieć unikalną wartość „wewnątrz” elementu the_entity):
Aby skojarzyć wartość uniqnull z wierszem w the_entity, musimy również dodać wiersz w the_relation.
Dla wierszy w the_entity, w których nie są skojarzone żadne unikalne wartości puste (tj. Dla tych, które umieścilibyśmy NULL w the_entity_incorrect), po prostu nie dodajemy wiersza w the_relation.
Zauważ, że wartości dla uniqnull będą unikalne dla całego the_relation, a także zauważ, że dla każdej wartości w the_entity może być co najwyżej jedna wartość w the_relation, ponieważ wymuszają to klucze podstawowy i obcy.
Następnie, jeśli wartość 5 dla unikqnull ma być skojarzona z identyfikatorem the_entity równym 3, musimy:
A jeśli wartość id równa 10 dla the_entity nie ma unikalnego odpowiednika, robimy tylko:
Aby zdenormalizować te informacje i uzyskać dane, które mogłaby zawierać tabela taka jak the_entity_incorrect, musimy:
Operator „left external join” zapewnia, że w wyniku pojawią się wszystkie wiersze z the_entity, umieszczając NULL w unikatowej kolumnie, gdy w the_relation nie ma pasujących kolumn.
Pamiętaj, że każdy wysiłek poświęcony przez kilka dni (lub tygodni lub miesięcy) na zaprojektowanie dobrze znormalizowanej bazy danych (i odpowiednich denormalizujących poglądów i procedur) pozwoli Ci zaoszczędzić lata (lub dekady) bólu i zmarnowanych zasobów.
źródło