まず、グーグルで調べてみると、ミューテックス・テーブルについて書かれたこの記事を見つけました。
私は約1,400万件のレコードを持つテーブルを持っています。同じフォーマットのデータを追加したい場合、挿入したいレコードがすでに存在しないことを、2つのクエリを使用せずに確認する方法はありますか(つまり、チェックするクエリと、結果セットが空の場合に挿入するクエリ)?
フィールドに unique
制約を設けると、既に存在する場合に insert
が失敗することになりますか?
単なる制約では,phpで挿入を行うと,スクリプトが終了してしまいます。
テーブルへのINSERT IGNORE INTOの使用
http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html を参照してください。
また、dev.mysql.comで説明されているように、INSERT ... ON DUPLICATE KEY UPDATE
構文もあります。
**Google's webcache]1によると、bogdan.org.uaからの投稿は以下の通りです。
2007年10月18日
はじめに:最新のMySQLでは、タイトルにあるような構文はできません。 できません。しかし、既存の機能を使って、期待されることを実現する非常に簡単な方法がいくつかあります。 しかし、既存の機能を使って期待されることを実現する非常に簡単な方法がいくつかあります。
3つの可能な解決策があります:INSERT IGNORE、REPLACE、または > insert ... on duplicate key update を使うことです。 重複するキーの更新時に挿入する。
テーブルがあるとします。
CREATE TABLE
transcripts
(ensembl_transcript_id
varchar(20) NOT NULL,transcript_chrom_start
int(10) unsigned NOT NULL,transcript_chrom_end
int(10) unsigned NOT NULL, PRIMARY KEY (ensembl_transcript_id
) )ENGINE=InnoDB DEFAULT CHARSET=latin1;ここで、Ensemblからトランスクリプトのメタデータをインポートする自動パイプラインがあるとします。 メタデータをEnsemblからインポートする自動パイプラインがあり、そのパイプラインが様々な理由で 実行のどの段階でも壊れてしまう可能性があります。そこで、次の2つを確保する必要があります。 確保する必要があります。1) パイプラインを繰り返し実行しても、データベースが破壊されないこと。 データベースを破壊しない。 主キーの重複」エラーで死なないようにすることです。
方法1:REPLACEの使用
とても簡単です。
REPLACE INTO
transcripts
(トランスクリプト) SETensembl_transcript_id
= 'ENSORGT00000000001',transcript_chrom_start
= 12345,transcript_chrom_end
= 12678;レコードが存在する場合は上書きされ、まだ存在しない場合は作成されます。 存在しない場合は作成されます。しかし、この方法を使うのは、今回のケースでは効率的ではありません。 今回のケースでは、既存のレコードを上書きする必要はありません。 既存のレコードを上書きする必要はなく、単にスキップすればよいのです。
方法2:INSERT IGNOREの使用 これも非常に簡単です。
INSERT IGNORE INTO
transcripts
(トランスクリプト) SETensembl_transcript_id
= 'ENSORGT00000000001',transcript_chrom_start
= 12345,transcript_chrom_end
= 12678 です。ここで、'ensembl_transcript_id'が既にデータベースに存在している場合は ここで、「ensembl_transcript_id」がすでにデータベースに存在している場合は、静かにスキップ(無視)されます。(もっと正確に言うと 以下はMySQLのリファレンスマニュアルからの引用です。"IGNORE キーワードを使用すると キーワードを使用すると、INSERT 文の実行中に発生したエラーは、警告として扱われます。 代わりに警告として扱われます。例えば、IGNORE を使用しない場合、既存の UNIQUE INDEX と重複している > 行は警告として扱われます。 テーブルの既存のUNIQUEインデックスやPRIMARY KEYの値と重複する行は 重複キーのエラーが発生し、文が中止されます。".)もし、その レコードがまだ存在しない場合は作成されます。
この2番目の方法には、以下のような潜在的な弱点があります。 他の問題が発生した場合に、クエリをアボートしないこと(マニュアルを参 マニュアル参照)。そのため、事前にIGNOREキーワードなしでテストした場合に使用すべきです。 IGNOREキーワードなしでテストした場合に使用してください。
もう1つの選択肢は、「INSERT ... ON DUPLICATE KEY UPDATE」構文を使用することです。 構文を使用し、UPDATE部分では何もしないで、無意味な(空の)操作、例えば、計算 0+0 を計算するような、意味のない(空の)操作をするだけです(Geoffray は MySQL の id=id の代入を行うことを提案しています)。 id=id を割り当てて、MySQL の最適化エンジンがこの操作を無視するように 演算を無視するように提案しています)。)この方法の利点は、重複したキーイベントを無視するだけで この方法の利点は、重複したキーイベントを無視するだけで、他のエラーでは中止することです。
この記事はXaprbに触発されて書きました。また、次のこともアドバイスします。 柔軟なSQLクエリの書き方に関する彼の他の投稿も参考にしてください。
MySQLでは、on duplicate key update、または[insert ignore][2]が有効なソリューションとなります。
重複キー更新時]1の更新の例(mysql.comより)。
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
mysql.comをベースにした[insert ignore][2]の例。
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
または
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
または
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
例外が許されるのであれば、どんな単純な制約でも良いはずです。例:
申し訳ありませんが、これは非常に単純なことです。あなたが共有しているリンクに照らし合わせてみると、悪い印象を受けますよね。
しかし、あなたのニーズを満たしているように見えるので、私は決してこの答えを与えません。(もしそうでなければ、あなたが要求を更新するきっかけになるかもしれませんし、それは「良いこと」(TM)でもあります。)
編集済み。挿入がデータベースのユニーク制約を破る場合、データベースレベルで例外が発生し、ドライバによって中継されます。これは確実に失敗してスクリプトを停止させます。このような場合、PHPで対処することは可能でしょうか?