UPSERTとINSERTについて

返信する
choco
管理人
記事: 279
登録日時: 2011年5月30日(月) 10:44

UPSERTとINSERTについて

投稿記事 by choco »

データを新規にDBに登録する時に悩むのが、既に同じデータがあったら更新して欲しい。
ですよね。

普通は、それなりの関数を書く必要がありますがOracleは専用の命令がある所が凄いです。

【MERGE】とその凄さについて軽く説明しておきます。

まず、【MERGE】の書式はこうです。

MERGE INTO 表名1
  USING 表名2 | 副問い合わせ
  ON ( 結合条件 )
WHEN MATCHED THEN
  UPDATE SET 列名1 = 値1, 列名2 = 値2, ・・・
WHEN NOT MATCHED THEN
  INSERT [( 列名1, 列名2, ・・・ )] VALUES ( 値1, 値2, ・・・ )

で、こんなテーブルを用意しちゃったりします。

ID TEXT DATE
---------- ------------------------------ --------
1 AAAA 08-07-03
2 BBBB 08-07-03
3 CCCC 08-07-03

1.上記のテーブルに対して、DDDDをインサートしてみましょう。

MERGE INTO TEST01
USING DUAL
ON (ID=4)
WHEN MATCHED THEN
UPDATE SET TEXT='DDDD'
WHEN NOT MATCHED THEN
INSERT ( ID, TEXT ) VALUES ( 4,'DDDD' )
;


こんな結果になりました。

ID TEXT DATE
---------- ------------------------------ --------
1 AAAA 08-07-03
2 BBBB 08-07-03
3 CCCC 08-07-03
4 DDDD 08-07-03

2.上記のテーブルに対して、ID=3、TEXT=DDDDを更新してみましょう。

MERGE INTO TEST01
USING DUAL
ON (ID=3)
WHEN MATCHED THEN
UPDATE SET TEXT='DDDD'
WHEN NOT MATCHED THEN
INSERT ( ID, TEXT ) VALUES ( 3,'DDDD' )
;

で、こうなります。

ID TEXT DATE
---------- ------------------------------ --------
1 AAAA 08-07-03
2 BBBB 08-07-03
3 DDDD 08-07-03

バインド変数を使うと更にこんな構文に。

DECLARE
id NUMBER;
text VARCHAR(30);
u_cur INTEGER;
u_sql VARCHAR2(1000);
u_row INTEGER;

BEGIN
id := 4;
text := 'DDDD';

u_cur := DBMS_SQL.OPEN_CURSOR;
u_sql := 'MERGE INTO TEST01 USING DUAL ON (ID=:b1) WHEN MATCHED THEN UPDATE SET TEXT=:b2 WHEN NOT MATCHED THEN INSERT ( ID, TEXT ) VALUES ( :b1, :b2 )';
DBMS_SQL.PARSE(u_cur, u_sql, dbms_sql.v7);
DBMS_SQL.BIND_VARIABLE(u_cur, ':b1', id);
DBMS_SQL.BIND_VARIABLE(u_cur, ':b2', text);
u_row := DBMS_SQL.EXECUTE(u_cur);
DBMS_SQL.CLOSE_CURSOR(u_cur);

End
;
/

・・・なりました。
返信する