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

SQL Serverで複合外部キーを作成する方法(T-SQLの例)

    複合外部キー 複数の列で構成される外部キーです。

    この記事では、SQLServerでTransact-SQLを使用して複合外部キーを作成する例を示します。

    単一の外部キーを作成するのと同じように複合外部キーを作成できますが、1つの列だけを指定する代わりに、2つ以上の列の名前をコンマで区切って指定する点が異なります。

    このように:

    CONSTRAINT FK_FKName FOREIGN KEY
     (FKColumn1, FKColumn2)
    REFERENCES PrimaryKeyTable (PKColumn1, PKColumn2)
    

    例1-複合外部キーを作成する

    これは、複合外部キー(および複合主キー)を使用するデータベースの例です。

    この例では、 BandTest というデータベースを作成します。 :

    CREATE DATABASE BandTest;
    

    データベースが作成されたので、先に進んでテーブルを作成しましょう。

    USE BandTest;
    
    CREATE TABLE Musician (
    MusicianId int NOT NULL,
    FirstName varchar(60),
    LastName varchar(60),
    CONSTRAINT PK_Musician PRIMARY KEY (MusicianID)
    );
    
    CREATE TABLE Band (
    BandId int NOT NULL,
    BandName varchar(255),
    CONSTRAINT PK_Band PRIMARY KEY (BandId)
    );
    
    CREATE TABLE BandMember (
    MusicianId int NOT NULL,
    BandId int NOT NULL,
    CONSTRAINT PK_BandMember PRIMARY KEY (MusicianID, BandId),
    CONSTRAINT FK_BandMember_Band FOREIGN KEY (BandId) REFERENCES Band(BandId),
    CONSTRAINT FK_BandMember_Musician FOREIGN KEY (MusicianId) REFERENCES Musician(MusicianId)
    );
    
    CREATE TABLE MembershipPeriod (
    MembershipPeriodId int NOT NULL,
    MusicianId int NOT NULL,
    BandId int NOT NULL,
    StartDate date NOT NULL,
    EndDate date NULL,
    CONSTRAINT PK_MembershipPeriod PRIMARY KEY (MembershipPeriodID),
    CONSTRAINT FK_MembershipPeriod_BandMember FOREIGN KEY (MusicianID, BandId) REFERENCES BandMember(MusicianID, BandId)
    );
    

    この例では、BandMember テーブルには複数列の主キーがあります。 MembershipPeriod テーブルには、その複数列の主キーを参照する外部キーがあります。したがって、主キー定義と外部キー定義の両方に、コンマで区切られた列が含まれます。

    上記のデータベース設計の背後にある理由は、ミュージシャンが多くのバンドのメンバーになる可能性があるということです。また、各バンドには多くのミュージシャンがいる可能性があります。したがって、私たちは多対多の関係を持っています。これがBandMemberの理由です テーブルが作成されます–Musician間の相互参照テーブルとして使用されます テーブルとBand テーブル。この場合、複合主キーを使用することを選択しました。

    ただし、ミュージシャンは複数回バンドのメンバーになることもできます(たとえば、ミュージシャンがバンドを離れて、後で戻る場合があります)。したがって、MembershipPeriod テーブルを使用して、各ミュージシャンが各バンドのメンバーであったすべての期間を記録できます。これは、BandMemberの複合主キーを参照する必要があります テーブルなので、複数列の外部キーを作成する必要があります。

    例2–データの挿入

    上記のコードを実行しただけで、データベースにデータをロードできます。

    INSERT INTO Musician
    VALUES 
    ( 1, 'Ian', 'Paice' ),
    ( 2, 'Roger', 'Glover' ),
    ( 3, 'Richie', 'Blackmore' ),
    ( 4, 'Rod', 'Evans' ),
    ( 5, 'Ozzy', 'Osbourne' );
    
    INSERT INTO Band
    VALUES 
    ( 1, 'Deep Purple' ),
    ( 2, 'Rainbow' ),
    ( 3, 'Whitesnake' ),
    ( 4, 'Iron Maiden' );
    
    INSERT INTO BandMember
    VALUES 
    ( 1, 1 ),
    ( 1, 3 ),
    ( 2, 1 ),
    ( 2, 2 ),
    ( 3, 1 ),
    ( 3, 2 ),
    ( 4, 1 );
    
    INSERT INTO MembershipPeriod
    VALUES 
    ( 1, 1, 1, '1968-03-01', '1976-03-15' ),
    ( 2, 1, 1, '1984-04-01', NULL ),
    ( 3, 1, 3, '1979-08-01', '1982-01-01' ),
    ( 4, 2, 1, '1969-01-01', '1973-06-29' ),
    ( 5, 2, 1, '1984-04-01', NULL ),
    ( 6, 2, 2, '1979-01-01', '1984-01-01' ),
    ( 7, 3, 1, '1968-03-01', '1975-06-21' ),
    ( 8, 3, 1, '1984-04-01', '1993-11-17' ),
    ( 9, 3, 2, '1975-02-01', '1984-04-01' ),
    ( 10, 3, 2, '1993-11-17', '1997-05-31' ),
    ( 11, 3, 2, '2015-01-01', NULL ),
    ( 12, 4, 1, '1968-03-01', '1969-12-01' );
    

    例3–基本的なクエリ

    データベースに対して実行できるクエリの例を次に示します。

    SELECT 
      CONCAT(m.FirstName, ' ', m.LastName) AS 'Musician',
      b.BandName AS 'Band',
      mp.StartDate AS 'Start',
      mp.EndDate AS 'End'
    FROM Musician m
    JOIN BandMember bm
      ON m.MusicianId = bm.MusicianId
    JOIN Band b 
      ON b.BandId = bm.BandId AND m.MusicianId = bm.MusicianId
    JOIN MembershipPeriod mp
    ON mp.BandId = b.BandId AND mp.MusicianId = m.MusicianId;
    

    結果:

    +------------------+-------------+------------+------------+
    | Musician         | Band        | Start      | End        |
    |------------------+-------------+------------+------------|
    | Ian Paice        | Deep Purple | 1968-03-01 | 1976-03-15 |
    | Ian Paice        | Deep Purple | 1984-04-01 | NULL       |
    | Ian Paice        | Whitesnake  | 1979-08-01 | 1982-01-01 |
    | Roger Glover     | Deep Purple | 1969-01-01 | 1973-06-29 |
    | Roger Glover     | Deep Purple | 1984-04-01 | NULL       |
    | Roger Glover     | Rainbow     | 1979-01-01 | 1984-01-01 |
    | Richie Blackmore | Deep Purple | 1968-03-01 | 1975-06-21 |
    | Richie Blackmore | Deep Purple | 1984-04-01 | 1993-11-17 |
    | Richie Blackmore | Rainbow     | 1975-02-01 | 1984-04-01 |
    | Richie Blackmore | Rainbow     | 1993-11-17 | 1997-05-31 |
    | Richie Blackmore | Rainbow     | 2015-01-01 | NULL       |
    | Rod Evans        | Deep Purple | 1968-03-01 | 1969-12-01 |
    +------------------+-------------+------------+------------+
    

    これで、複数の機会にメンバーであった場合でも、各ミュージシャンが各バンドのメンバーであった日付を確認できます。

    例4–わずかに変更されたクエリ

    上記のクエリを変更して、結果をもう少し読みやすい形式で提供することができます。

    SELECT 
      CONCAT(m.FirstName, ' ', m.LastName) AS 'Musician',
      b.BandName AS 'Band',
      STRING_AGG(
        CONCAT(FORMAT(mp.StartDate, 'yyyy'), '-', ISNULL(FORMAT(mp.EndDate, 'yyyy'), 'present')), ', ') AS 'Time with the band'
    FROM Musician m
    JOIN BandMember bm
      ON m.MusicianId = bm.MusicianId
    JOIN Band b 
      ON b.BandId = bm.BandId AND m.MusicianId = bm.MusicianId
    JOIN MembershipPeriod mp
    ON mp.BandId = b.BandId AND mp.MusicianId = m.MusicianId
    GROUP BY m.FirstName, m.LastName, b.BandName;
    

    結果:

    +------------------+-------------+------------------------------------+
    | Musician         | Band        | Time with the band                 |
    |------------------+-------------+------------------------------------|
    | Ian Paice        | Deep Purple | 1968-1976, 1984-present            |
    | Ian Paice        | Whitesnake  | 1979-1982                          |
    | Richie Blackmore | Deep Purple | 1968-1975, 1984-1993               |
    | Richie Blackmore | Rainbow     | 1975-1984, 1993-1997, 2015-present |
    | Rod Evans        | Deep Purple | 1968-1969                          |
    | Roger Glover     | Deep Purple | 1969-1973, 1984-present            |
    | Roger Glover     | Rainbow     | 1979-1984                          |
    +------------------+-------------+------------------------------------+
    

    この例では、STRING_AGG()を利用しています。 各ミュージシャンのさまざまな期間を連結する機能。これにより、必要な行数が減り、同じフィールドに期間をグループ化できるようになります。

    ISNULL()も利用しています 関数。これにより、NULL値をより意味のあるものに変更できます。

    ISNULL()に注意してください 2番目の引数は、最初の引数の型に暗黙的に変換できる型である必要があります。この場合、最初の引数は元々日付でした タイプ。これは、文字列を使用できないことを意味します。ただし、この場合、FORMAT()を使用することにしました。 日付をフォーマットする関数 価値。この関数は、日付を暗黙的に変換します 文字列の値であるため、2番目の引数に文字列を使用できました。


    1. テーブルから挿入可能なSQL形式にすべてのデータをエクスポートするにはどうすればよいですか?

    2. Sqlite Android Raw QueryINSERTINTOが機能しない

    3. PostgreSQL 12:外部キーとパーティションテーブル

    4. PostgreSQLは構成/confファイルをどこに保存しますか?