SQLでレコードを更新/挿入するための正しい/最速の方法は何ですか(Firebird / MySql)
質問
データベース内のレコードが存在する場合は更新し、存在しない場合は挿入するためにいくつかのSQLが必要です。周りを見てみると、これに対するいくつかの解決策があるように見えますが、これを行います。
アップデートは両方のデータベースに対して実行する必要があるため、Firebird 2とMySQL 5の両方で動作するのが理想的です。プラスになります。
速度と信頼性もこの場合の速度よりも信頼性に影響しますが、(異なるテーブルで)数千のレコードをすばやく連続して更新するために使用される可能性があります。
サブジェクション?
解決
次のいずれかを使用する必要があります。
BEGIN TRANSACTION
IF EXISTS (SELECT * FROM the_table WHERE pk = 'whatever')
UPDATE the_table SET data = 'stuff' WHERE pk = 'whatever'
ELSE
INSERT INTO the_table (pk, data) VALUES ('whatever', 'stuff')
COMMIT
または、ただし、個別に送信し、主キー制約の違反に関するINSERTのエラーを無視します。
INSERT INTO the_table (pk, data) VALUES ('whatever', 'stuff')
UPDATE the_table SET data = 'stuff' WHERE pk = 'whatever'
他のヒント
Firebird 2.1では、 UPDATE OR INSERT を使用できます単純な場合は MERGE はより複雑なシナリオです。
MySQLの場合、REPLACE
コマンドを試してください: http:/ /dev.mysql.com/doc/refman/5.0/en/replace.html
(Firebirdの同等物については、Milan Babuskovによるこの回答に関するコメントを参照してください。)
2.1より前のfirebirdでは、このトリッキーな方法を使用できます:
insert into table (id, a, b, c) values (:id, :a, :b, :c)
when SQLCODE -803
do
begin
update table set a = :a, b = :b, c = :c where id = :id;
end;
REPLACEはINSERTとまったく同じように機能しますが、テーブル内の古い行がPRIMARY KEYまたはUNIQUEインデックスの新しい行と同じ値を持つ場合、新しい行が挿入される前に古い行が削除されます。
構文:
REPLACE [LOW_PRIORITY |遅延] [INTO] tbl_name [(col_name、...)]
{ VALUES | VALUE}
({expr | DEFAULT},...),(...),...
理由:制約を操作するときは、置換を避けるのが最善です。
MySQLでINSERTを使用しましたで行を更新するには:
INSERT INTO table () VALUES () ON DUPLICATE KEY UPDATE key
ただし、自動生成されたキーは使用できません。