Zakładając, że dobrze zrozumiałem twój scenariusz, nazwałbym właściwy sposób, aby to zrobić:
Zacznij od opisu swojej bazy danych na wyższym poziomie! Masz pracowników, a pracownicy mogą być pracownikami „ce” i pracownikami „sn” (cokolwiek to jest). W kategoriach obiektowych istnieje klasa „pracownik” z dwiema podklasami nazywanymi „pracownikiem ce” i „pracownikiem sn”.
Następnie przełożyć tego opisu wyższego poziomu do trzech tabelach: employees
, employees_ce
i employees_sn
:
employees(id, name)
employees_ce(id, ce-specific stuff)
employees_sn(id, sn-specific stuff)
Ponieważ wszyscy pracownicy są pracownikami (prawda!), Każdy pracownik będzie miał wiersz w employees
tabeli. Pracownicy „ce” również mają wiersz w employees_ce
tabeli, a pracownicy „sn” również mają wiersz w employees_sn
tabeli. employees_ce.id
jest kluczem obcym do employees.id
, tak jak employees_sn.id
jest.
Aby odnieść się do pracownika dowolnego rodzaju (ce lub sn), zapoznaj się z employees
tabelą. Oznacza to, że klucz obcy, z którym miałeś problem, powinien odnosić się do tej tabeli!
Prawdopodobnie możesz dodać dwa ograniczenia klucza obcego (szczerze: nigdy tego nie próbowałem), ale wtedy nalegałby, aby wiersz nadrzędny istniał w obu tabelach.
Zamiast tego prawdopodobnie chcesz utworzyć nadtyp dla dwóch podtypów pracowników, a następnie wskazać tam klucz obcy. (Zakładając oczywiście, że masz dobry powód, aby podzielić te dwa typy pracowników).
type
w tabeli pracowników byłobyce
lubsn
.źródło
LEFT JOIN
wszystkie, jeśli jest ich mało. Gdy nie używasz tabeli bazowej „pracownika”, nie można zadeklarować klucza podstawowego (ponieważ odwołuje się on do tabeli A lub tabeli B lub…); teraz może być. Mądrość rozszczepieniaemployees_ce
iemployees_sn
została przyjęta, a założenie to zostało odnotowane.Właściwie robię to sam. Mam tabelę o nazwie „Komentarze”, która zawiera komentarze do rekordów w 3 innych tabelach. Żadne rozwiązanie nie obsługuje w rzeczywistości wszystkiego, czego prawdopodobnie chcesz. W twoim przypadku zrobiłbyś to:
Rozwiązanie 1:
Dodaj pole tinyint do workers_ce i workers_sn, które ma domyślną wartość, która jest inna w każdej tabeli (to pole reprezentuje `` identyfikator tabeli '', więc nazwiemy je tid_ce & tid_sn)
Utwórz unikalny indeks dla każdej tabeli, używając PK tabeli i pola identyfikatora tabeli.
Dodaj pole tinyint do tabeli „Deductions”, aby przechowywać drugą połowę klucza obcego (identyfikator tabeli)
Utwórz 2 klucze obce w swojej tabeli „Odliczenia” (nie możesz wymusić integralności referencyjnej, ponieważ jeden klucz będzie ważny lub drugi ... ale nigdy oba:
ALTER TABLE [dbo].[Deductions] WITH NOCHECK ADD CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid]) REFERENCES [dbo].[employees_ce] ([empid], [tid]) NOT FOR REPLICATION GO ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce] GO ALTER TABLE [dbo].[Deductions] WITH NOCHECK ADD CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid]) REFERENCES [dbo].[employees_sn] ([empid], [tid]) NOT FOR REPLICATION GO ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn] GO employees_ce -------------- empid name tid khce1 prince 1 employees_sn ---------------- empid name tid khsn1 princess 2 deductions ---------------------- id tid name khce1 1 gold khsn1 2 silver ** id + tid creates a unique index **
Rozwiązanie 2: To rozwiązanie pozwala zachować referencyjną integralność: 1. Utwórz drugie pole klucza obcego w tabeli „Odliczenia”, zezwól na wartości Null w obu kluczach obcych i utwórz normalne klucze obce:
employees_ce -------------- empid name khce1 prince employees_sn ---------------- empid name khsn1 princess deductions ---------------------- idce idsn name khce1 *NULL* gold *NULL* khsn1 silver
Integralność jest sprawdzana tylko wtedy, gdy kolumna nie jest pusta, więc można zachować integralność referencyjną.
źródło
Wiem, że to od dawna zastój temat, ale na wypadek, gdyby ktoś szukał tutaj, to jak radzę sobie z wielotabelowymi kluczami obcymi. Dzięki tej technice nie masz żadnych wymuszonych przez DBA operacji kaskadowych, więc upewnij się, że zajmujesz się nimi
DELETE
w swoim kodzie.Przykład SO Op wyglądałby tak
deductions -------------- type id name 1 khce1 gold 2 khsn1 silver types --------------------- 1 employees_ce 2 employees_sn
źródło
Technicznie możliwe. Prawdopodobnie odnosiłbyś się do workers_ce w odliczeniach i workers_sn. Ale dlaczego nie połączysz workers_sn i workers_ce? Nie widzę powodu, dla którego masz dwa stoliki. Nikt do wielu relacji. I (nie w tym przykładzie) wiele kolumn.
Jeśli robisz dwa odwołania dla jednej kolumny, pracownik musi mieć wpis w obu tabelach.
źródło
Tak to mozliwe. Będziesz musiał zdefiniować 2 FK dla 3. tabeli. Każdy FK wskazujący wymagane pola jednej tabeli (tj. 1 FK na tabelę zagraniczną).
źródło
Zakładając, że z jakiegoś powodu musisz mieć dwie tabele dla dwóch typów pracowników, rozszerzę odpowiedź vmarquez:
Schemat:
Dane w potrąceniach:
Umożliwiłoby to odliczenie wskazujące na dowolną inną tabelę w schemacie. Ten rodzaj relacji nie jest obsługiwany przez ograniczenia na poziomie bazy danych, IIRC, więc musisz upewnić się, że Twoja aplikacja prawidłowo zarządza ograniczeniem (co czyni ją bardziej uciążliwą, jeśli masz kilka różnych aplikacji / usług trafiających do tej samej bazy danych).
źródło