web-dev-qa-db-ja.com

INSERTの前にSELECTで常に確認しますか?

主キーがまだ存在しない場合にのみ行をINSERTしたい場合、INSERTを直接実行して、重複の場合にエラーを無視する方が効率的/簡単ですか、または私は常にSELECTを実行して、最初にすでに存在するかどうかを確認しますか?

6
James

WHERE NOT EXISTSを使用して、新しいレコードを挿入する前に新しい値を確認できます。

INSERT INTO <table>
(
    field1, field2, field3
)
SELECT value1, value2, value3
FROM dual
WHERE NOT EXISTS (SELECT 1
                  FROM <table>
                  WHERE <pk fields> = <new values>);
CREATE TABLE foo(id int, v1 int, v2 int);
INSERT INTO foo VALUES (1, 100,100);
INSERT INTO foo VALUES (2, 200, 200);

このレコードは存在するため、挿入しないでください:

INSERT INTO foo (id, v1, v2)
SELECT 1, 101, 101
FROM   dual
WHERE NOT EXISTS (SELECT 1 FROM foo WHERE id=1);

これは新しいレコードです。

INSERT INTO foo (id, v1, v2)
SELECT 3, 300, 300
FROM   dual
WHERE NOT EXISTS (SELECT 1 FROM foo WHERE id=3);

最終結果:

SELECT * FROM foo;
 id | v1 | v2 
-:| -:| -:
 1 | 100 | 100 
 2 | 200 | 200 
 3 | 300 | 300 

dbfiddle ここ

4
McNets

最良(より効率的なオプション)は、PK衝突の予想される確率に依存します。

衝突の可能性が高い場合は、DMLオーバーヘッドを節約し、SELECTの前に最初にINSERTを実行します。

衝突する可能性が低い場合は、INSERT IGNOREを実行するだけで十分です。

注:PKがauto_incrementの場合、失敗したINSERT IGNOREauto_incrementを膨らませる可能性があります(変数オプションについては innodb_autoinc_lock_mode を参照)。

2
Riedsio

通常、IODKUがより良い方法です。

INSERT INTO tbl ...
    ON DUPLICATE KEY UPDATE 
        ....

https://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html

1
Rick James