18

与えられたスキーマ:

ここに画像の説明を入力

私が必要とするのは、すべてuser_identities.belongs_toの参照をusers.id.

同時に、すべてusersprimary_identity写真のようにアタリがあります。

ただし、この参照を で追加しようとするとON DELETE NO ACTION ON UPDATE NO ACTION、MySQL は言う

#1452 - 子行を追加または更新できません: 外部キー制約が失敗します ( yap. #sql-a3b_1bf, CONSTRAINT #sql-a3b_1bf_ibfk_1FOREIGN KEY ( belongs_to) REFERENCES users( id) ON DELETE NO ACTION ON UPDATE NO ACTION)

これは循環依存が原因だと思われますが、どうすれば解決できますか (そして参照整合性を維持できますか)?

4

6 に答える 6

11

これを解決する唯一の方法は (少なくとも MySQL の機能が限られている場合) NULL、両方の FK 列に値を許可することです。プライマリ ID を持つ新しいユーザーを作成すると、次のようになります。

insert into users (id, primary_identity)
values (1, null);

insert into identities (id, name, belongs_to)
values (1, 'foobar', 1);

update users 
  set primary_identity = 1
where id = 1;

commit;

このソリューションの唯一の欠点は、ユーザーがプライマリ ID を持つように強制できないことです (列が null 可能である必要があるため)。


別のオプションは、遅延制約をサポートする DBMS に変更することです。その後、2 つの行を挿入するだけで、制約はコミット時にのみチェックされます。または、部分インデックスを持つことができる DBMS を使用すると、is_primary列でソリューションを使用できます。

于 2012-09-29T11:34:20.693 に答える
7

私はそれをこのように実装しません。

primary_identityテーブルからフィールドを削除し、という名前のusersテーブルにフィールドを追加します。これをプライマリプロファイルのインジケーターとして使用します。user_profilesis_primary

于 2012-09-29T11:11:51.080 に答える
2

これにより、 の NULL が防止FKsされますが、プライマリ プロファイルが存在することは強制されません。アプリケーションで管理する必要があります。

tableの代替キー (一意のインデックス) と一致する FK に注意し{UserID, ProfileID}ProfileくださいPrimaryProfile

ここに画像の説明を入力

于 2012-10-04T19:49:13.120 に答える
0

この質問は、削除側からMySQL の循環外部キーを持つテーブルを削除する方法で提起されましたが、答えの 1 つがここにも当てはまると思います。

SET foreign_key_checks = 0;
INSERT <user>
INSERT <user identity>
SET foreign_key_checks = 1;

それをトランザクションにして、一度にすべてコミットします。試したことはありませんが、削除では機能するため、挿入では機能しない理由がわかりません。

于 2013-08-05T14:17:09.623 に答える
0

問題は、プライマリ ID 情報を user_identities テーブルに保持しようとしていることにあるようです。

代わりに、主要なユーザー情報 (名前/電子メール) を users テーブルに入れることをお勧めします。user_identities テーブルへの外部キーは使用しないでください。

user_identities テーブルからの外部キーのみ

すべての制約は、一方向のみであるため、正常に機能するようになりました。

user_identities は、プライマリ ユーザー (ユーザー テーブル内) が存在しない限り入力できません。同様に、(user_identities 内に) 既存の子 ID がある場所では、プライマリ ユーザーを削除できません。

何が起こっているのかを明確にするために、テーブルの名前を「primary_users」および「secondary_users」に変更することをお勧めします。

それは大丈夫ですか?

于 2012-10-01T09:36:37.093 に答える
0

私はそれを使用していませんが、INSERT IGNOREを試すことができます。テーブルごとに 1 つずつ、そのうちの 2 つを実行して、両方が完了すると、参照整合性が維持されるようにします。トランザクションでそれらを行う場合、2 番目のトランザクションの挿入に問題がある場合はロールバックできます。

この機能では制約を無視しているため、代わりにプログラム コードでそのチェックを行う必要があります。そうしないと、データベース内のデータが制約を無視してしまう可能性があります。

上記の問題を指摘してくれた@Mihaiに感謝します。別のアプローチは、挿入中に制約を無効にし、後で再度有効にすることです。ただし、許容範囲を超えるオーバーヘッドが発生する可能性がある大きなテーブルでは、試してみてください。

于 2012-09-29T11:28:32.690 に答える