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

SQL FOREIGN KEY CONSTRAINT:初心者のための究極の簡単なガイド

    初心者?その場合、SQL外部キーは外部キーである可能性があります。

    SQL外部キーについてさまざまな意見を聞いたことがあるかもしれません。まだの場合は、すぐに行います。またはあなたの経験はあなたの見方に影響を与えます。知っておくべき主なことは、リレーショナルデータベースでは外部キーが必須であるということです。

    ただし、一部の開発者は、いくつかの問題に直面したときに外部キーを削除または無視する場合があります。じゃあ何をすればいいの?外部キーを使用するか、使用しないか?それらを使用する必要がない場合がありますか?

    このガイドは、このことがどれほど重要かを理解するためのものです。また、コードのいくつかの落とし穴を知り、それらを修正する方法を学びます。その上、もちろん、実際の例を使用します。処理できないものはありません。

    SQL外部キーとは何ですか?

    まず最初に。 SQLの外部キーとは何ですか?一言で言えば、2つのテーブルをリンクするキーです。親テーブルと子テーブルがあるとします。それらを親と子にするいくつかの共通点があります–これらの2つのテーブルを関連付けるキーです。

    ただし、SQLデータベースでは、外部キーはテーブルに関連するだけではありません。それは関係を強制します。これが外部キー制約と呼ばれる理由です。

    親テーブルの主キーに存在しない外部キー値を持つ子レコードを追加しようとすると、エラーが発生します。後で、これを説明するコードサンプルを確認します。

    どのテーブルにSQL外部キー制約が必要ですか?

    子テーブルは外部キーを持つことができます。 1つの外部キーが別のテーブルを参照している可能性があります。また、「子」テーブルには複数の外部キーが存在する可能性があります。 SQL Serverでは、外部キーは別のテーブルの主キーまたは一意キーを参照できます。

    自己参照はどうですか?

    これは、外部キーの一般的な定義から外れます。 自己参照 参照する外部キーを割り当てることができることを意味します 同じテーブルの別の列 。 SQL Server、MySQL、およびOracleはこれをサポートしています。

    自己参照は、マネージャーとスタッフの関係のような階層を作成する場合に適用できます。それでも、外部キーのほとんどの実装は2つのテーブルの間にあります。

    後で例を示します。

    SQL外部キーを使用する4つの利点

    SQLの主キーと外部キーについて詳しく見ていきましょう。 SQLデータベースに外部キーが必須である理由は何ですか? 4つのポイントを調べてみましょう(ここでは、制約の構文は重要ではありません)。

    1。 「欠測」データを避ける

    「欠落」データは、親テーブルの主キー値が関連付けられていない子テーブルの外部キー値です。これらは、孤立した行とも呼ばれます。その場合、データベースには参照整合性がほとんどまたはまったくないと言えます。

    外部キー制約が適用されると、データの「欠落」はまったく発生しません。データベースエンジンは、別のテーブルによって参照されている主キー値の削除を許可しません。同様に、親テーブルの主キーに存在しない外部キーを子テーブルに挿入すると、エラーがトリガーされます。

    外部キー制約を使用しない場合に発生する可能性のある最悪の事態は何ですか?ここにいくつかあります:

    • 顧客は支払った製品を受け取りません。
    • 治療は患者に投与されません。
    • チェックリストがない場合は、安全上の注意をスキップしてください。

    このようなものはデータベースの外で処理できますが、コーディングする必要があります。これについてはさらに詳しく説明します。

    組織内の開発者がデータベースの外部で同じ制約を処理したとしましょう。コードが失敗した場合、彼は責任を負い、本番環境で問題を修正しますか?私はそうは思わない。そして、あなたがデータベース管理者である場合はどうなりますか?次に、あなたは彼らの混乱をきれいにする必要があります。あなたが私に尋ねてもそれほど勇気づけられません。

    2。一貫性のないレポートを避ける

    それは最初のポイントに関連しています。一部のデータが「欠落」している場合、一貫性のない合計がさまざまなレポートに表示されます。詳細が要約と一致しません。孤立した行は、要約の合計になります。一方、親テーブルへの内部結合のため、詳細レポートは孤立した行をキャプチャしませんでした。

    データベースを良好な状態に保つことがあなたの仕事である場合は、この混乱も解消します。

    3。孤立した行を回避するためにコードは必要ありません

    外部キー制約は、セルフクリーニングエージェントのように機能します。混乱をクリーンアップする代わりに、データベースは孤立した行を許可しないことでクリーンアップします。外部キー制約は警察としても機能します。彼らは、孤立した行を引き起こす誤ったロジックを阻止し、データベースの外部で行われた犯罪のように扱います。

    孤立した行のない光沢のあるデータベースが必要ですか?もちろん、あなたはそうします。いつかデータを分析したい場合は、外部キーを使用してよかったと思います。このデータベースは、必要なデータをステージング領域にコピーするための優れたソースになります。

    4。ダイアグラム内のテーブルの関係をすばやく理解する

    SQL Server Management Studioには、データベース用の組み込みの作図ツールがあります。主キーと外部キーにより、データベース図が一目でわかりやすくなります。ただし、図に含めたリレーションシップを持つテーブルの数によって異なります。

    ダイアグラムは、新しいチームメンバーがデータ構造を理解するのに役立ちます。上級チームメートにとっては、ドキュメントとしても役立つ可能性があります。

    SQL外部キーが「問題」(および修正)になる可能性がある場合

    古いデータを新しいデータベースに移行するには、レコードを一括で挿入します。ソースデータベースの参照整合性が低い場合、ソースからレコードを挿入するのは面倒です。その理由は、外部キーエラーがあちこちでポップアップするためです。

    修正はありますか? 2つのオプションがあります。

    1. 最初に参照テーブルまたは親テーブルにデータを入力してください。その後、子テーブルにデータを入力します。 1つの問題は、実行が非常に遅いことです。その他の場合、より多くの外部キー制約エラーが発生します。後者の場合は、挿入の順序を再評価し、主キーが最初に挿入されていることを確認する必要があります。 「実行速度が遅い」問題がある場合は、次のオプションを検討してください。
    2. 外部キーを一時的に無効にし、移行が完了(およびクリーンアップ)した後に有効にします。これは、SQL Server Management Studioで実行するか、T-SQLALTERTABLEを使用して実行できます。ただし、言うのは簡単です。この時点で、あなたはあなたの知恵と意志力に加えてより多くの忍耐を必要とします。後で、外部キーを無効化および再有効化するための構文を見つけます。

    考慮すべきもう1つのことは、OLAPまたはデータ分析のステージング領域としてデータベースを使用することです。ソーストランザクションデータベースが孤立した行からクリーンであると仮定します。または、コードを使用してこれらの行を回避することができます。次に、外部キーを使用しないことを選択できます。外部キーは、特に巨大なデータセットで、一括挿入と更新を遅くします。

    SQL外部キー制約を追加、編集、および削除する3つの簡単な方法

    外部キーを追加、編集、または削除するには何が必要ですか?これらの3つのヒントで簡単です。

    最初の2つの手順では、グラフィカルユーザーインターフェイスを使用します。 SQL ServerManagementStudioやdbForgeStudioforSQLServerなどのツールは非常に優れた候補です。 3つ目は、T-SQLコードを使用します。 GUIまたはT-SQLコードの選択は、状況によって異なります。

    1。 TableDesignerを使用したSQL外部キー制約の追加、編集、および削除

    テーブルデザイナを使用してテーブル構造を作成または変更するときに、SQLで外部キー制約を追加することができます。 SSMSで。下の図1は、テーブル構造が開いているときにメインメニューからアクセスする方法を示しています。

    もう1つのオプションは、テーブルデザイナの任意の場所を右クリックして、関係を選択することです。 コンテキストメニューから:

    関係を選択したら 外部キー関係 ウィンドウがポップアップします:

    外部キー関係 ウィンドウでは、新しい外部キーを追加するか、既存のキーを編集/削除するかを選択できます。

    追加または編集する場合は、クリックしてテーブルと列を展開します 仕様。次に、省略記号をクリックします ボタンをクリックして、主キーテーブルと外部キーテーブルを定義または編集します。

    そこから、主キー列と外部キー列を指定できます。

    主キーと外部キーを定義したら、 OKをクリックします。 。次に、テーブルデザイナに戻り、変更を保存します。

    2。データベース図を使用したSQL外部キー制約の追加、編集、および削除

    データベース図を使用して、SQL外部キー制約を作成できます。図5は、外部キーテーブルをクリックして主キーテーブルにドラッグすることにより、2つのテーブル間に関係を作成する方法を示しています。

    マウスを離すと、テーブルと列 図4のようなウィンドウがポップアップ表示されます。次に、主キー列と外部キー列を指定できます。次に、[OK]をクリックします。

    既存の関係を編集するには、図の関係を右クリックします。次に、プロパティを選択します

    次に、プロパティ ウィンドウで、テーブルと列を展開します 省略記号をクリックします ボタン:

    省略記号をクリックした後 ボタン、テーブルと列 ウィンドウが表示されます。主キー列と外部キー列を変更できます(上記の図4を再度参照してください)。

    その間、関係を削除する 既存を右クリックする必要があります 関係。 データベースから関係を削除を選択します はいをクリックします プロンプトが表示されたら。

    3。 T-SQLを使用したSQL外部キー制約の追加、編集、および削除

    外部キーを追加する3番目の方法は、T-SQLコードを使用することです。 SQL CREATE TABLEを使用して、外部キー制約を追加できます。または、ALTER TABLEを使用して、テーブルの作成後にこの制約を追加することもできます。

    CREATETABLEを使用するための構文は次のとおりです。

    -- Single-column foreign key
    CREATE TABLE Table2
    (ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
     col1 INT NULL REFERENCES Table1(col1)
    )
    GO
    

    列の名前とタイプを定義した後、テーブルと列にREFERENCESを追加できます。上記の構文は、 Table1を示しています。 col1のテーブル 桁。外部キーに対して有効にするには、両方のテーブルの列名が同じである必要があることに注意してください。

    上記の構文は、単一列の外部キー用です。外部キーとして複数の列が必要な場合は、以下のようにFOREIGNKEY句を使用します。

    -- Multiple-column foreign key
    CREATE TABLE Table2
    (ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
     col1 INT NOT NULL,
     col2 INT NOT NULL,
     col3 VARCHAR(10) NULL
     CONSTRAINT FK_Table1_Table2 FOREIGN KEY(col1, col2)
    	REFERENCES Table1(col1,col2)
    )
    GO
    

    テーブルを作成した後、ALTERTABLEを使用して外部キーを追加できます。構文は次のとおりです。

    ALTER TABLE Table2 WITH CHECK ADD CONSTRAINT FK_Table1_Table2_2 FOREIGN KEY(col3)
    	REFERENCES Table3(col1)
    GO
    

    外部キー制約を削除するには、DROPCONSTRAINTでALTERTABLEを使用できます:

    ALTER TABLE Table2 
    DROP CONSTRAINT FK_Table1_Table2_2
    GO
    

    これで、外部キーを追加、編集、および削除する3つの方法を要約できます。

    SQL(MySQL)外部キー制約の例

    親テーブルへの参照が1つある子テーブル

    -- Single Reference
    CREATE TABLE [dbo].[Countries](
    	[CountryID] [int] IDENTITY(1,1) NOT NULL,
    	[Country] [nvarchar](50) NOT NULL,
    	[ContinentID] [int] NULL,
    	[Modified] [datetime] NOT NULL,
     CONSTRAINT [PK_Country] PRIMARY KEY CLUSTERED 
    (
    	[CountryID] ASC
    ))
    GO
    
    ALTER TABLE [dbo].[Countries]  WITH CHECK ADD CONSTRAINT [FK_Countries_Continent] FOREIGN KEY([ContinentID])
    REFERENCES [dbo].[Continent] ([ContinentID])
    
    GO
    
    ALTER TABLE [dbo].[Countries] CHECK CONSTRAINT [FK_Countries_Continent]
    GO
    

    この関係を視覚化するには、以下の図9をご覧ください。

    ContinentID 2つのテーブルを相互に関連付けるキーです。

    複数の参照を持つ子テーブル

    SportsCar テーブルには、3つの異なるテーブルへの複数の参照があります:

    -- Multiple References
    CREATE TABLE [dbo].[SportsCars](
    	[SportsCarID] [int] IDENTITY(1,1) NOT NULL,
    	[ManufacturerID] [int] NULL,
    	[StyleID] [int] NULL,
    	[CountryID] [int] NULL,
    	[Model] [nvarchar](50) NOT NULL,
    	[Years] [varchar](50) NOT NULL,
    	[Notes] [varchar](255) NOT NULL,
    	[Modified] [datetime] NOT NULL,
     CONSTRAINT [PK_SportsCars] PRIMARY KEY CLUSTERED 
    (
    	[SportsCarID] ASC
    ))
    GO
    
    ALTER TABLE [dbo].[SportsCars] WITH CHECK ADD CONSTRAINT [FK_SportsCars_Country] FOREIGN KEY([CountryID])
    REFERENCES [dbo].[Countries] ([CountryID])
    GO
    
    ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Country]
    GO
    
    ALTER TABLE [dbo].[SportsCars] WITH CHECK ADD CONSTRAINT [FK_SportsCars_Manufacturer] FOREIGN KEY([ManufacturerID])
    REFERENCES [dbo].[Manufacturers] ([ManufacturerID])
    GO
    
    ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Manufacturer]
    GO
    
    ALTER TABLE [dbo].[SportsCars] WITH CHECK ADD CONSTRAINT [FK_SportsCars_Styles] FOREIGN KEY([StyleID])
    REFERENCES [dbo].[Styles] ([StyleID])
    GO
    
    ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Styles]
    GO
    

    データベース図での表示方法は次のとおりです。

    自己参照

    位置階層は、次の表に自己参照を示しています。

    CREATE TABLE [dbo].[Ranks](
    	[RankId] [int] IDENTITY(1,1) NOT NULL,
    	[Rank] [varchar](50) NOT NULL,
    	[RankLevel] [smallint] NOT NULL,
    	[RankParentId] [int] NULL,
     CONSTRAINT [PK_Ranks] PRIMARY KEY CLUSTERED 
    (
    	[RankId] ASC
    )) ON [PRIMARY]
    GO
    
    ALTER TABLE [dbo].[Ranks] WITH CHECK ADD CONSTRAINT [FK_Ranks_Ranks] FOREIGN KEY([RankParentId])
    REFERENCES [dbo].[Ranks] ([RankId])
    GO
    
    ALTER TABLE [dbo].[Ranks] CHECK CONSTRAINT [FK_Ranks_Ranks]
    GO
    

    この自己参照の図は単純です。この行は、自己参照で同じテーブルを指しています。

    ONUPDATEおよびONDELETEを使用

    ON UPDATE CASCADEを使用すると、主キー列の値を更新すると、関連するテーブルの外部キー値も更新されます。一方、ON DELETE CASCADEを使用する場合、主キーを削除すると外部キーも削除されます。 ONUPDATEおよびONDELETEのデフォルトはNOACTIONです。

    UPDATEおよびDELETECASCADEの例を次に示します。

    ALTER TABLE [dbo].[Countries] WITH CHECK ADD CONSTRAINT [FK_Countries_Continent] FOREIGN KEY([ContinentID])
    REFERENCES [dbo].[Continent] ([ContinentID]) 
    ON UPDATE CASCADE 
    ON DELETE CASCADE
    GO
    

    SQL外部キー制約の無効化

    以下は、既存の外部キー制約を無効にします。関係はまだ存在していることに注意してください。

    ALTER TABLE [dbo].[SportsCars] NOCHECK CONSTRAINT [FK_SportsCars_Country]
    GO
    

    これはデフォルトではないため、お勧めしません。ただし、一括挿入と更新を高速化するために、上記のような外部キーを一時的に無効にすることができます。完了したら、CHECKCONSTRAINTを使用して元に戻す必要があります。

    ALTER TABLE [dbo].[SportsCars] CHECK CONSTRAINT [FK_SportsCars_Country]
    GO
    

    落とし穴と修正

    このセクションでは、外部キーを使用してレコードをINSERT、UPDATE、またはDELETEしたときに何が起こるかを示します。これは、外部キーが無効にされていないことも前提としています。 NOCHECKCONSTRAINTを使用します。これは、これらの一般的な問題が発生したときに役立ちます。

    挿入時

    -- This will cause an error because countryID = 47 does not exist in the Countries table
    INSERT INTO SportsCars 
    (ManufacturerID, StyleID, CountryID, Model, Years, Notes) 
    VALUES (108, 10, 47, 'F2', '2021', 'Limited Edition')
    GO
    

    エラーメッセージは次のとおりです。

    Msg 547, Level 16, State 0, Line 56
    The INSERT statement conflicted with the FOREIGN KEY constraint "FK_SportsCars_Country". The conflict occurred in database "Vehicles", table "dbo.Countries", column 'CountryID'.
    The statement has been terminated.
    

    修正 CountryIDを追加します =47をに 最初にテーブル。次に、上記のINSERTステートメントを再実行します。シーケンスは、レコードを親テーブルに挿入し、次に子テーブルに挿入することから始まります。

    更新時

    -- Update CountryID to 47 will trigger an error.
    UPDATE SportsCars
    SET CountryID = 47
    WHERE ManufacturerID = 108
    GO
    

    UPDATEエラーは次のとおりです:

    Msg 547, Level 16, State 0, Line 60
    The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_SportsCars_Country". The conflict occurred in database "Vehicles", table "dbo.Countries", column 'CountryID'.
    The statement has been terminated.
    

    修正 CountryIDを追加します =47をに テーブル。次に、UPDATEステートメントを再実行します。

    削除時

    -- This will trigger an error because ManufacturerID = 108 is referenced in the SportsCars table
    DELETE FROM Manufacturers
    WHERE ManufacturerID = 108
    

    このコードは、次のようなエラーをトリガーします:

    Msg 547, Level 16, State 0, Line 64
    The DELETE statement conflicted with the REFERENCE constraint "FK_SportsCars_Manufacturer". The conflict occurred in database "Vehicles", table "dbo.SportsCars", column 'ManufacturerID'.
    The statement has been terminated.
    

    修正 SportsCarsから対応するレコードを削除します ManufacturerIDのテーブル =108。次に、上記のDELETEステートメントを再実行します。もう1つの方法は、該当する場合はONDELETECASCADEを有効にすることです。シーケンスは、子テーブルからレコードを削除することから始まり、次に–親テーブルからレコードを削除します。

    要点

    それで、外部キーはまだあなたにとって外部キーですか?

    これまでに学んだことを要約してみましょう。

    • 外部キーは2つのテーブル(または自己参照を使用する場合は1つのテーブル)をリンクします。参照整合性を確保するためにそれらが必要です。
    • GUIツールまたはT-SQLのいずれかを使用して、外部キー制約を追加、編集、または削除できます。
    • GUIツールの場合、SQL ServerManagementStudioまたはdbForgeStudioforSQLServerを使用できます。どちらもデータベース図とテーブルデザイナを提供して、主キーと外部キーを使用してテーブルを作成します。
    • CREATETABLEとALTERTABLEは、外部キー制約の追加と削除に適しています。
    • ALTERTABLEのNOCHECKCONSTRAINTを使用して、外部キーを一時的に無効にすることができます。これにより、一括挿入と更新が高速化されます。ただし、必ずCHECKCONSTRAINTを使用して有効に戻してください。
    • 外部キーの問題を回避するには、正しい順序に従うようにしてください。 INSERTおよびUPDATEの場合、最初に親テーブルに挿入し、次に子テーブルに挿入します。 DELETEの場合、最初に子レコードを削除してから、親レコードを削除します。

    初心者が外部キーを習得するのに役立つ何かを追加しますか? コメント セクションはあなたの明るいアイデアのために開かれています。この投稿が気に入ったら、お気に入りのソーシャルメディアプラットフォームで共有してください。


    1. 動的SQL(パラメーターとしてテーブル名を渡す)

    2. 2つのデータベース間に外部キー関係を追加する

    3. Java JDBC MySQLの例外:ResultSetを閉じた後の操作は許可されません

    4. Oracleを使用してINTOを選択