Po pierwsze, istnieje reguła projektowa, w której tabela modeluje jeden typ obiektu lub relację między typami jednostek, ale nie oba. Dlatego wyobrażam sobie trzy tabele: Media
(podmiot), Idea
(podmiot) i IdeasMedia
(relacja). p.s. wiesz, że liczba pojedyncza "mediów" jest "średnia", prawda? :)
Oto niektóre standardowe SQL DDL-92, która skupia się wyłącznie na klucze:
CREATE TABLE Media (MediaID INTEGER NOT NULL UNIQUE);
CREATE TABLE Idea (IdeaID INTEGER NOT NULL UNIQUE);
CREATE TABLE IdeasMedia
(
MediaID INTEGER NOT NULL REFERENCES Media (MediaID),
IdeaID INTEGER NOT NULL REFERENCES Idea (IdeaID)
);
CREATE ASSERTION Idea_must_have_media DEFERRABLE
CHECK (
NOT EXISTS (
SELECT *
FROM Idea AS i
WHERE NOT EXISTS (
SELECT *
FROM IdeasMedia AS im
WHERE im.MediaID = i.IdeaID
)
)
);
Jest „jajka i kury” scenariusz tutaj: nie można utworzyć pomysł z bez odwoływania IdeasMedia
ale może Stwórz IdeasMedia
bez tworzenia Idea
!
Idealnym (opartym na ustawieniach) rozwiązaniem byłoby SQL Standard do obsługi wielu zadań, np.
INSERT INTO Media (MediaID) VALUES (22),
INSERT INTO Idea (IdeaID) VALUES (55),
INSERT INTO IdeasMedia (MediaID, IdeaID) VALUES (22, 55);
gdzie średnik wskazuje SQL oświadczenie granicę, przy której są zaznaczone ograniczenia punkt i przecinki oznaczający podrzędne oświadczenia.
Niestety, nie ma planów dodania tego opartego na zestawie paradygmatu do standardu SQL.
SQL-92 (proceduralne) Rozwiązaniem tego problemu jest następujący:
BEGIN TRANSACTION;
INSERT INTO Media (MediaID) VALUES (22);
SET CONSTRAINTS Idea_must_have_media DEFERRED;
-- omit the above if the constraint was declared as INITIALLY DEFERRED.
INSERT INTO Idea (IdeaID) VALUES (55);
INSERT INTO IdeasMedia (MediaID, IdeaID) VALUES (55, 22);
SET CONSTRAINTS Idea_must_have_media IMMEDIATE;
-- above may be omitted: constraints are checked at commit anyhow.
COMMIT TRANSACTION;
Niestety, SQL Server nie obsługuje CREATE ASSERTION
ani CHECK
ograniczenia, które mogą odnosić się do innych tabel ani odroczeniu ograniczeń!
Osobiście bym sobie z tym poradzić w SQL Server w następujący sposób:
- Tworzenie 'pomocnik' przechowywane procs dodawać, zmieniać i usuwać
Ideas
i ich odpowiednie IdeasMedia
relacje.
- Usuń uprawnienia aktualizacji z tabel, aby zmusić użytkowników do korzystania z procedur .
- Możliwe jest użycie wyzwalaczy do obsługi scenariuszy podczas usuwania encji
Media
i Idea
.
Z pewnością ta (ponownie proceduralna) implementacja jest daleko od idealnego podejścia opartego na zestawie, co prawdopodobnie tłumaczy, dlaczego większość programistów kodu SQL przymyka oko na wymóg relacji 1: 1.N, a zamiast tego załóżmy, że projektant miał na myśli 1: 0..N !!
Nie jestem pewien, w jaki sposób można to zrobić, przechowując 'Media' w oddzielnej tabeli: w jaki sposób wstawi się dane? Musisz wstawić najpierw do jednej tabeli, a potem do drugiej. Możesz spróbować umieścić pierwsze "Media" w "Idea" (de-normalizacji) i zadeklarować pola jako 'not null' - ale nie poleciłbym tego. Możesz być lepiej z jakąś logiką w kodzie zamiast bazy danych. –
Zgadzam się z Aleks. Myślę, że jest to reguła biznesowa, która należy gdzieś do warstwy pośredniej, a nie do bazy danych. – David
@Aleks dołączanie FK NOT NULL z Idea to Media nie jest rzadkością. To proste, i tak, będzie musiał najpierw wypełnić Media. – vol7ron