実行していますが、 、 などINSERT INTO Foo VALUES (a, b, c, ...)
のいずれかが外部キー制約を満たさないことがあります。a
b
この状況では、挿入が行われず、エラーが生成されないようにしたいと考えています。
これを 1 つのステートメントで行うことはできますか、それとも別のステートメントで行う必要がありIF EXISTS
ますか?
はい。ignoreキーワードを使用します。
INSERT IGNORE INTO `foo` (...) VALUES (...);
IGNORE キーワードを使用すると、INSERT ステートメントの実行中に発生したエラーは代わりに警告として扱われます。たとえば、IGNORE を使用しない場合、テーブル内の既存の UNIQUE インデックスまたは PRIMARY KEY 値を複製する行は、重複キー エラーを引き起こし、ステートメントは中止されます。IGNORE を使用すると、行はまだ挿入されませんが、エラーは発行されません。
一方、懸念が親行の前に子を挿入しているという事実によるものである場合は、親が挿入された後に制約を無効にし、それらを有効にすることもできます。
SET FOREIGN_KEY_CHECKS=0;
-- do your inserts not caring about foreign keys
SET FOREIGN_KEY_CHECKS=1;
ただし、これは、データの整合性を尊重していることがわかっている場合に限ります。
余談ですが、mysql Web サイトで見つかった遅延制約に関する次のコメントを追加する価値があると思います。
一般的な MySQL と同様に、多くの行を挿入、削除、または更新する SQL ステートメントでは、InnoDB は UNIQUE および FOREIGN KEY 制約を行ごとにチェックします。外部キー チェックを実行する場合、 InnoDB は、参照する必要がある子レコードまたは親レコードに共有行レベル ロックを設定します。InnoDB はすぐに外部キー制約をチェックします。チェックはトランザクションのコミットまで延期されません。SQL 標準によると、デフォルトの動作は遅延チェックです。つまり、制約は、SQL ステートメント全体が処理された後にのみチェックされます。InnoDB が遅延制約チェックを実装するまでは、外部キーを使用して自分自身を参照するレコードを削除するなど、いくつかのことが不可能になります。
MySQL innoDB が将来この機能を実装する可能性があることを認識しています。
これを行う最善の方法は、次を使用することです。
INSERT INTO table (col1, col2) SELECT val1, val2 FROM table2 WHERE val3 = 123
WHERE
一部の結果が次の場合、false
全体INSERT
は実行されません。同時に、SELECT val1, val2
必要なサブクエリを含めることができます。
あなたの場合、おそらくWHERE
条件に外部キーが存在するかどうかを確認します。
詳細な説明については、MySQL INSERT IF (カスタム if ステートメント)を参照してください。
挿入用の SQL の構造を完全に制御できる場合は、次のようなことを試すことができます。
insert into Foo (a, b, c)
select
x.a,
x.b,
x.c
from
(select
101 as a,
202 as b,
'ABC123' as c
from dual ) x
inner join other_table y
on x.b = y.pkid
この例では、データとその親テーブルで内部結合を実行しているため、データの外部キー値に対応する値がプライマリ テーブルにない場合、何も挿入されません。