Oracle
 sql >> база данни >  >> RDS >> Oracle

Внедряване на изискване „И двете, или или, но не нула“ в база данни

Отговорът на Ypercube е добре, освен че това всъщност може да се направи само чрез декларативна цялост, като същевременно се поддържат отделни таблици. Номерът е да комбинирате отложени кръгови FOREIGN KEY с малко творческа денормализация:

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;

Вмъкването на текст става по следния начин:

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

Вмъкване на документ по този начин:

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

И вмъкване както на текст, така и на документ по този начин:

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

Обаче опитът да се вмъкне само инструкция се проваля при извършване:

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

Опитът за вмъкване на „несъответстващ тип“ също е неуспешен при извършване:

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

И, разбира се, опитът за вмъкване на лоши стойности в инструкцията е неуспешен (този път преди ангажиране):

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. Създаване на тригер в Oracle Express

  2. Вложените скоби в клаузата FROM валиден ли е синтаксисът на Oracle SQL?

  3. Как да получа текстово съдържание от BLOB в Oracle SQL

  4. Грешка в базата данни на Oracle в symfony2 (доктрина). Правилно ли е настроен parameters.yml?

  5. PDO изключение не се хвърля за грешки на задействане