2009-06-06 12 views
10

W języku SQL istnieje sposób na wymuszenie, że tylko jedna kolumna z grupy kolumn ma wartość, a pozostałe mają wartość zerową? Może ograniczenie lub spust? Tego typu rzeczy mogą dotyczyć tabeli odnośników, ale czy istnieją alternatywne projekty tabel, które mogłyby to ulepszyć?SQL: jak wymusić ustawienie tylko jednej kolumny w grupie kolumn

Na przykład:

ID OtherTable1ID OtherTable2ID OtherTable3ID 
----------------------------------------------------- 
1  23    NULL    NULL 
2  NULL    45    NULL 
3  33    55    NULL -- NOT ALLOWED 

Głównym problemem jest to, że kolumny te są FKS do innych tabel, więc nie mogę zwinąć je w dół do pojedynczej kolumny.

Używam programu SQL Server, ale każda odpowiedź wystarczy.

+0

Dzięki za aktualizację, ale możesz chcieć podać więcej szczegółów na temat projektu bazy danych. Na przykład, czy jest to sytuacja podtytułowa, w której ta tabela może być podtypem jednej i tylko jednej z pozostałych tabel. Czy dozwolone jest także zerowanie wszystkich kolumn "Inne"? –

+0

Wygląda jak tabela odnośników. Czy to w zasadzie oznacza, że ​​jeśli dodasz jeszcze jeden FK, dodasz do niego jeszcze jedną kolumnę? –

+0

Tak, to dla mnie po prostu tablica porównawcza. Jeśli muszę dodać kolejny parametr wyszukiwania, będę musiał dodać kolejną kolumnę FK. Czy istnieją lepsze sposoby osiągnięcia tego? –

Odpowiedz

13

@ proponowanych ograniczeń tvanfosson pracują OK dla trzech kolumn, ale dla ogółu Wolę

(cast(col1 is not null, int) + 
cast(col2 is not null, int) + 
cast(col3 is not null, int)) = 1 

ponieważ uogólnia lepiej do dowolnej liczby kolumn z „liniowo rośnie” (zamiast „kwadratowo rośnie”) kwota kodowanie (jest jeszcze bardziej w dialektach SQL, które nie wymagają jawnego przesyłania wartości boolean do bitów int, ale nie jestem pewien, czy SQL Server jest jednym z nich).

+4

Dla SQL Server prawdopodobnie to by działało lepiej ... (przypadek, gdy col1 NIE JEST NULL to 1 inny 0 koniec + przypadek, gdy col2 NIE JEST NULL to 1 inny 0 koniec <2) –

+1

@Glen Little: Zgadzam się z oferowaną składnią, ale uważam, że porównanie dla przypadku OP powinno być nadal "... = 1'. –

6

Ograniczenie takie jak następujące powinno działać:

(column1 is null and column2 is null) 
    or (column1 is null and column3 is null) 
    or (column2 is null and column3 is null) 

nie spowoduje, że zawiera niezerowym kolumny jednak. Aby to zrobić dodać kolejne ograniczenie:

column1 is not null 
    or column2 is not null 
    or column3 is not null 
0

To brzmi dla mnie jak jeśli chcesz używać jednej kolumny do zestawu tych rzeczy. Być może możesz użyć jakiegoś tagu, aby powiedzieć, że jest to Foo,3 lub Bar,7 lub Baz,9?

+0

Powinienem był to wyjaśnić w moim pytaniu, ale problemem, z którym stoję, jest to, że kolumny są FK do innych tabel. Pozwól mi zaktualizować moje pytanie, przepraszam –

+0

Ah, teraz robi się interesująco! Pozwól mi trochę pomyśleć, ale brzmi to tak, jakby to był problem z kiepską implementacją RDBMS. Niestety, w tym sensie, nie sądzę, że jest tam dobry ... –

+0

(Aby wyjaśnić, nie ma powodu, dla którego nie powinieneś być w stanie zadeklarować typu kolumny jako "odniesienia do tego lub odniesienie do tego, lub odniesienie do drugiego, "z pełnym wsparciem FK na tym wszystkim, ale obecne systemy DBMS nigdzie nie zbliżają się do tego.) –

1
CREATE TABLE Repro.Entity 
(
    entityId INTEGER IDENTITY (1, 1) NOT NULL, 
    column1 INTEGER, 
    column2 INTEGER, 
    column3 INTEGER, 
    CONSTRAINT Entity_PK PRIMARY KEY(entityId), 
    CONSTRAINT Entity_CK CHECK(
     (column1 IS NOT NULL AND column2 IS NULL AND column3 IS NULL) OR 
     (column1 IS NULL AND column2 IS NOT NULL AND column3 IS NULL) OR 
     (column1 IS NULL AND column2 IS NULL AND column3 IS NOT NULL)) 
) 
1

Dla mnie wygląda to na złą decyzję projektową. Ponieważ ID jest kluczem podstawowym w tej tabeli, będzie to prawna wartość dla wszystkich relacji klucza obcego. Oznacza to, że musisz ciężko pracować w warstwie przedniej/biznesowej, aby zagwarantować, że wartości mieszczą się w akceptowalnym zakresie.

Na przykład, sposób konfigurowania tabel jest całkowicie zgodny z prawem, aby tabela 2 używała 1 jako wartości odnośnika zamiast 2, której ma używać - a baza danych nie będzie jej pułapką.

Prawdopodobnie nie pójdę tą drogą. Po prostu utworzę schemat o nazwie odnośniki i utworzę jedną tabelę odnośników na wartość odnośnika. W ten sposób baza danych odpowiednio wymusi wszystkie ograniczenia.

Sposób, w jaki skonfigurowałeś tabelę odnośników, obecnie ograniczasz się do liczby całkowitych kluczy obcych. W niektórych przypadkach może to nie być dobry pomysł - na przykład chcesz zapisać kod kraju/kody dla stanu, a nie liczby całkowite, które je reprezentują.

+0

Ja też wolę unikać kolumn NULLable, ale projekt OP (podlegający ograniczeniom działającym w żądany sposób) ma przewagę nad twoją (zakładając, że dobrze zrozumiałem), ponieważ może napisać ograniczenie, aby wymusić dokładnie jedną wartość nie-NULL, podczas gdy Twój może mieć sytuację, w której w tabelach referencyjnych może znajdować się zero wierszy, chyba że użyjesz własnych "rozproszonych kluczy obcych" (google Hugh Darwen) za pomocą wyzwalaczy (lub podobnych). – onedaywhen

Powiązane problemy