起源
使用oracle的时候,我们经常会运行下面的sql得到当前系统时间:
sql
SQL> select sysdate from dual; SYSDATE --------- 10-DEC-14
我想看看dual是什么,运行一下desc
sql
SQL> desc dual; Name Null? Type ----------------------------------------- -------- ---------------------------- DUMMY VARCHAR2(1)
dual是一个表,有一个名为DUMMY,类型为VARCHAR2(1)。DUMMY这个词在英文中的含义为“something designed to resemble and serve as a substitute for the real or usual thing; a counterfeit or sham.”,大概意思就是虚拟的,用来替代一些真实存在东西的概念。
再看一下数据库中还有没其他叫DUAL的对象:
sql
SQL> select object_name, object_type, owner from dba_objects where object_name = 'DUAL'; OBJECT_NAM OBJECT_TYPE OWNER ---------- ----------------------- ---------- DUAL TABLE SYS DUAL SYNONYM PUBLIC
还有一个叫DUAL的public synonym,所以任意的用户都可以访问到DUAL了。
神奇的是,DUAL这货在实例是nomount的状态下也可以访问:
sql
[oracle@bogon ~]$ sqlplus / as sysdba SQL*Plus: Release 12.1.0.2.0 Production on Wed Dec 10 08:00:15 2014 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to an idle instance. SQL> startup nomount; ORACLE instance started. Total System Global Area 1644167168 bytes Fixed Size 2925024 bytes Variable Size 973082144 bytes Database Buffers 654311424 bytes Redo Buffers 13848576 bytes SQL> select * from dual; ADDR INDX INST_ID CON_ID D ---------------- ---------- ---------- ---------- - 000000000E07DD5C 0 1 0 X SQL> select sysdate from dual; SYSDATE --------- 10-DEC-14
在nmount装下也可以select sysdate
此时,来看一下DUAL的结构:
sql
SQL> select * from x$dual; ADDR INDX INST_ID CON_ID D ---------------- ---------- ---------- ---------- - 000000000E07DD5C 0 1 0 X
在nomount状态时,DUAL实际上就是X$DUAL。
X$这类对象,在Oracle中属于直接定义在内存结构中的,在数据库实例启动的时候,都已经创建出来。
继续搜寻
现在知道这个表在什么地方了,还有一个疑问:这个DUAL到底是用来干嘛的呢?难道就是方便我们查询一下sysdate或者什么操作?
于是以“X$DUAL oracle”为关键词google了一下,找到Tom的一篇文章
1.What is the dual table, what is its purpose.
dual is just a convienence table. You don't need to use it, you can use anything you
want. The advantage to dual is the optimizer understands dual is a special one row, one
column table -- when you use it in queries, it uses this knowledge when developing the
plan.
2.Why does it contain only one column with datatype varchar2, why not
number .
truly, why no. Why not a date you would ask then. The column, its name, its datatype
and even its value are NOT relevant. DUAL exists solely as a means to have a 1 row table
we can reliably select from. Thats all.
3.Does it contain one row by default.
yes, when we build the database, we build dual and put a single row in it.
4.why do we
usually SELECT USER FROM DUAL,
why cant I do it like
SQL> select USER FROM EMP WHERE ROWNUM<2;
truly, why can't you? is something preventing you from doing so?? You can if you want.
Me, I'll stick with "select user from dual". I know dual exists. I know it has at least
1 and at most 1 row. I know the optimizer knows all about dual and does the most
efficient thing for me.
5) yes
6) the optimizer understands dual is a magic, special 1 row table. It stopped on the
select * because there is to be one row in there. Its just the way it works. Hopefully
you reset dual back to 1 row after your testing or you just totally broke your database!
7) like I said, duals magic, the optimizer knows all about what DUAL should be and does
things based on that.
8) dual = magic. dual is a one row table however having more then 1 or less then one is
dangerous. You are updating the data dictionary. You should naturally expect very bad
things to happen.
简单总结,意思如下:
- DUAL is a convienence table
- The column, its name, its datatype and even its value are NOT relevant. DUAL exists solely as a means to have a 1 row table we can reliably select from. Thats all
- the optimizer understands dual is a magic
- dual = magic
从Tom的语气中可以看出来 ,他对于这么多为什么也表示很无奈,在他看来DUAL这个表是为方便使用而设计出来的,其中并没有太多为什么可以回答。
这种情况很像我们面对用户一些没法回答的问题,我们也说不上来到底是为啥时,我们回答:啊,这个只能这样,就是这样设计的,你这样操作就好了。