Oracle DUAL 表如何工作?

Laz*_*zer 33 oracle

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。

  • “它不应该在生产中使用,除非您特别需要通过 SQL 调用某些过程”为什么不呢? (5认同)
  • 我也不能同意它不应该用于生产。对我来说,这听起来像是“切掉烤肉的末端”模因。 (2认同)

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执行操作,以使实例不读取磁盘上的实际值。


Gar*_*ary 9

顺便说一下,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

我这里还有一些例子:

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

塔内尔·波德

  • 这种省略许多空格的能力并不是 Oracle 所独有的。在 SQL Server 中的工作方式相同。 (2认同)

小智 7

一个快速的双重操作重写你的代码来查询 x$dual。因为这个“表”是SGA中的C数据结构,所以可以在nomount模式下查询。