li
  当前位置:主页 > 性能优化 > 文章内容
li
缺少GROUP BY表达式可以顺利执行的问题
来源: http://yangtingkun.itpub.net/  作者: yangtingkun    时间:2008-01-26   阅读:2  
本文章共2668字,分2页,当前第1页,快速翻页:
 

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;
SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE
*
1 行出现错误:
ORA-00979:
不是 GROUP BY 表达式

这个SQL由于GROUP BY语句中确少OWNER字段,因此执行报错。

但是把这个SQL内嵌到子查询中,居然可以得到结果:

SQL> SELECT USERNAME, OBJECT_TYPE, CN
2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
3 WHERE USERNAME = OWNER
4 AND USERNAME LIKE 'SYS%';

USERNAME OBJECT_TYPE CN
------------------------------ ------------------ ----------
SYS LOB 28
SYS TYPE 478
SYS VIEW 2112
.
.
.
SYSTEM INDEX PARTITION 48
SYSTEM TABLE PARTITION 53

已选择42行。

检查SQL的执行计划,发现是MERGE JOIN

SQL> SELECT USERNAME, OBJECT_TYPE, CN
2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
3 WHERE USERNAME = OWNER
4 AND USERNAME LIKE 'SYS%';

执行计划
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (GROUP BY)
2 1 MERGE JOIN
3 2 SORT (JOIN)
4 3 TABLE ACCESS (FULL) OF 'T2'
5 2 SORT (JOIN)
6 5 TABLE ACCESS (FULL) OF 'T1'

想想也有道理,Oracle先对OWNER字段进行排序,进行MERGE JOIN连接后,再对OBJECT_TYPE字段进行GROUP BY

如果使用HASH_JOIN提示,Oracle也可以得到执行结果:

SQL> SET AUTOT TRACE EXP
SQL> SELECT /* USE_HASH(T2) */ USERNAME, OBJECT_TYPE, CN
2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
3 WHERE USERNAME = OWNER
4 AND USERNAME LIKE 'SYS%';

执行计划
IXDBA.NET社区论坛
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=54 Card=1467 Bytes=76284)
1 0 SORT (GROUP BY) (Cost=54 Card=1467 Bytes=76284)
2 1 HASH JOIN (Cost=45 Card=1467 Bytes=76284)
3 2 TABLE ACCESS (FULL) OF 'T2' (Cost=2 Card=2 Bytes=48)
4 2 TABLE ACCESS (FULL) OF 'T1' (Cost=42 Card=5867 Bytes=164276)

不过这个SQL也很有意思,只需要将上面的USERNAME改成OWNER,就会报错:

SQL> SELECT OWNER, OBJECT_TYPE, CN
2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE), T2
3 WHERE USERNAME = OWNER
4 AND USERNAME LIKE 'SYS%';
WHERE USERNAME = OWNER
*
3 行出现错误:
ORA-00979:
不是 GROUP BY 表达式

这时即使加上HINT也不行:

SQL> SELECT /* USE_HASH(T2) */ OWNER, OBJECT_TYPE, CN
2 FROM (SELECT OWNER, OBJECT_TYPE, COUNT(*) CN FROM T1 GROUP BY OBJECT_TYPE) T1, T2
3 WHERE USERNAME = OWNER
4 AND USERNAME LIKE 'SYS%';
WHERE USERNAME = OWNER
*
3 行出现错误:
ORA-00979:
不是 GROUP BY 表达式

这个问题在10R2中只能通过RULE方式再现,通过使用USE_MERGEUSE_HASH提示已经无法再现了:

SQL> CONN TEST/TEST@TESTZJ已连接。
SQL> SELECT * FROM V$VERSION;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production

SQL> CREATE TABLE T1 AS SELECT * FROM DBA_OBJECTS;



阅读更多内容1 · 2 · 下一页>>


  上一篇: ORA-21561错误   下一篇: Oracle11g物理STANDBY应用日志时...
li
 §相关评论  
 热点文章

·Resize datafile导致ASM Crash
·在Oracle10g RAC下新增ASM磁盘
·ORACLE SQL性能优化系列 (一)
·oracle性能调优:管理oracle日志
·oracle RAC环境中系统时钟的调
·why:Rac的心跳线不支持交叉线?
·RAC的VIP及实例依赖关系:版本O
·如何启动DataGuard的备用数据库
·系统表空间IO错误 数据损坏处理
·不幸中的万幸:遭遇ORA-00600 [
·用ORACLE的高级复制实现内外网
li
 编辑推荐
·Resize datafile导致ASM Crash
·在Oracle10g RAC下新增ASM磁盘
·ORACLE SQL性能优化系列 (一)
·oracle性能调优:管理oracle日志
·oracle RAC环境中系统时钟的调
·why:Rac的心跳线不支持交叉线?
·RAC的VIP及实例依赖关系:版本O
·如何启动DataGuard的备用数据库
·系统表空间IO错误 数据损坏处理
·不幸中的万幸:遭遇ORA-00600 [
·用ORACLE的高级复制实现内外网
li
 相关篇章
·ORA-21561错误
·临时表产生REDO过多的bug
·缺少GROUP BY表达式可以顺利执行...
·使用SQL判断一个数是否质数
·9i上使用CONNECT BY访问DUAL表的...
·数据库升级造成的X_$BH状态异常问...
·表异常增大的bug
·Oracle10201在Enterprise Linux ...
·ORA-600(ktsircinfo_num1)错误
·函数索引产生隐藏列
·Oracle11g物理STANDBY应用日志时...
·用SQL计算100以内的质数
·用SQL实现99乘法表
·使用nlsparam的一个例子
·用SQL解决两道有趣的题(二)
·用SQL解决两道有趣的题(一)
·RAC环境的STANDBY数据库备份报错
·2007年总结
·Oracle11g物理STANDBY打开模式应...
·Oracle11新特性——备份恢复功能...
 
li
设为首页 | 关于我们 | 技术服务 | 收藏本站 | 网站地图 | 联系方式 | 本站友情连接