Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Implementacja w bazie danych wymagania „albo-albo”, ale nie zerowego

Odpowiedź Ypercube jest w porządku, z wyjątkiem tego, że w rzeczywistości można to zrobić wyłącznie poprzez integralność deklaratywną przy zachowaniu oddzielnych tabel. Sztuczka polega na połączeniu odroczonych okrągłych kluczy OBCYCH z odrobiną kreatywnej denormalizacji:

CREATE TABLE Instruction (
    InstructionId INT PRIMARY KEY,
    TextId INT UNIQUE,
    DocumentId INT UNIQUE,
    CHECK (
        (TextId IS NOT NULL AND InstructionId = TextId)
        OR (DocumentId IS NOT NULL AND InstructionId = DocumentId)
    )
);

CREATE TABLE Text (
    InstructionId INT PRIMARY KEY,
    FOREIGN KEY (InstructionId) REFERENCES Instruction (TextId) ON DELETE CASCADE
);

CREATE TABLE Document (
    InstructionId INT PRIMARY KEY,
    FOREIGN KEY (InstructionId) REFERENCES Instruction (DocumentId) ON DELETE CASCADE
);

ALTER TABLE Instruction ADD FOREIGN KEY (TextId) REFERENCES Text DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE Instruction ADD FOREIGN KEY (DocumentId) REFERENCES Document DEFERRABLE INITIALLY DEFERRED;

Wstawianie tekstu odbywa się w następujący sposób:

INSERT INTO Instruction (InstructionId, TextId) VALUES (1, 1);
INSERT INTO Text (InstructionId) VALUES (1);
COMMIT;

Wstawianie dokumentu w ten sposób:

INSERT INTO Instruction (InstructionId, DocumentId) VALUES (2, 2);
INSERT INTO Document (InstructionId) VALUES (2);
COMMIT;

I wstawiaj zarówno tekst, jak i dokument w ten sposób:

INSERT INTO Instruction (InstructionId, TextId, DocumentId) VALUES (3, 3, 3);
INSERT INTO Text (InstructionId) VALUES (3);
INSERT INTO Document (InstructionId) VALUES (3);
COMMIT;

Jednak próba wstawienia samej instrukcji nie powiedzie się po zatwierdzeniu:

INSERT INTO Instruction (InstructionId, TextId) VALUES (4, 4);
COMMIT; -- Error (FOREIGN KEY violation).

Próba wstawienia „niedopasowanego typu” również nie udaje się po zatwierdzeniu:

INSERT INTO Document (InstructionId) VALUES (1);
COMMIT; -- Error (FOREIGN KEY violation).

I oczywiście próba wstawienia złych wartości do instrukcji nie udaje się (tym razem przed zatwierdzeniem):

INSERT INTO Instruction (InstructionId, TextId) VALUES (5, 6); -- Error (CHECK violation).
INSERT INTO Instruction (InstructionId) VALUES (7); -- Error (CHECK violation).


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. brak uprawnień w przestrzeni tabel „USERS”

  2. Mały obiekt Blob lub Clob Oracle 10g nie jest przechowywany w trybie inline?

  3. Funkcja NLS_CHARSET_ID() w Oracle

  4. Wspólny użytkownik z uprawnieniami SYSBACKUP

  5. Parametryzacja nazwy tabeli w pliku wejściowym sqlplus