CREATE TABLE t1(c1 VARCHAR2(10), c2 INT, c3 INT, c4 INT);
CREATE TABLE t2(c1 VARCHAR2(10), c2 INT, c3 INT, c4 INT);
INSERT INTO t1
SELECT DECODE (MOD (LEVEL, 2), 0, 'A', 'B') , LEVEL, LEVEL, LEVEL
FROM DUAL
CONNECT BY LEVEL <= 100000;
INSERT INTO t2
SELET DECODE (MOD (LEVEL, 2), 0, 'A', 'B') , LEVEL, LEVEL, LEVEL
FROM DUAL
CONNECT BY LEVEL <= 100000;
ANALYZE TABLE t1 COMPUTE STATISTICS ;
ANALYZE TABLE t2 COMPUTE STATISTICS ;
-- Merge 문을 사용
-- case 1
MERGE /*+ gather_plan_statistics */ INTO t2
USING ( SELECT *
FROM t1
WHERE c1 IN ('A', 'B')) x
ON ( x.c1 = t2.c1
AND x.c2 = t2.c2
AND x.c3 = t2.c3
AND t2.c1 = 'A' )
WHEN MATCHED THEN
UPDATE
SET t2.c4 = x.c4
WHEN NOT MATCHED THEN
INESRT (t2.c1, t2.c2, t2.c3, t2.c4)
VALUES (x.c1, x.c2, x.c3, x.c4) ;
SELECT *
FROM TABLE (DBMS_XPLAN.display_cursor(NULL, NULL, 'allstats last')) ;
-- case 2
MERGE /*+ gather_plan_statistics */ INTO t2
USING ( SELECT *
FROM t1
WHERE c1 IN ('A', 'B')) x
ON ( x.c1 = t2.c1
AND x.c2 = t2.c2
AND x.c3 = t2.c3
AND t2.c1 = 'A', 'B' )) // IN 조건을 사용
WHEN MATCHED THEN
UPDATE
SET t2.c4 = x.c4
WHEN NOT MATCHED THEN
INESRT (t2.c1, t2.c2, t2.c3, t2.c4)
VALUES (x.c1, x.c2, x.c3, x.c4) ;
SELECT /*+ CASE1 NO_MERGE 상태 */
lv.rid ,
lv.c1, lv.c2, lv.c3, lv.c4,
x.c1, x.c2, x.c3, x.c4
FROM (SELECT t1.c1, t1.c2, t1.c3, t1.c4 c4
FROM t1
WHERE t1.c1 = 'A' OR t1.c1 = 'B' ) x,
LATERL ( SELECT t2.c1, t2.c2, t2.c4, t2.ROWID as rid
FROM t2
WHERE x.c1 = t2.c1
AND x.2 = t2.c2
AND x.3 = t2.c3
AND x.c1 = 'A')(+) lv ;
SELECT /*+CASE1 MERGE 상태 */
t2.roWID rid,
t2.c1, t2.c2 c2, t2.c3 c3, t2 .c4 c4,
t1.c1, t1.c2 c2, t1.c3 c3, t1.c4 c4
FROM t1, t2
WHERE t1.c3 = t2.c3(+)
AND t1.c2 = t2.c2(+)
AND t1.c1 = t2.c1(+)
AND t2.c1(+) 'A'
AND(t1.c1= 'A' OR t1.c1= 'B');
SELECT /*+ CASE2 NO_MERGE 상태 */
lv.rid,
lv.c1, lv.c2, lv.c3, lv.c4,
x.c1, x.c2, x.c3, x.c4
FROM (SELECT t1.c1 c1, t1.c2 c2, t1.c3 c3, t1.c4 c4
FROM t1
WHERE t1.c1 = 'A' OR t1.c1 = 'B' ) x,
LATERAL(SELECT t2.c1, t2.c2, t2.c3, t2.c4, t2.ROWID AS rid
FROM t2
WHERE x.c1 = t2.c1
AND x.c2 = t2.c2
AND x.c3 = t2.c3
AND (t2.c1 = 'A' OR t2.c1 = 'B')) (+) lv ;
2) 인덱스를 만들 수 없는 경우라면, Between 을 사용하면 된다.
Between 은 Outer 조인이 가능하므로 view merging 이 정상적으로 발생된다.
MERGE /*+ gather_plan_statistics */ INTO t2
USING ( SELECT *
FROM t1
WHERE c1 IN('A','B')) x
ON ( x.c1 = t2.c1
AND x.c2 = t2.c2
AND x.c3 = t2.c3
AND t2.c1 BETWEEN 'A' AND 'B')
WHEN MATCHED THEN
UPDATE
SET t2.c4 = x.c4
WHEN NOT MATCHED THEN
INSERT (t2.c1, t2.c2, t2.c3, t2.c4)
VALUES (x.c1, x.c2, x.c3, x.c4) ;
MERGE /*+ gather_plan_statistics */ INTO t2
USING ( SELECT *
FROM t1
WHERE c1 IN ('A','B')) x
ON ( x.c1 = t2.c1
AND x.c2 = t2.c2
AND x.c3 = t2.c3
AND t2.c1 = DECODE(t2.c1,'A','A','B'))
WHEN MATCHED THEN
UPDATE
SET t2.c4 = x.c4
WHEN NOT MATCHED THEN
INSERT (t2.c1, t2.c2, t2.c3, t2.c4)
VALUES (x.c1, x.c2, x.c3, x.c4) ;