Erp100论坛's Archiver

xiangzhao 发表于 2008-8-12 11:43

神秘的DUAL

关键字 ORACLE DUAL  


DUAL ? 有什么神秘的? 当你想得到ORACLE系统时间, 简简单单敲一行SQL  

不就得了吗? 故弄玄虚….  

SQL>; select sysdate from dual;  

SYSDATE  

---------  

28-SEP-03  



哈哈, 确实DUAL的使用很方便. 但是大家知道DUAL倒底是什么OBJECT, 它有什么特殊的行为吗? 来,我们一起看一看.  



首先搞清楚DUAL是什么OBJECT :  

SQL>; connect system/manager  

Connected.  

SQL>; select owner, object_name , object_type from dba_objects where object_name like '%DUAL%';  



OWNER OBJECT_NAME OBJECT_TYPE  

--------------- --------------- -------------  

SYS DUAL TABLE  

PUBLIC DUAL SYNONYM  



原来DUAL是属于SYS schema的一个表,然后以PUBLIC SYNONYM的方式供其他数据库USER使用.  

再看看它的结构:  

SQL>; desc dual  

Name Null? Type  

----------------------------------------- -------- ----------------------------  

DUMMY VARCHAR2(1)  



SQL>;  



只有一个名字叫DUMMY的字符型COLUMN .  



然后查询一下表里的数据:  

SQL>; select dummy from dual;  

DUMMY  

----------  

X  



哦, 只有一条记录, DUMMY的值是’X’ .很正常啊,没什么奇怪嘛. 好,下面就有奇妙的东西出现了!  

插入一条记录:  

SQL>; connect sys as sysdba  

Connected.  

SQL>; insert into dual values ( 'Y');  

1 row created.  

SQL>; commit;  

Commit complete.  

SQL>; select count(*) from dual;  

COUNT(*)  

----------  

2  

迄今为止,一切正常. 然而当我们再次查询记录时,奇怪的事情发生了  

SQL>; select * from dual;  

DUMMY  

----------  

X  

刚才插入的那条记录并没有显示出来 ! 明明DUAL表中有两条记录, 可就是只显示一条!  

再试一下删除 ,狠一点,全删光 !  

SQL>; delete from dual; /*注意没有限定条件,试图删除全部记录*/  

1 row deleted.  

SQL>; commit;  

Commit complete.  



哈哈,也只有一条记录被删掉,  

SQL>; select * from dual;  

DUMMY  

----------  

Y  



为什么会这样呢? 难道SQL的语法对DUAL不起作用吗?带着这个疑问, 我查询了一些ORACLE官方的资料. 原来ORACLE对DUAL表的操作做了一些内部处理,尽量保证DUAL表中只返回一条记录.当然这写内部操作是不可见的 .  

看来ORACLE真是蕴藏着无穷的奥妙啊!  



附: ORACLE关于DUAL表不同寻常特性的解释  

There is internalized code that makes this happen. Code checks that ensure  

that a table scan of SYS.DUAL only returns one row. Svrmgrl behaviour is  

incorrect but this is now an obsolete product.  

The base issue you should always remember and keep is: DUAL table should always  

have 1 ROW. Dual is a normal table with one dummy column of varchar2(1).  

This is basically used from several applications as a pseudo table for  

getting results from a select statement that use functions like sysdate or other  

prebuilt or application functions. If DUAL has no rows at all some applications  

(that use DUAL) may fail with NO_DATA_FOUND exception. If DUAL has more than 1  

row then applications (that use DUAL) may fail with TOO_MANY_ROWS exception.  

So DUAL should ALWAYS have 1 and only 1 row

页: [1]

Powered by Discuz! Archiver 7.0.0  © 2001-2007 Comsenz Inc.