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

複数の1対1を作成する方法

    継承を使用しています(エンティティ関係モデリングでは「サブクラス」または「カテゴリ」とも呼ばれます)。一般に、データベースでそれを表すには3つの方法があります。

    1. 「1つのテーブル内のすべてのクラス」: 親クラスとすべての子クラスを「カバー」するテーブルを1つだけ(つまり、すべての親列と子列を含む)、フィールドの正しいサブセットがNULLでないことを確認するためのCHECK制約を設定します(つまり、2つの異なる子が「混合」しない)。
    2. 「テーブルごとの具象クラス」: 子ごとに異なるテーブルを用意しますが、親テーブルはありません。これには、すべての子で親の関係(この場合は在庫<-ストレージ)を繰り返す必要があります。
    3. 「テーブルごとのクラス」: 親テーブルと子ごとに個別のテーブルを用意します。これが、あなたがやろうとしていることです。これは最もクリーンですが、パフォーマンスがいくらか犠牲になる可能性があります(主にデータを変更する場合、子から直接参加して親をスキップできるため、クエリの場合はそれほど多くありません)。

    私は通常3番目のアプローチを好みますが、両方のプレゼンスを強制します および独占性 アプリケーションレベルでの子供のデータベースレベルで両方を適用するのは少し面倒ですが、DBMSが遅延制約をサポートしている場合は実行できます。例:

    CHECK (
        (
            (VAN_ID IS NOT NULL AND VAN_ID = STORAGE_ID)
            AND WAREHOUSE_ID IS NULL
        )
        OR (
            VAN_ID IS NULL
            AND (WAREHOUSE_ID IS NOT NULL AND WAREHOUSE_ID = STORAGE_ID)
        )
    )
    

    これにより、両方の排他性が適用されます(CHECKによる) )とプレゼンス(CHECKの組み合わせによる) およびFK1 / FK2 )子供の。

    残念ながら、MS SQL Serverは遅延制約をサポートしていませんが、ストアドプロシージャの背後で操作全体を「非表示」にし、クライアントがテーブルを直接変更することを禁止できる場合があります。

    延期された制約なしに、排他性のみを適用できます:

    STORAGE_TYPE は型識別子であり、通常はスペースを節約するための整数です(上記の例では、0と1はアプリケーションに「認識」されており、それに応じて解釈されます)。

    VAN.STORAGE_TYPE およびWAREHOUSE.STORAGE_TYPE ストレージを節約し、CHECKの必要性を回避するために、計算(別名「計算済み」)列を使用できます。 s。

    ---編集---

    計算列は、SQLServerでは次のように機能します。

    CREATE TABLE STORAGE (
        STORAGE_ID int PRIMARY KEY,
        STORAGE_TYPE tinyint NOT NULL,
        UNIQUE (STORAGE_ID, STORAGE_TYPE)
    );
    
    CREATE TABLE VAN (
        STORAGE_ID int PRIMARY KEY,
        STORAGE_TYPE AS CAST(0 as tinyint) PERSISTED,
        FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
    );
    
    CREATE TABLE WAREHOUSE (
        STORAGE_ID int PRIMARY KEY,
        STORAGE_TYPE AS CAST(1 as tinyint) PERSISTED,
        FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
    );
    
    -- We can make a new van.
    INSERT INTO STORAGE VALUES (100, 0);
    INSERT INTO VAN VALUES (100);
    
    -- But we cannot make it a warehouse too.
    INSERT INTO WAREHOUSE VALUES (100);
    -- Msg 547, Level 16, State 0, Line 24
    -- The INSERT statement conflicted with the FOREIGN KEY constraint "FK__WAREHOUSE__695C9DA1". The conflict occurred in database "master", table "dbo.STORAGE".
    

    残念ながら、SQLServerでは外部で使用される計算列が必要です。 永続化するためのキー。他のデータベース(Oracleの仮想列など)にはこの制限がない場合があり、ストレージスペースを節約できます。



    1. SQL同じテーブルのグループの列のSUMを更新する方法

    2. PostgreSQL13を使用した論理レプリケーションのパーティショニング

    3. SQLエラー:ORA-00942テーブルまたはビューが存在しません

    4. 「それは秘密ですか?安全ですか?」データモデリングでの機密データの処理