いいえ、大丈夫ではありません。テーブル間の循環参照は厄介です。この(10年前の)記事を参照してください: SQL By Design:The Circular Reference
一部のDBMSはこれらを特別な注意を払って処理できますが、MySQLには問題があります。
オプション1
設計として、2つのFKの1つをnull許容にする。これにより、鶏と卵の問題を解決できます(最初にどのテーブルに挿入する必要がありますか?)。
コードに問題があります。これにより、製品にデフォルトの画像を設定して、その画像が別の製品を参照できるようになります。
このようなエラーを禁止するには、FK制約を次のようにする必要があります。
CONSTRAINT FK_products_1
FOREIGN KEY (id, default_picture_id)
REFERENCES products_pictures (product_id, id)
ON DELETE RESTRICT --- the SET NULL options would
ON UPDATE RESTRICT --- lead to other issues
これにはUNIQUE
が必要です テーブルproducts_pictures
の制約/インデックス (product_id, id)
上記のFKが定義され、正しく機能するために。
オプション2
もう1つの方法は、Default_Picture_ID
を削除することです。 product
の列 テーブルを作成し、IsDefault BIT
を追加します picture
の列 テーブル。このソリューションの問題は、製品ごとに1つの画像のみがそのビットをオンにし、他のすべての画像がそれをオフにする方法です。 SQL-Server(およびPostgresでは)では、これは部分インデックスを使用して実行できます:
CREATE UNIQUE INDEX is_DefaultPicture
ON products_pictures (Product_ID)
WHERE IsDefault = 1 ;
しかし、MySQLにはそのような機能はありません。
オプション3
このアプローチでは、両方のFK列をNOT NULL
として定義することもできます。 延期可能な制約を使用することです。これはPostgreSQLで機能し、Oracleでも機能すると思います。この質問と@Erwinによる回答を確認してください:SQLAlchemyの複雑な外部キー制約
(すべてのキー列がNULLではありません パート)。
MySQLの制約は延期できません。
オプション4
(私が最もきれいだと思う)アプローチは、Default_Picture_ID
を削除することです。 列を作成し、別のテーブルを追加します。 FK制約に循環パスはなく、すべてのFK列はNOT NULL
になります このソリューションで:
product_default_picture
----------------------
product_id NOT NULL
default_picture_id NOT NULL
PRIMARY KEY (product_id)
FOREIGN KEY (product_id, default_picture_id)
REFERENCES products_pictures (product_id, id)
これには、UNIQUE
も必要です。 テーブルproducts_pictures
の制約/インデックス (product_id, id)
ソリューション1のように。
要約すると、MySQLには2つのオプションがあります:
-
オプション1(null許容FK列)と上記の修正により、整合性を正しく適用します
-
オプション4(null許容FK列なし)