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。
#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),此列的最大宽度可以是一个字符。
如果要获取更多详细信息,请在此处检查
评论
“除非您特别需要通过SQL调用某些过程,否则不应在生产中使用它”为什么不呢?
–尼克·皮尔波因特(Nick Pierpoint)
11年8月22日在16:20
我也不同意不应在生产中使用它。对我来说,这听起来像是“砍断烤架”模因。
– ErikE
17年4月1日在18:36
该答案与自己不同,因此需要改进。它在一个地方从官方文档中复制:“双重表很有用”,在另一个地方则建议“除非在生产中使用,否则不应在生产中使用它”。
–超立方体ᵀᴹ
17年4月2日在8:18