Oracle ¤Î MERGE ¹½Ê¸¤Ë´Ø¤¹¤ëÈ÷˺Ͽ - ¥Ð¥¤¥ó¥ÉÊÑ¿ô¤Î°·¤¤Êý
DB ¥¢¥×¥ê¤ò½ñ¤¤¤Æ¤¤¤ë¤È¡¢¤É¤¦¤·¤Æ¤â»È¤¤¤¿¤¯¤Ê¤ë¤Î¤¬ UPSERT µ¡Ç½¡£
¼ÂºÝ¤Ë¤Ï UPSERT ¤È¤¤¤¦¹½Ê¸¤Ï¤¢¤ê¤Þ¤»¤ó¤¬¡¢°ÕÌ£¤È¤·¤Æ¤Ï¥ì¥³¡¼¥É¤¬¤¢¤ì¤Ð UPDATE ¤Ç¹¹¿·¤·¡¢¥ì¥³¡¼¥É¤¬¤Ê¤±¤ì¤Ð INSERT ¤ÇÄɲäò¤¹¤ë¤Ã¤Æ¤³¤È¤Ç¤¹¡£
½¾¤Ã¤Æ¡¢ÉáÄ̤˽ñ¤¯¤Ê¤é¡¢SELECT ¢ª UPDATE/INSERT ¤È¾ì¹çʬ¤±¤È¤¤¤¦¥í¥¸¥Ã¥¯¤Ç¥×¥í¥°¥é¥à¤ò½ñ¤¯¤ï¤±¤Ç¤¹¤¬¡¢¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤Ç¹Í¤¨¤ë¤È¥³¥ì¤¬°Õ³°¤È¤ä¤Ã¤«¤¤¤Ê¤È¤¤¬¤¢¤ê¤Þ¤¹¡£¤½¤Î¤è¤¦¤Ê¾ì¹ç¤Ï SELECT FOR UPDATE ¤È¤«»È¤Ã¤Æ¹Ô¥í¥Ã¥¯¤ò¤«¤±¤¿¤ê¤¹¤ëÌõ¤Ê¤Î¤Ç¤¹¤¬¡¢¤³¤ì¤Þ¤¿Í½´ü¤»¤Ì¥í¥Ã¥¯ÂÔ¤Á¤Î¸µ¤Ë¤Ê¤Ã¤¿¤ê¤¹¤ë¾ì¹ç¤¬¤¢¤êÆÀ¤ë¤Î¤Ç¡¢¤¢¤Þ¤ê¿Í¤Ë½ñ¤«¤»¤¿¤¯¤Ê¤¤¡£
Oracle ¤Ë¤Ï UPSERT ¤ËÁêÅö¤¹¤ë¹½Ê¸¤È¤·¤Æ MERGE ¹½Ê¸¤¬¤¢¤ë¤Î¤Ç¡¢·ë¹½½ÅÊõ¤·¤Þ¤¹¡£¤¿¤À¤· Oracle9 °Ê¹ß¤Ç¼ÂÁõ¤µ¤ì¤¿µ¡Ç½¤Ê¤Î¤Ç¤¹¤¬¡¢º£»þ 8i °ÊÁ°¤ò»È¤Ã¤Æ¤ë´Ä¶¤â¾¯¤Ê¤¤¤È»×¤¦¤Î¤ÇÌäÂê¤Ê¤¤¤Ç¤·¤ç¤¦¡£
MERGE ¹½Ê¸¤ÏÄ̾A¤Î¤è¤¦¤ËÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¤È»×¤¤¤Þ¤¹¡£Oracle ¤Î SQL ¥Þ¥Ë¥å¥¢¥ë¤â°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
¡¡¡¡USING¡¡É½Ì¾2¡¡¡Ã¡¡ÉûÌ䤤¹ç¤ï¤»
¡¡¡¡ON¡¡( ·ë¹ç¾ò·ï )
WHEN¡¡MATCHED¡¡THEN
¡¡¡¡UPDATE¡¡SET¡¡Îó̾1 = ÃÍ1,¡¡Îó̾2 = ÃÍ2,¡¡Ž¥Ž¥Ž¥
WHEN¡¡NOT¡¡MATCHED¡¡THEN
¡¡¡¡INSERT¡¡[( Îó̾1,¡¡Îó̾2,¡¡Ž¥Ž¥Ž¥ )]¡¡VALUES¡¡( ÃÍ1,¡¡ÃÍ2,¡¡Ž¥Ž¥Ž¥ )
¤Ç¡¢Â¿¤¯¤ÎÎãÂê¤Ë¤ª¤¤¤Æ¤Ï¡¢É½£±¤Èɽ£²¤ò£²¤Ä¤Îɽ¤ò¸µ¤Ë¥´¥Ë¥ç¥´¥Ë¥ç¤Ã¤Æ½èÍý¤¬¤«¤«¤ì¤Æ¤¤¤Æ¡¢¼ÂºÝ¤è¤¯»È¤¦ UPSERT ½èÍý¤È¤ÏÊÌÍÑÅÓ¤ÎÎãÂê¤Ê¤ó¤Ç¤¹¤è¤Í¡£
¤Ã¤Æ¤ï¤±¤Ç¡¢º£¤«¤éÅÐÏ¿¤¹¤ë¥Ç¡¼¥¿¤¬´û¤Ëɽ£±¤Ë¤¢¤ì¤Ð UPDATE ½èÍý¤Ç̵¤±¤ì¤Ð INSERT ½èÍý¤Ã¤Æ¸À¤¦¼ÂºÝ¤Î UPSERT ÍÑÅӤ˧¤·¤¿ÎãÂê¤ò¶¦Í¤·¤Æ¤ª¤³¤¦¤È»×¤¤¤Þ¤·¤Æ¤³¤Îµ»ö¤ò½ñ¤¤¤Æ¤¤¤Þ¤¹¡£
¤â¤Ã¤È¤â¡¢ MERGE ¹½Ê¸¤Ç UPSERT ½èÍý¤ò½ñ¤³¤¦¤È»×¤Ã¤¿¤é¡¢¥¢¥ì¡©¤É¤¦¤¹¤ë¤ó¤À¤Ã¤±¡©¤È¾®°ì»þ´Ö¤Û¤ÉǺ¤ó¤À¤Î¤Ç¤³¤¦¤·¤Æ¥á¥â¤Ë»Ä¤·¤Æ¤¤¤ë¤ï¤±¤Ç¤¹¤±¤É¡£(^^¡¶
¤µ¤Æ¡¢¼ÂºÝ¤Î UPSERT ÍÑÅÓ¤ËÂбþ¤µ¤»¤ë¤¿¤á¤Ë¤Ï DUAL ɽ¤ò³èÍѤ¹¤ë¼ê¤¬¤¢¤ê¤Þ¤¹¡£¼ÂºÝ¤ËÎã¤ò¸«¤ÆÌ㤦¤Î¤¬Áᤤ¤Ç¤·¤ç¤¦¡£
¤Þ¤º¤Ï¥Æ¥¹¥ÈÍѤÎɽ¤È¥Ç¡¼¥¿¤òºîÀ®¤¹¤ë¡£
CREATE TABLE TEST01 ( ID INTEGER PRIMARY KEY, TEXT VARCHAR(30), ON_CREATED DATE DEFAULT SYSDATE ); INSERT INTO TEST01 (ID, TEXT) VALUES( 1, 'AAAA' ); INSERT INTO TEST01 (ID, TEXT) VALUES( 2, 'BBBB' ); INSERT INTO TEST01 (ID, TEXT) VALUES( 3, 'CCCC' ); commit;
SQL> SELECT * FROM TEST01; ID TEXT ON_CREAT ---------- ------------------------------ -------- 1 AAAA 08-07-03 2 BBBB 08-07-03 3 CCCC 08-07-03
´Ö°ã¤¤¤òÀè¤Ë¼¨¤·¤Æ¤âʶ¤é¤ï¤·¤¤¤Î¤Ç¡¢¤Þ¤º¤ÏÀµ²ò¤«¤é¡£
ID=4, TEXT='DDDD' ¤ò INSERT ½èÍý¤·¤¿¤¤»þ¤Ï¤É¤¦¤¹¤ë¤«¡©
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=4 ¤ÎÎó¤¬ INSERT ¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤ï¤«¤ê¤Þ¤¹¡£
1¹Ô¤¬¥Þ¡¼¥¸¤µ¤ì¤Þ¤·¤¿¡£ SQL> SELECT * FROM TEST01; ID TEXT ON_CREAT ---------- ------------------------------ -------- 1 AAAA 08-07-03 2 BBBB 08-07-03 3 CCCC 08-07-03 4 DDDD 08-07-03
¤Ç¤Ï¼¡¤Ë¡¢ID=3, TEXT='DDDD' ¤È UPDATE ½èÍý¤·¤¿¤¤»þ¤Ï¤É¤¦¤¹¤ë¤«¡©
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=3 ¤ÎÎó¤¬ INSERT ¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤ï¤«¤ê¤Þ¤¹¡£
1¹Ô¤¬¥Þ¡¼¥¸¤µ¤ì¤Þ¤·¤¿¡£ SQL> SELECT * FROM TEST01; ID TEXT ON_CREAT ---------- ------------------------------ -------- 1 AAAA 08-07-03 2 BBBB 08-07-03 3 DDDD 08-07-03
¤µ¤Æ¡¢¤³¤ì¤Ç DUAL ɽ¤ò»È¤¦¤È¥¦¥Þ¥¤¶ñ¹ç¤Ë¼«Ê¬¼«¿È¤Îɽ¤ò UPDATE/INSERT ¤Ç¤¤ë¤³¤È¤¬¤ï¤«¤Ã¤Æ¤¤¿¤«¤È»×¤¤¤Þ¤¹¡£
´ðËܹ½Ê¸¤Ï¤³¤¦¤Ç¤¹¡£
¡¡¡¡USING¡¡DUAL
¡¡¡¡ON¡¡(Îó̾1 = ÃÍ1,¡¡Îó̾2 = ÃÍ2,¡¡Ž¥Ž¥Ž¥)
WHEN¡¡MATCHED¡¡THEN
¡¡¡¡UPDATE¡¡SET¡¡Îó̾1 = ÃÍ1,¡¡Îó̾2 = ÃÍ2,¡¡Ž¥Ž¥Ž¥
WHEN¡¡NOT¡¡MATCHED¡¡THEN
¡¡¡¡INSERT¡¡[( Îó̾1,¡¡Îó̾2,¡¡Ž¥Ž¥Ž¥ )]¡¡VALUES¡¡( ÃÍ1,¡¡ÃÍ2,¡¡Ž¥Ž¥Ž¥ )
¤µ¤Æ¡¢¼ÂºÝ¤Î¶È̳¤Ë¤ª¤¤¤Æ¤ÏÅöÁ³¤Î¤³¤È¤Î¤è¤¦¤Ë¥Ð¥¤¥ó¥ÉÊÑ¿ô¤ò»È¤¦¤³¤È¤Ë¤Ê¤ë¤Ç¤·¤ç¤¦¡£¼¡¤Ï¥Ð¥¤¥ó¥ÉÊÑ¿ôÂбþ¤Ë¤·¤Æ¤ß¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
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 ; /
¼Â¹Ô·ë²Ì¤Ï¤³¤¦¤Ê¤ê¤Þ¤¹¡£Àµ¾ï¤Ë ID=4 ¤ÎÎó¤¬ INSERT ¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤ï¤«¤ê¤Þ¤¹¡£
PL/SQL¥×¥í¥·¡¼¥¸¥ã¤¬Àµ¾ï¤Ë´°Î»¤·¤Þ¤·¤¿¡£ SQL> SELECT * FROM TEST01; ID TEXT ON_CREAT ---------- ------------------------------ -------- 1 AAAA 08-07-03 2 BBBB 08-07-03 3 CCCC 08-07-03 4 DDDD 08-07-03
Ʊ¤¸¤¯¡¢ID=3, TEXT='DDDD' ¤È UPDATE ½èÍý¤·¤¿¤¤»þ¤ò¥Ð¥¤¥ó¥ÉÊÑ¿ô¤Ç¤ä¤Ã¤Æ¤ß¤Þ¤¹¡£id := 3 ¤ÎÉôʬ¤¬°ã¤¦¤À¤±¤Ç¤¹¡£
DECLARE id NUMBER; text VARCHAR(30); u_cur INTEGER; u_sql VARCHAR2(1000); u_row INTEGER; BEGIN id := 3; 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 ; /
¼Â¹Ô·ë²Ì¤Ï¤³¤¦¤Ê¤ê¤Þ¤¹¡£Àµ¾ï¤Ë ID=3 ¤ÎÎó¤¬ UPDATE ¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤ï¤«¤ê¤Þ¤¹¡£
PL/SQL¥×¥í¥·¡¼¥¸¥ã¤¬Àµ¾ï¤Ë´°Î»¤·¤Þ¤·¤¿¡£ SQL> SELECT * FROM TEST01; ID TEXT ON_CREAT ---------- ------------------------------ -------- 1 AAAA 08-07-03 2 BBBB 08-07-03 3 DDDD 08-07-03
¤Ä¤Þ¤ê¡¢¥Ð¥¤¥ó¥ÉÊÑ¿ô¤ò»È¤Ã¤¿ MERGE ¹½Ê¸¤Ï¤³¤¦¤Ê¤ê¤Þ¤¹¡£
Ãí°ÕÅÀ¤Ï¡¢UPDATE ¶ç¤ÎÎó̾¤Ë¤Ï ON ¶ç¤Ç»ÈÍѤ·¤¿Îó̾¤Ï»ÈÍѤǤ¤Ê¤¤¤È¤¤¤¦ÅÀ¤Ç¤¹¡£¤³¤ì¤Ï°ÕÌ£¤ò¹Í¤¨¤ì¤Ð¤ï¤«¤ë¤È»×¤¤¤Þ¤¹¤¬¡¢¥Þ¥Ã¥Á¤·¤Æ¤¤¤ë¼«Ê¬¼«¿È¤Î¥¡¼¤òÊѹ¹¤Ç¤¤Ê¤¤¤Ã¤Æ¤ï¤±¤Ç¤¹¡£¥¡¼°Ê³°¤Ï¹¹¿·²Äǽ¤Ã¤Æ¤ï¤±¤Ç¤¹¡£
INSERT ¶ç¤Ï¤½¤Î¤è¤¦¤ÊÀ©¸Â¤Ï¤¢¤ê¤Þ¤»¤ó¡£¤À¤Ã¤Æ¤Þ¤ÀÉ½Ãæ¤Ë¸ºß¤·¤Æ¤¤¤Ê¤¤¤Î¤Ç¤¹¤«¤é¡£
¡¡¡¡USING¡¡DUAL
¡¡¡¡ON¡¡(Îó̾1 = ?,¡¡Îó̾2 = ?,¡¡Ž¥Ž¥Ž¥)
WHEN¡¡MATCHED¡¡THEN
¡¡¡¡UPDATE¡¡SET¡¡Îó̾n1 = ?,¡¡Îó̾n2 = ?,¡¡Ž¥Ž¥Ž¥
WHEN¡¡NOT¡¡MATCHED¡¡THEN
¡¡¡¡INSERT¡¡[( Îó̾1,¡¡Îó̾2,¡¡Ž¥Ž¥Ž¥ )]¡¡VALUES¡¡( ?,¡¡?,¡¡Ž¥Ž¥Ž¥ )
¤µ¤Æ¡¢Perl DBI ¤«¤é MERGE ¹½Ê¸¤òÍøÍѤ¹¤ë¤Ê¤é¤³¤¦¤Ê¤ê¤Þ¤¹¡£
my $sth = $dbh->prepare(qq{ MERGE INTO TEST01 USING DUAL ON ( ID=? ) WHEN MATCHED THEN UPDATE SET TEXT=? WHEN NOT MATCHED THEN INSERT ( ID, TEXT ) VALUES ( ?, ? ) }); my $id = 4; my $text = 'DDDD'; $sth->execute( $id, $text, $id, $text ); $id = 3; $text = 'DDDD'; $sth->execute( $id, $text, $id, $text );
Ʊ¤¸°ú¿ô¤òÅϤ¹¤Î¤¬¤Ê¤ó¤À¤«¡¦¡¦¡¦¤Ã¤Æ´¶¤¸¤ë¾ì¹ç¤Ë¤Ï¡¢¤µ¤é¤Ë MERGE ʸ¤ò¤³¤ó¤Ê´¶¤¸¤ËÊѹ¹¤¹¤ë¤ÈÎɤ¤¤«¤â¤·¤ì¤Þ¤»¤ó¡£
my $sth = $dbh->prepare(qq{ MERGE INTO TEST01 A USING (SELECT ? ID, ? TEXT FROM DUAL) B ON ( A.ID=B.ID ) WHEN MATCHED THEN UPDATE SET TEXT=B.TEXT WHEN NOT MATCHED THEN INSERT ( ID, TEXT ) VALUES ( B.ID, B.TEXT ) }); my $id = 4; my $text = 'DDDD'; $sth->execute( $id, $text ); $id = 3; $text = 'DDDD'; $sth->execute( $id, $text );
PL/SQL ¤Ç¤â½ñ¤¤¤Æ¤ª¤¯¤È¤³¤ó¤Ê´¶¤¸¤Ç¤¹¡£ºÇ½ªÅª¤Ë¤ÏËÍ¤Ï DBI ¤«¤é½ñ¤¯¤³¤È¤ò¹Í¤¨¤Æ°Ê²¼¤Î·Á¼°¤¬¼ý¤Þ¤ê¤¬¤è¤¯´¶¤¸¤Æ¤¤¤Þ¤¹¡£
DECLARE id NUMBER; text VARCHAR(30); u_cur INTEGER; u_sql VARCHAR2(1000); u_row INTEGER; BEGIN id := 3; text := 'DDDD'; u_cur := DBMS_SQL.OPEN_CURSOR; u_sql := 'MERGE INTO TEST01 A USING (SELECT :b1 ID, :b2 TEXT FROM DUAL) B ON ( A.ID=B.ID ) WHEN MATCHED THEN UPDATE SET TEXT=B.TEXT WHEN NOT MATCHED THEN INSERT ( ID, TEXT ) VALUES ( B.ID, B.TEXT )'; 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 ; /
´Ö°ã¤¤¤òºÇ¸å¤Ë½ñ¤³¤¦¤«¤È»×¤Ã¤¿¤ó¤Ç¤¹¤±¤É¡¢´Ö°ã¤¤¤Ï½ñ¤«¤Ê¤¯¤Æ¤âÎɤ¤¤È´¶¤¸¤Æ¤¤¿¤Î¤Ç¡¢¤³¤ì¤Ë¤Æ¤ª½ª¤¤¡£
¥³¥á¥ó¥È¤ä¥·¥§¥¢¤ò¤ª´ê¤¤¤·¤Þ¤¹¡ª
ht
´ðËܹ½Ê¸¤Ï
merge into TBL_NAME using TBL_NAME|SUBQUERY on ( CONDITION )
[ when matched then MERGE_UPDATE_CLAUSE ]
[ when not matched then MERGE_INERT_CLAUSE ]
[ ERROR_LOGGING_CLAUSE]¡¡¤Ç¤¹¡£
¥ª¥é¥¯¥ë¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤¹¤ë¤Î¤¬¤è¤¤¤«¤È»×¤¤¤Þ¤¹¡£
º£²ó¤Î¾ì¹ç¡¢Èæ³ÓÂоݤΥơ¼¥Ö¥ë¤¬Ì¤ÄêµÁ¤Î¤¿¤á¥À¥ß¡¼¥Æ¡¼¥Ö¥ë(dual)¤ò»ÈÍѤ·¤Æ¤¤¤ëÅÀ¤òÉÕ¤±²Ã¤¨¤ë¤È¸í²ò¤¬¤Ê¤¤¤«¤È»×¤¤¤Þ¤¹¡£
¤Ê¤Î¤Ç using dual on (ID=4)¡¡°Ê³°¤Ë
using ( select 4 ID from dual) DUMMY on (DUMMY.ID=TEST01.ID)¡¡ ¤È¤¤¤Ã¤¿½ñ¤Êý¤â¤¢¤ê¤Þ¤¹¡£merge¤·¤Æ¤¤¤ë¤³¤È¤òÁÛÁü¤·¤ä¤¹¤¯±þÍѤǤ¤ëÍøÅÀ¤¬¤¢¤ê¤Þ¤¹¡£