sql >> Databáze >  >> RDS >> Oracle

Implementace požadavku obojí, buď-nebo, ale ne null v databázi

Odpověď Ypercube je v pořádku, až na to, že to lze ve skutečnosti provést čistě prostřednictvím deklarativní integrity při zachování oddělených tabulek. Trik je v kombinaci odložených kruhových CIZÍCH KLÍČŮ s trochou kreativní denormalizace:

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;

Vkládání textu se provádí takto:

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

Vložení dokumentu takto:

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

A vložení textu i dokumentu takto:

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

Pokus o vložení samotné instrukce však se nezdaří při potvrzení:

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

Pokus o vložení „neshodného typu“ také se nezdaří při potvrzení:

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

A samozřejmě pokus vložit špatné hodnoty do instrukce selže (tentokrát před potvrzením):

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


  1. Funkce Oracle Custom IsNumber s přesností a měřítkem

  2. Jak vytvořit materializované pohledy na SQL Server?

  3. Získání posledního vloženého ID s výrazem v mysql

  4. Jak se dotazovat na oprávnění v adresáři Oracle?