缺少GROUP BY表达式可以顺利执行的问题
上一篇 / 下一篇 2008-01-11 23:13:16 / 个人分类:Bug
Oracle9204上执行一个明显语法错误的SQL,却可以得到查询结果。
首先重现一下问题:
SQL> CREATE TABLE T1 AS SELECT * FROM DBA_OBJECTS;
表已创建。
SQL> CREATE TABLE T2 AS SELECT * FROM DBA_USERS;
表已创建。
SQL> SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE;ITPUB个人空间d-v]1|o
SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE
#s(Tr E*P(ec'Q*P0 *
"{9XW[T}l0第1行出现错误:ITPUB个人空间#Ieh7b3SF8Q6RW
ORA-00979:不是GROUP BY表达式
这个SQL由于GROUP BY语句中确少OWNER字段,因此执行报错。
但是把这个SQL内嵌到子查询中,居然可以得到结果:
SQL> SELECT USERNAME, OBJECT_TYPE, CN
n:G,Q*?Z/mO1jL0 2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
#Gt:dA
RC,Y%E,M6m0 3 WHERE USERNAME = OWNERITPUB个人空间kwclm.J2yY
4 AND USERNAME LIKE 'SYS%';
USERNAME OBJECT_TYPE CNITPUB个人空间E(A}O5h3A;Z`
------------------------------ ------------------ ----------
Rg$[#p1~x(stQ0SYS LOB 28
lf7v$n~sp0SYS TYPE 478
!Q NvQO0\4Y!}0SYS VIEW 2112
yT8`epd1B;D I-]0.ITPUB个人空间.z&T)p%~}*i.~!w
.ITPUB个人空间e;A,RK.o,@
.ITPUB个人空间3Ic S1u
r)hN L(NO
SYSTEM INDEX PARTITION 48
,cyRiAp#d0SYSTEM TABLE PARTITION 53
已选择42行。
检查SQL的执行计划,发现是MERGE JOIN:
SQL> SELECT USERNAME, OBJECT_TYPE, CN
\(iJ c[R8\-^0 2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
%B
s n:m{
j'g'Fk0 3 WHERE USERNAME = OWNER
$A,sX`]0 4 AND USERNAME LIKE 'SYS%';
执行计划
VM.\r^.O4Y5jR0----------------------------------------------------------ITPUB个人空间sR\iUJ k
0 SELECT STATEMENT ptimizer=CHOOSEITPUB个人空间Dq.P+iW]-@A
1 0 SORT (GROUP BY)ITPUB个人空间 L5YE$F5n
2 1 MERGE JOIN
b`Z^&k9L:LbT2H
m6^o0 3 2 SORT (JOIN)
*fc5l,|e&{^F:Z.p0 4 3 TABLE ACCESS (FULL) OF 'T2'ITPUB个人空间#v$G7u.U(r.D-{4U@a$W
5 2 SORT (JOIN)
OgGU~eM,L0 6 5 TABLE ACCESS (FULL) OF 'T1'
想想也有道理,Oracle先对OWNER字段进行排序,进行MERGE JOIN连接后,再对OBJECT_TYPE字段进行GROUP BY。
如果使用HASH_JOIN提示,Oracle也可以得到执行结果:
SQL> SET AUTOT TRACE EXPITPUB个人空间_#W.m)[@VO2[)U
SQL> SELECT /*+ USE_HASH(T2) */ USERNAME, OBJECT_TYPE, CN
!b)];I;Z Dj&he0 2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
*` Otk3P0 3 WHERE USERNAME = OWNER
(k$nB.zQT0 4 AND USERNAME LIKE 'SYS%';
执行计划ITPUB个人空间Zn Z/a#z{ Sq
----------------------------------------------------------ITPUB个人空间{Qeb,v
0 SELECT STATEMENT ptimizer=CHOOSE (Cost=54 Card=1467 Bytes=76284)ITPUB个人空间\:B,W(R
c%_
1 0 SORT (GROUP BY) (Cost=54 Card=1467 Bytes=76284)ITPUB个人空间%I0Hh{(q.t A6yzf
2 1 HASH JOIN (Cost=45 Card=1467 Bytes=76284)ITPUB个人空间7sa6@n8p'b
3 2 TABLE ACCESS (FULL) OF 'T2' (Cost=2 Card=2 Bytes=48)ITPUB个人空间:z)o8EL/l1A4^
4 2 TABLE ACCESS (FULL) OF 'T1' (Cost=42 Card=5867 Bytes=164276)
不过这个SQL也很有意思,只需要将上面的USERNAME改成OWNER,就会报错:
SQL> SELECT OWNER, OBJECT_TYPE, CNITPUB个人空间q-^9jmll]
2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
Hp(e$c)qteK#n(_0B0 3 WHERE USERNAME = OWNER
,Z"J5tk)qZ M0 4 AND USERNAME LIKE 'SYS%';
S;`c:_8z)R2MG_0WHERE USERNAME = OWNER
'\)h4LD"\Uh)oz0 *
"v9ZY4|X a0第3行出现错误:ITPUB个人空间&Jg
r%D2u)Bu'e
ORA-00979:不是GROUP BY表达式
这时即使加上HINT也不行:
SQL> SELECT /*+ USE_HASH(T2) */ OWNER, OBJECT_TYPE, CNITPUB个人空间'R]kK*v-W"J7X
2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE) T1, T2ITPUB个人空间.j:q#T KQb\V
3 WHERE USERNAME = OWNERITPUB个人空间)S4p1i,KV-aE
4 AND USERNAME LIKE 'SYS%';ITPUB个人空间Er'Y1D:e5X
WHERE USERNAME = OWNER
n2aYDH:V{Hn\0 *
}2R@8NG,`0第3行出现错误:ITPUB个人空间^^`}6Be
ORA-00979:不是GROUP BY表达式
这个问题在10R2中只能通过RULE方式再现,通过使用USE_MERGE和USE_HASH提示已经无法再现了:
SQL> CONN TEST/TEST@TESTZJ