sql >> データベース >  >> RDS >> Oracle

両方、どちらか、またはnullではない要件をデータベースに実装する

    Ypercubeの回答 これは、実際には、個別のテーブルを維持しながら、純粋に宣言型の整合性によって実行できることを除いて、問題ありません。秘訣は、延期された循環外部キーと少しの創造的な非正規化を組み合わせることです。

    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. 重複する行を削除して、より高い値の行を保持するにはどうすればよいですか?

    2. OracleでのBLOBストレージの長さ

    3. phpリンクからmysql行を削除します

    4. diffをデータベースに保存する最もコンパクトな方法は何ですか?