SQL> desc dual
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual;

       4*5
----------
        20

SQL>


我觉得很奇怪。如果对偶中没有名为4 * 5的列,那么select语句如何工作?

此外,为什么在创建自己的对偶表时看不到相同的行为?

SQL> create table dual2(dummy varchar2(1)); 

Table created.

SQL> desc dual2
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual2;

no rows selected

SQL> 


#1 楼

摘自Wikipedia:DUAL表是一种特殊的单行表,默认情况下在所有Oracle数据库安装中都存在。它适用于选择伪列,例如SYSDATE或USER。该表有一个称为DUMMY的VARCHAR2(1)列,其值是'X'。

因此,双表是一种针对等于空但不为null的值执行操作的方法表。当人们不关心表但需要通过select语句执行操作时,这很有用。如果表中有多行或多列,则将返回多个结果(由于在执行操作时对整个元组进行了操作。)
除非您特别需要,否则不应在生产中使用它。通过SQL调用某些过程。
4*5是数学运算,就像'Foo'是字符串一样。因此,就像一个人可以从任何表中选择4 * 5一样,就像一个人可以从任何表中选择“ Foo”一样,DUAL是一种从已知良好的表中选择它的方法,该表永远不会有多个结果。
从文档(CONCEPTS):

DUAL是数据字典中的一个小表,Oracle数据库和用户编写的程序可以引用该小表来保证已知结果。当必须仅返回一次值(例如,当前日期和时间)时,双重表很有用。所有数据库用户都可以访问DUAL。
DUAL表具有称为DUMMY的一列和包含值X的一行。

以及SQL参考:

DUAL是由Oracle数据库自动创建的表以及数据字典。 DUAL在用户SYS的架构中,但所有用户均可通过名称DUAL访问。它具有一列DUMMY,定义为VARCHAR2(1),并且包含一行带有值X的行。从DUAL表中进行选择对于使用SELECT语句计算常量表达式很有用。由于DUAL只有一行,因此该常数仅返回一次。或者,您可以从任何表中选择一个常量,伪列或表达式,但是该值将返回与该表中的行一样多的次数。有关从DUAL中选择常量值的许多示例,请参见“关于SQL函数”。
从Oracle Database 10g第1版开始,在计算不包含DUAL表的表达式时,不会对DUAL表执行逻辑I / O。 DUMMY栏。该优化在执行计划中列为“快速双重”。如果从DUAL中选择DUMMY列,则不会进行此优化,并且会发生逻辑I / O。


评论


“除非您特别需要通过SQL调用某些过程,否则不应在生产中使用它”为什么不呢?

–尼克·皮尔波因特(Nick Pierpoint)
11年8月22日在16:20

我也不同意不应在生产中使用它。对我来说,这听起来像是“砍断烤架”模因。

– ErikE
17年4月1日在18:36

该答案与自己不同,因此需要改进。它在一个地方从官方文档中复制:“双重表很有用”,在另一个地方则建议“除非在生产中使用,否则不应在生产中使用它”。

–超立方体ᵀᴹ
17年4月2日在8:18



#2 楼

DUAL是具有一行的表,如以下SQL语句所示:如果插入一个,您将看到相同的行为。

4 * 5是Oracle可以评估的表达式,而无需实际使用表中的数据。它将对每行评估一次,就像对普通列表达式进行评估一样。因此,如果没有行,则不会返回任何结果,如果有两行,您将获得20次两次。

#3 楼

dual表几乎可以像其他任何表一样工作:它是一个表,您可以从中选择记录。

例如,这意味着您可以描述表格。在这里,在SQL*Plus中:

SQL> set lines 50
SQL> desc dual
Name                    Null?    Typ
----------------------- -------- ----------------
DUMMY                            VARCHAR2(1)


因此,该表具有一个名为dummy的列,即varchar2(1)。设计,一条记录(至少在没有人摆弄的情况下):

SQL> select count(*) from dual;

COUNT(*)
----------
         1


因此,为了获得与dual2相同的行为,必须具有将一条记录插入对偶。更好的是,使用dual(ctas)创建它:

SQL> create table dual2 as select * from dual;


现在,您的查询有效: />早些时候,我说过对偶几乎可以像其他桌子一样工作。因此,什么时候它不能像其他任何表一样工作?

,如果未从表本身中选择任何值,它的行为就会有所不同。同样,通过您的查询,我让Oracle解释它们...

SQL> select 4*5 from dual2;
       4*5
----------
        20


...,以便查看如何访问该表:

SQL> set lines 150
SQL> explain plan for select 4*5 from dual2;

EXPLAIN PLAN ausgef³hrt.


可以看到该语句在create table as select上执行了full table access

现在,与dual2相同:

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 3445655939

-------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     1 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| DUAL2 |     1 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------


这是dual表的行为不同的地方:不需要dual的值,因此将执行dummy操作,以使实例不读取磁盘上的实际值。

#4 楼

顺便说一句,当实例启动但尚未打开数据库时,DUAL是少数可用的“表”之一。

您会得到类似

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X


#5 楼

除了其他答案外,Oracle对于空格SQL文本(至少在某些地方)不是很挑剔。在某些情况下,SQL解析器还会通过字符类差异来标记化,而不仅仅是空白。

例如,您可以运行以下语句:

SQL> select*from dual;

D
-
X


SQL> select(1)from dual;

       (1)
----------
         1

SQL> select-null from dual;

     -NULL
----------


SQL> select-1 from dual;

        -1
----------
        -1

SQL> 



也可以在其中没有任何空格的情况下运行SQL:

SQL> select*from/**/dual;

D
-
X



我在这里还有更多示例:

http:// blog.tanelpoder.com/2008/01/14/can-you-write-a-working-sql-statement-without-using-any-whitespace/

Tanel Poder

评论


忽略许多空间的能力不是Oracle独有的。在SQL Server中的工作原理相同。

– ErikE
17年4月1日在18:33

#6 楼

快速的双重操作会重新编写您的代码以查询x $ dual。由于此“表”是SGA中的C数据结构,因此可以在nomount模式下对其进行查询。

#7 楼

问题已经回答。这些是对偶表目的的一些说明。
对偶可用于对select子句中的表达式求值。
许多其他数据库系统不需要此表。
MS SQL Server,MySql和Posgres可以评估以下语句

select 3+5 ;


Oracle不能。 Oracle select语句始终需要一个“从”子句。

某些函数不能在DUMP之类的pl / sql表达式中使用。

所以

declare
str varchar2(100);
begin
str:=dump('Hallo');
end;
/


将引发异常,但

declare
str varchar2(100);
begin
select dump('Hallo') into str from dual;
end;
/


将起作用。

它可以用于扩展查询的结果集

select user_id,username from user_users
union all
select -1,'NO USER'
from dual
/

给出了

| USER_ID |     USERNAME |
|---------|--------------|
|  476267 | USER_4_E8C50 |
|      -1 |      NO USER |


或使用CONNECT BY生成带有选择查询的数据:

select level as n 
from dual
connect by level <= 5 ;


或递归CTE:

with nlist(n) as (
  select 1 from dual
  union all
  select n+1
  from nlist 
  where n<5    )
select n
from nlist
 ;


,它返回

| N |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |


在sqlfiddle中

#8 楼

就其价值而言,它在MySQL中的工作方式完全相同。

mysql> use test;
Database changed

mysql> create table fred(billy int);
Query OK, 0 rows affected (0.79 sec)

mysql> select 4 + 5 from fred;
Empty set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
Empty set (0.00 sec)

mysql> insert into fred values(1);
Query OK, 1 row affected (0.13 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
+------+
1 row in set (0.00 sec)

mysql> insert into fred values(2);
Query OK, 1 row affected (0.08 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
|     9 |
+-------+
2 rows in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
|    9 |
+------+
2 rows in set (0.00 sec)

mysql> explain select 4 + 5 as mary from fred;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | fred  | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

mysql> 


而且似乎DUAL在MySQL中也存在某种内存结构
也。注意两个解释计划的区别-MySQL中“ DUAL”不使用表。

但是有趣的是,我无法在MySQL的双重数据库上执行DESC,这与Oracle不同-但它是专门为AIUI引入的,以允许Oracle语法在MySQL上运行。

mysql> select 4 + 5 from dual;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> explain select 4 + 5 from dual;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)

mysql> desc dual;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'dual' at line 1
mysql> 


#9 楼

在oracle数据库中,Dual表基本上用于获取伪列的值。它包含以下属性:


它是sys用户所有的
它可供所有用户使用
它只包含一个名称为虚拟且数据类型为实的列Varchar2(1),此列的最大宽度可以是一个字符。

如果要获取更多详细信息,请在此处检查