2009-07-15 8 views
0

私はmysqlに "IF record EXISTS THEN UPDATE ELSE INSERT"を実装しようとしています。具体的には、私はDoctrine ORMでそれを行う方法を理解しなければなりません。"IF"を使ってmysql文を開始できますか?

ネイティブMySqlを使用する1つのソリューションは、「ON DUPLICATE KEY UPDATE」を使用することです。これは残念ながらDoctrineではサポートされていません。

もう1つの半解決策は、 "REPLACE INTO"構文を使用することです。 Doctrineはこれをサポートしていますが、REPLACEはレコードを更新しません。代わりにレコードを削除し、新しい自動インクリメントIDを使用して新しいレコードを作成します。これにより、自動インクリメントIDに依存すると悪い解決策になります。

私が操作しようとしているテーブルはINNODBなので、トランザクションを調べましたが、トランザクションの内部に同じルールが適用されているかどうかは完全には分かりません。

「IF(INSERT IGNORE INTOテーブルcritical_id = $ id)トランザクション内でELSE(UPDATEテーブルSET field = 'new_value')を終了しますか?

このようなことを言うことができない場合、この問題の解決策はありますか?

答えて

1

どちらの「DUPLICATE KEY UPDATE ON」にする方法を見つける作業、または二つの文を使用するように切り替える:最初の更新や、必要に応じて挿入し、既存の行を見つけるために選択します。

これはあなたにとって唯一のオプションです。上記の作業を行うストアドプロシージャを作成するのに手間がかかります。

+0

私は "重複キー"を使用する方法を見つけたので、これは最善の解決策だと思うので、私はこの回答を受け入れますが、mysql固有の用語を持たないトランザクションソリューションがあるかどうかを調べようとしています。 fwiw、タイトルに掲げられた質問は決して答えられなかった。答えは、IFでSELECT、INSERT、UPDATEステートメントを開始できないと思います。他のdbmsに存在するRecordcountというプロパティについて聞いたことがあります。私は、レコードが変更されたかどうかを教えてくれるmysqlの同等のもの、つまり "内部トランザクションカウンタ"を探していました。まだ見ている。 – seans

0

あなたはすでにINSERT IGNORE INTOについて言及しています。これはあなたのニーズを満たしていないのですか?

http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html

+0

すでにレコードが存在する場合は、レコードを更新する予定です。私が間違っていない限り、INSERT IGNOREはすべてをスキップします。 – seans

1

「挿入または更新」は、「Upsert」と呼ばれます。 google "upsert mysql"の場合は、ほんのわずかの解決策があることがわかります。

  1. 2ステップ、挿入、[更新および変形
  2. "DUPLICATE KEY UPDATE ON"

そしておそらくいくつかのより多くをREPLACEが、それらのほとんどはバリエーションがあります。

あなたのSQLは次のようになり、トランザクションを使用した:

UPDATE xxx SET (x1, x2) = (y1, y2) WHERE id = myid; 
    IF found THEN 
     RETURN; 
    END IF; 
    BEGIN 
     INSERT INTO xxx (x1, x2) VALUES (y1, y2); 
     RETURN; 
    EXCEPTION WHEN unique_violation THEN 
    --##Do nothing, or you can put this whole sql code 
    --##in a LOOP and it will loop over and try update again 
    END; 

このコードは私のPostgreSQLの機能の一つから取り除かれます。私はInnoDBがこれをサポートしていないと思うが、間違っているかもしれない。

関連する問題