web-dev-qa-db-ja.com

SQL Serverの抽象クラス。それらは可能ですか?

非常に具体的な質問があります。誰もまだ質問していないことに驚いています。具体的なクラスモデルとSQL Server 2016 DDLが含まれます。主なポイントは次のとおりです。私のモデルでは、一部のクラスが基本クラスから継承しています。たとえば、"BaseInfo"としましょう。

このクラスは抽象です。 SQLの用語では、行を含む別のテーブルを作成したくない(またはしますか?)ことを意味します(例:CREATE TABLE "BaseInfo"....。ただし、一部のテーブル(実際にはかなり多く)には、同じ列(およびいくつかの独自の列)。OOP用語で、一部のクラスにそのテーブル定義から継承させたい。これをDDLで定義する方法はありますか、またはこれを手動で実装しますか?

ノート:

  1. TPH、TPT、TPCで見つかるすべての記事を読みました。それらは単純すぎるため、すべて同じPerson-Student-Educatorモデルを備えており、私のケースとは一致しません。私がおそらくやりたいのはTPCですが、BaseInfoテーブルに加えた変更がすべての子クラスに自動的に適用されるようにしたいと思います。

  2. BaseInfoのクエリは行いません。私はむしろ、子の一部(またはすべて)を含む(まれな)複雑なクエリを実行します。

  3. BaseInfo DDL(ALTER TABLE BaseInfo...)に加えられた変更は、子に(できれば自動的に)反映する必要があります。

  4. ここでは、PostgreSQLがINHERITSステートメントで輝いています。 SQL Serverに同等のものはありますか(私は調査を行い、まだ何も見つかりません)?

  5. 回答が得られない場合や、他の突破口がある場合は、手動でアプローチします。 BaseInfo DDLを使用してコードスニペットを保存し、各子テーブルのCREATE TABLEステートメントに追加します。

  6. 答えは概念モデルの定義を尊重する必要があります!

4
Petros Apotsos

PostgreSQLが実際にこの要求をサポートしていることは正しいが、SQL Serverには同様の機能はありません。これにより、各テーブルにすべての「共通」列を配置するか、必要に応じてに結合される共通列を含む「ベース」テーブルを用意する(ほとんどの場合、100%必要になることはありません)。

ここに示すように、これらの「共通」列をすべて(ほとんど)のテーブルにコピーすることを反対にすることをお勧めします。

  1. 回答が得られない場合や、他の突破口がある場合は、手動でアプローチします。 BaseInfo DDLを使用してコードスニペットを保存し、各子テーブルのCREATE TABLEステートメントに追加します。

なぜなら:

  1. スキーマが同期しなくなる可能性がはるかに高いため、長期的なメンテナンスはより困難/エラーが発生しやすくなります。 CREATE TABLEステートメントのテンプレート化は1つのことですが、変更を調整する必要があります。実際、ここでの要件の1つは次のとおりです。

    1. BaseInfo DDL(ALTER TABLE BaseInfo...)に加えられた変更は、子に(できれば自動的に)反映する必要があります。
  2. データを分離すると、パフォーマンスが向上します。データベースには、アプリのコードとは根本的に異なる目的(物理ストレージとセットベースの操作)があることに留意してください。直感に反し、「不格好」または「建築」のベストプラクティスに反するように見えるかもしれませんが、特定のRDBMSの長所に合わせてデータモデルを構造化すると、最良の結果が得られます。結合は「余分な」作業であるように見える場合があります(ただし、そうである場合もあります)が、RDBMSはこのように機能するように特に最適化されています(一般に、テーブルが小さいほど、クエリインデックスのメンテナンス-無視してはならないもの!).

  3. 各クラスとサブクラスの関係をビューに抽象化することで、JOINの「煩雑さ」の多くを回避できます。これらはすべてのSELECTの場合、およびほとんどのUPDATEの場合でも更新可能なビュー(MSDNページで CREATE VIEW について詳しく説明されています)でさえも確実に役立ちます。INSERTおよびDELETEステートメントも機能しませんが、INSERTOUTPUTINSERT句を介して両方のテーブルをBaseInfoテーブルに結合することにより、両方のテーブルをさらに簡単にすることができます。また、DELETEステートメントは、外部キーにON DELETE CASCADEプロパティを指定するときに両方のテーブルを処理できます。次に、ほとんどの例を示します。この:

    /*
    DROP VIEW dbo.UpdatableView;
    DROP TABLE dbo.UpdatableViewTableB;
    DROP TABLE dbo.UpdatableViewTableA;
    */
    
    CREATE TABLE dbo.UpdatableViewTableA
    (
        ID INT NOT NULL IDENTITY(1, 1) CONSTRAINT [PK_UpdatableViewTableA] PRIMARY KEY,
        IsActive BIT NOT NULL,
        InsertTime DATETIME2 NOT NULL CONSTRAINT [DF_UpdatableViewTableA_InsertTime]
             DEFAULT (SYSDATETIME())
    );
    
    CREATE TABLE dbo.UpdatableViewTableB
    (
        ID INT NOT NULL CONSTRAINT [PK_UpdatableViewTableB] PRIMARY KEY,
        Whateva NVARCHAR(4000) NULL,
        CONSTRAINT [FK_UpdatableViewTableB_UpdatableViewTableA_ID]
            FOREIGN KEY ([ID])
            REFERENCES dbo.UpdatableViewTableA ([ID])
            ON DELETE CASCADE
    );
    GO
    CREATE VIEW dbo.UpdatableView
    AS
    SELECT a.[ID], a.[IsActive], a.[InsertTime], b.[Whateva]
    FROM   dbo.UpdatableViewTableA a
    INNER JOIN dbo.UpdatableViewTableB b
            ON b.[ID] = a.[ID];
    GO
    INSERT INTO dbo.UpdatableViewTableA ([IsActive]) VALUES (1);
    INSERT INTO dbo.UpdatableViewTableB ([ID], [Whateva]) VALUES (1, N'test row');
    
    INSERT INTO dbo.UpdatableViewTableA ([IsActive]) VALUES (1);
    INSERT INTO dbo.UpdatableViewTableB ([ID], [Whateva]) VALUES (2, N'another row');
    
    SELECT * FROM dbo.UpdatableView;
    
    UPDATE uv
    SET    uv.IsActive = 0
    FROM   dbo.UpdatableView uv
    WHERE  uv.[ID] = 2;
    
    SELECT * FROM dbo.UpdatableView;
    
    UPDATE uv
    SET    uv.[Whateva] = N'what?'
    FROM   dbo.UpdatableView uv
    WHERE  uv.[ID] = 1;
    
    SELECT * FROM dbo.UpdatableView;
    
    DELETE uv
    FROM   dbo.UpdatableView uv
    WHERE  uv.[ID] = 1;
    -- Msg 4405, Level 16, State 1, Line 59
    -- View or function 'uv' is not updatable because the modification 
    --   affects multiple base tables.
    

以下のDBA.SEの回答で、このタイプのデータモデルの実装のバリエーションを詳しく説明しました。

追伸それが価値があるもの(そしてそれはそれほど多くないかもしれません;-)のために、私はほとんどのので、この機能にどのくらいの実際の利点があるかわかりません「ベース」クラスのプロパティは、レポート内だけの場合でも、個別にクエリされることに価値があります。これは、Microsoft Connectで最近リクエストされた関数のオーバーロードに対するPostgreSQLの機能( ユーザー定義関数のオーバーロード? )に似ています。

2
Solomon Rutzky

SQL Serverには、このようなものはありません。

スキーマを構築および維持するためのツールは何ですか。データベースプロジェクトを使用しますか? 「手動」の方法を実行した場合、SSDTにはこれに関するSQL固有のテンプレートはありませんが、T4テンプレートを使用して 似たようなもの を実行できる場合があります。

興味がある場合は、テンプレート化の別の方法として、BimlScriptを使用することもできます。これは、プログラムでSSISパッケージを生成するために使用されますが、SQL DDLの生成と同様のことを最近開始したため、チェックインできます。

4
Cody Konior