Merge加Hint(Append)时出现的问题

本文描述了在Oracle数据库中使用Merge语句结合Hint(Append)时遇到的问题,包括计数不准确及唯一约束失效等现象,并提供了具体的实验步骤与解决办法。

Merge加Hint(Append)时出现的问题
2008-11-04 11:39

之前count(*)的问题困扰了team很久,甚至准备到Metalink上开TAR了。没想到昨天这个问题被深受其害的开发组的小MM给重现了,至此这个很妖的问题以及由此引起的另一个在逃的问题被缉拿归案了:
问题就出在在Mergez上用hint, --- Merge /*+ APPEND */ ,由它引起的问题如下:
1. 查询被Merge的target表如果建pk索引时,count(*)始终为0(见上一篇文章)
2. target表上的pk约束和unique index失效,但通过dba_constraints,dba_indexes看状态,没有问题;

--- 实验过程如下:
Connected.
kl@k01> DROP TABLE KL_TEST PURGE;

Table dropped.

(创建目标table)
kl@k01> create table KL_TEST
2 (
3 a NUMBER(15) not null,
4 b NUMBER(15) not null,
5 c NUMBER(15) not null,
6 d NUMBER(15) not null,
7 e NUMBER(15) not null,
8 f NUMBER(15) not null
9 )
10 ;

Table created.

(创建PK,这是必须场景)
kl@k01>
kl@k01> alter table KL_TEST
2 add constraint KL_TEST_PK primary key (A, B, C, D)
3 ;

Table altered.

kl@k01>
kl@k01> DROP TABLE KL_TEST_1 PURGE;

Table dropped.
(创建source表,里面的数据将被Merge进target表KL_TEST)
kl@k01> CREATE TABLE KL_TEST_1 NOLOGGING PCTFREE 0 AS
2 SELECT * FROM KL_TEST
3 WHERE 1=2;

Table created.

kl@k01>
kl@k01> INSERT INTO KL_TEST_1 VALUES (1,1,1,1,1,1);

1 row created.

kl@k01> INSERT INTO KL_TEST_1 VALUES (1,2,1,2,1,2);

1 row created.

kl@k01> INSERT INTO KL_TEST_1 VALUES (1,1,1,1,1,1); --- 故意在source table中加入了一条重复纪录

1 row created.

kl@k01>
kl@k01> commit;

Commit complete.

kl@k01>
kl@k01>

(开始merge,hint是关键)
kl@k01> MERGE /*+ APPEND */ INTO KL_TEST trgt
2 USING
3 (select fct.a,fct.b,fct.c,fct.d,fct.e,fct.f from KL_TEST_1 fct) tmp
4 ON
5 (tmp.a = trgt.a
6 and tmp.b = trgt.b
7 and tmp.c = trgt.c
8 and tmp.d = trgt.d
9 and tmp.e = trgt.e
10 and tmp.f = trgt.f)
11 WHEN NOT MATCHED THEN
12 INSERT (a,b,c,d,e,f)
13 VALUES (tmp.a,tmp.b,tmp.c,tmp.d,tmp.e,tmp.f);

3 rows merged.

kl@k01>
kl@k01> commit;

Commit complete.

kl@k01>
(察看COUNT(*), 没纪录!!!)
kl@k01> SELECT COUNT(*) FROM KL_TEST;

COUNT(*)
----------
0
(强制FULL,有3条! 问题1出现了)
kl@k01> SELECT /*+ FULL (KL_TEST)*/ COUNT(*) FROM KL_TEST;

COUNT(*)
----------
3
(察看纪录,有一条重复纪录,PK&UNIQUE INDEX呢?问题2出现了)
kl@k01> select * from kl_test;

A B C D E F
---------- ---------- ---------- ---------- ---------- ----------
1 1 1 1 1 1

1 1 1 1 1 1
1 2 1 2 1 2

(PK是好的!)
kl@k01> select CONSTRAINT_NAME,CONSTRAINT_TYPE, STATUS from dba_constraints where table_name ='KL_TEST';

CONSTRAINT_NAME CON STATUS
------------------------------------------------------------------------------------------ --- -----------------
SYS_C00141098 C ENABLED
SYS_C00141093 C ENABLED
SYS_C00141094 C ENABLED
SYS_C00141095 C ENABLED
SYS_C00141096 C ENABLED
SYS_C00141097 C ENABLED
KL_TEST_PK P ENABLED

7 rows selected.

(居然还能insert进去,妖吧!)
kl@k01> insert into kl_test values (1,1,1,1,1,1);

1 row created.

kl@k01> commit;

Commit complete.

kl@k01> select * from kl_test;

A B C D E F
---------- ---------- ---------- ---------- ---------- ----------
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 2 1 2 1 2

---- 看了上面这些,看来Oracle新的功能bug还是不少,还是老老实实的按常规方法吧,去掉Hint -append,再看看:
kl@k01> MERGE INTO KL_TEST trgt
2 USING
3 (select fct.a,fct.b,fct.c,fct.d,fct.e,fct.f from KL_TEST_1 fct) tmp
4 ON
5 (tmp.a = trgt.a
6 and tmp.b = trgt.b
7 and tmp.c = trgt.c
8 and tmp.d = trgt.d
9 and tmp.e = trgt.e
10 and tmp.f = trgt.f)
11 WHEN NOT MATCHED THEN
12 INSERT (a,b,c,d,e,f)
13 VALUES (tmp.a,tmp.b,tmp.c,tmp.d,tmp.e,tmp.f);
MERGE INTO KL_TEST trgt
*
ERROR at line 1:
ORA-00001: unique constraint (KL.KL_TEST_PK) violated --(开始检查PK约束了)

--- Count(*)问题也正常了。

所以宗上,Merge加hint时要慎重,如果一定要用hint建议还是在存储过程中的insert/update/select中加。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值