2011-01-04 38 views
1

私は、主キーが重複である場合に、代わりにUPDATEを使用する必要がある簡単なINSERTクエリを持っています。 MySQLでは、これは簡単ですが、OracleではMERGEを使用する必要があるようです。OracleのINSERT重複プライマリ・キーのUPDATE?

私が見つけたMERGEのすべての例には、ソースとターゲットのテーブルがあります。私の場合、ソースとターゲットは同じテーブルです。私は自分のクエリを作成するための例を理解できませんでした。

マージは唯一の方法ですか、それとももっと良い解決策がありますか?

INSERT INTO movie_ratings 
VALUES (1, 3, 5) 

それは基本的に、このだとプライマリキーは、最初の2つの値であるので、更新は次のようになります:

UPDATE movie_ratings 
SET rating = 8 
WHERE mid = 1 AND aid = 3 

私は自動的にUPDATEステートメントを実行しますトリガを使用するのではと思いました主キーが重複している場合にのみ、INSERTが呼び出されました。このようにして問題がありますか?私はトリガーのいくつかの助けが必要ですが、私はそれらを理解しようとするといくつかの難しさを持っていると自分自身をやっている。これを行うの

+0

このような例では、INSERTの列名のリスト(オプション)を使用して、十分なテーブル構造を得ることができます。多分、MySQLで何が行われたのかを示したら、人々はあなたが何をしているのかを知るかもしれません。それは私の好奇心/怠惰なのかもしれません。 –

+0

テーブルの構造はimplicで、mid(int)、aid(int)、rating(int)です。 –

答えて

10

MERGEは、標準SQLの 'INSERTまたはUPDATE as appropriate'ステートメントであり、おそらくOracle SQLでもそうです。

はい、あなたからマージする「テーブル」が必要ですが、あなたはほぼ確実にその場でそのテーブルを作成することができます。

MERGE INTO Movie_Ratings M 
     USING (SELECT 1 AS mid, 3 AS aid, 8 AS rating FROM dual) N 
      ON (M.mid = N.mid AND M.aid = N.aid) 
     WHEN  MATCHED THEN UPDATE SET M.rating = N.rating 
     WHEN NOT MATCHED THEN INSERT( mid, aid, rating) 
          VALUES(N.mid, N.aid, N.rating); 

(。構文検証されていない)

+0

これはトリックでした。素晴らしいことを常に学ぶ:) –

+0

@ jonathan-leffler Oracle 11.1で私のためにエラーが発生するので、 'USING ... AS N'から 'AS'を削除する答えを編集しました – Stompchicken

+0

Oracleは** multi-table * INSERT/UPDATEステートメントで挿入/更新しますが、MERGEステートメントでは更新しません。未完成のソフトウェアについて話しています... –

1

典型的な方法は、INSERTを行う

  • とDUP_VAL_ON_INDEXをキャッチし、SQL%行= 0 INSERT
を行う場合は、最初の更新を実行する代わりに、
  • の更新を実行し、

    同じテーブルの別の操作を実行するテーブルにトリガを書き込むことはできません。これはOracleエラー(テーブルの変更)を引き起こしています。

  • +0

    それを知りませんでした、明確化のためにありがとう。しかし、それは必ずしも私の質問に答えるわけではないので、コメントであったはずです。 –

    +0

    @ Nazgulled:MERGEについての考えを加えました(私は今答えとして受け入れられると思う) – sjngm

    +0

    @ Nazgulled:Jonathan Lefflerの提案が実際にそのように機能するかもしれないので、私はMERGEを取り除いた。私は別の解決策を思いついた。 – sjngm

    0

    私はTよ-SQLの男だが、この場合のトリガは良い解決策ではない。ほとんどのトリガーは良い解決策ではありません。 T-SQLでは、私は単純にIFはEXISTS(WHERE dbo.Table SELECT * FROM ...)が、Oracleには、あなたが数を選択する必要があります...

    DECLARE 
        cnt NUMBER; 
    BEGIN 
        SELECT COUNT(*) 
        INTO cnt 
        FROM mytable 
        WHERE id = 12345; 
    
        IF(cnt = 0) 
        THEN 
        ... 
        ELSE 
        ... 
        END IF; 
    END; 
    

    それはMERGEがあると思われる実行することになりあなたは、この場合には必要なもの:

    MERGE INTO movie_ratings mr 
    USING (
        SELECT rating, mid, aid 
        WHERE mid = 1 AND aid = 3) mri 
    ON (mr.movie_ratings_id = mri.movie_ratings_id) 
    
    WHEN MATCHED THEN 
        UPDATE SET mr.rating = 8 WHERE mr.mid = 1 AND mr.aid = 3 
    
    WHEN NOT MATCHED THEN 
        INSERT (mr.rating, mr.mid, mr.aid) 
        VALUES (1, 3, 8) 
    

    私が言ったように、私はT-SQLの男だが、ここで基本的な考え方は、それ自体に対してmovie_ratingテーブルを「参加」することです。 if existsを使用したときにパフォーマンスが低下しない場合は、読みやすくするために使用します。

    関連する問題