SQL> desc dual
Name Null? Type
----------------------------------------- -------- ----------------------------
DUMMY VARCHAR2(1)
SQL> select 4*5 from dual;
4*5
----------
20
SQL>
Run Code Online (Sandbox Code Playgroud)
我觉得真的很奇怪。如果dual中没有名为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>
Run Code Online (Sandbox Code Playgroud)
Bri*_*ton 29
来自维基百科:
DUAL 表是一个特殊的单行表,默认情况下存在于所有 Oracle 数据库安装中。它适用于选择 SYSDATE 或 USER 等伪列。该表有一个名为 DUMMY 的 VARCHAR2(1) 列,其值为“X”。
因此,双表是一种对相当于空但不为空的表执行操作的方法。当人们不关心表,但需要通过 select 语句执行操作时,这很有用。如果表有多个行或列,将返回多个结果(由于在执行操作时对整个元组集进行操作。)
它不应在生产中使用,除非您特别需要通过 SQL 调用某些过程。
4*5是数学运算,就像'Foo' 字符串一样。因此,就像可以从任何表中选择 4*5 一样,就像可以从任何表中选择 'Foo' 一样,DUAL 是一种从永远不会有多个结果的已知良好表中选择它的方法。
从文档(概念):
DUAL 是数据字典中的一个小表,Oracle 数据库和用户编写的程序可以参考它以保证已知结果。当一个值必须只返回一次时,双表很有用,例如,当前日期和时间。所有数据库用户都可以访问 DUAL。
DUAL 表有一个名为 DUMMY 的列和一个包含值 X 的行。
和SQL 参考:
DUAL 是 Oracle 数据库与数据字典一起自动创建的表。DUAL 位于用户 SYS 的架构中,但所有用户都可以通过名称 DUAL 访问。它有一个列 DUMMY,定义为 VARCHAR2(1),并包含一个值为 X 的行。从 DUAL 表中进行选择对于使用 SELECT 语句计算常量表达式很有用。因为 DUAL 只有一行,所以常量只返回一次。或者,您可以从任何表中选择常量、伪列或表达式,但返回值的次数将与表中的行数相同。有关从 DUAL 中选择常量值的许多示例,请参阅“关于 SQL 函数”。
从 Oracle 数据库 10g 第 1 版开始,在计算不包含 DUMMY 列的表达式时,不会对 DUAL 表执行逻辑 I/O。此优化在执行计划中列为 FAST DUAL。如果您从 DUAL 中选择 DUMMY 列,则不会发生此优化并且会发生逻辑 I/O。
Hen*_*ann 18
DUAL 是一个只有一行的表,如以下 SQL 语句所示:
SELECT * FROM dual;
Run Code Online (Sandbox Code Playgroud)
您的dual2表没有行。如果您插入一个,您将看到相同的行为。
4*5 是一个表达式,Oracle 可以在不实际使用表中数据的情况下对其进行评估。它将为每一行计算一次,就像它对普通列表达式所做的一样。所以如果没有行,则不返回任何结果,如果有两行,您将得到 20 两次。
Ren*_*ger 13
该dual表的“工作”几乎与任何其他表的工作方式一样:它是一个您可以从中选择记录的表。
这意味着,例如,您可以描述表格。在这里,在SQL*Plus:
SQL> set lines 50
SQL> desc dual
Name Null? Typ
----------------------- -------- ----------------
DUMMY VARCHAR2(1)
Run Code Online (Sandbox Code Playgroud)
因此,该表只有一列,名为dummya varchar2(1)。
根据设计,该表有一个记录(至少如果没有人摆弄它的话):
SQL> select count(*) from dual;
COUNT(*)
----------
1
Run Code Online (Sandbox Code Playgroud)
因此,为了得到与相同的行为dual2,你有dual,你必须插入一条记录成双。更好的是,使用create table as select(ctas)创建它:
SQL> create table dual2 as select * from dual;
Run Code Online (Sandbox Code Playgroud)
现在,您的查询有效:
SQL> select 4*5 from dual2;
4*5
----------
20
Run Code Online (Sandbox Code Playgroud)
早些时候,我说过双几乎像任何其他表一样工作。那么,什么时候它不像任何其他表一样工作?
如果没有选择表本身的值,它的行为会有所不同。再次,对于您的疑问,我让 Oracle解释了它们......
SQL> set lines 150
SQL> explain plan for select 4*5 from dual2;
EXPLAIN PLAN ausgef³hrt.
Run Code Online (Sandbox Code Playgroud)
...为了查看表的访问方式:
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 |
-------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
可以看出,该语句做了一个full table accesson dual2。
现在,同样的事情dual:
SQL> explain plan for select 4*5 from dual;
EXPLAIN PLAN ausgef³hrt.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
这是dual表行为不同的地方:dummy不需要的值,因此fast dual执行操作,以使实例不读取磁盘上的实际值。
顺便说一下,DUAL 是少数几个在实例已启动但数据库尚未打开时工作的“表”之一。
你得到类似的东西
ADDR INDX INST_ID D
-------- ------ ------- -
0C0362D4 0 1 X
Run Code Online (Sandbox Code Playgroud)
小智 8
除了其他答案之外,Oracle 对 SQL 文本的空格并没有那么挑剔(至少在某些地方)。在某些情况下,SQL 解析器还通过字符类差异进行标记,而不仅仅是通过空格。
例如,您可以运行这样的语句:
SQL> select*from dual;
D
——
X
SQL> select(1)from dual;
(1)
----------
1
SQL> select-null from dual;
-空值
----------
SQL> select-1 from dual;
-1
----------
-1
查询>
也可以在没有任何空格的情况下运行 SQL:
SQL> select*from/**/dual; D —— X
我这里还有一些例子:
塔内尔·波德