AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 435
Accepted
Lazer
Lazer
Asked: 2011-01-10 01:34:53 +0800 CST2011-01-10 01:34:53 +0800 CST 2011-01-10 01:34:53 +0800 CST

Oracle DUAL 表是如何工作的?

  • 772
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> 
oracle
  • 9 9 个回答
  • 61024 Views

9 个回答

  • Voted
  1. Best Answer
    Brian Ballsun-Stanton
    2011-01-10T01:53:23+08:002011-01-10T01:53:23+08:00

    来自维基百科:

    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。

    • 29
  2. Hendrik Brummermann
    2011-01-10T03:11:56+08:002011-01-10T03:11:56+08:00

    DUAL是一个只有一行的表,如以下 SQL 语句所示:

    SELECT * FROM dual;
    

    您的dual2表没有行。如果插入一个,您将看到相同的行为。

    4*5 是一个表达式,Oracle 可以在不实际使用表中的数据的情况下进行计算。它将为每一行评估一次,就像它对普通列表达式所做的那样。因此,如果没有行,则不返回任何结果,如果有两行,您将获得 20 两次。

    • 18
  3. René Nyffenegger
    2011-01-22T01:24:31+08:002011-01-22T01:24:31+08:00

    该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必须将一条记录插入到对偶中。create table as select更好的是,使用(ctas)创建它:

    SQL> create table dual2 as select * from dual;
    

    现在,您的查询有效:

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

    早些时候,我说过 dual几乎可以像任何其他表一样工作。那么,它什么时候不能像其他任何表一样工作?

    如果没有选择表本身的值,它的行为会有所不同。同样,对于您的查询,我让 Oracle解释它们......

    SQL> set lines 150
    SQL> explain plan for select 4*5 from dual2;
    
    EXPLAIN PLAN ausgef³hrt.
    

    ...为了查看表的访问方式:

    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 |
    -------------------------------------------------------------------
    

    可以看出该语句做了一个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 |
    -----------------------------------------------------------------
    

    这是dual表表现不同的地方:dummy不需要 的值,因此fast dual执行了一个操作,以便实例不读取磁盘上的实际值。

    • 13
  4. Gary
    2011-01-11T20:58:01+08:002011-01-11T20:58:01+08:00

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

    你得到类似的东西

    ADDR     INDX   INST_ID D
    -------- ------ ------- -
    0C0362D4      0       1 X
    
    • 9
  5. Tanel Poder
    2011-01-11T14:03:51+08:002011-01-11T14:03:51+08:00

    除了其他答案之外,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:

    SQL> select*from/**/dual;
    
    D
    -
    X
    
    

    我这里还有一些例子:

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

    塔内尔·波德

    • 8
  6. I know more than you
    2011-07-17T02:52:57+08:002011-07-17T02:52:57+08:00

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

    • 7
  7. miracle173
    2014-07-06T00:01:55+08:002014-07-06T00:01:55+08:00

    问题已经回答了。这些是对双表目的的一些说明。Dual 可用于计算 select 子句中的表达式。许多其他数据库系统不需要这样的表来达到这个目的。MS SQL Server、MySql、Posgres 可以评估以下语句

    select 3+5 ;
    

    甲骨文不能。Oracle select 语句总是需要一个“from”子句。

    某些函数不能在 pl/sql 表达式中使用,例如DUMP。

    所以

    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

    • 4
  8. Vérace
    2014-07-05T14:01:57+08:002014-07-05T14:01:57+08:00

    对于它的价值,它在 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 的 dual 上做 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> 
    
    • 3
  9. Vipul
    2014-07-05T10:05:54+08:002014-07-05T10:05:54+08:00

    在 oracle 数据库中,Dual table 主要用于获取伪列的值。它包含以下属性:

    1. 它由 sys 用户拥有
    2. 它可供所有用户使用
    3. 它仅包含一列,名称为虚拟数据类型 Varchar2(1) ,该列的最大宽度可以是一个字符。

    如果您想了解更多详细信息,请查看此处

    • 1

相关问题

  • Oracle 中的数据库备份 - 导出数据库还是使用其他工具?

  • ORDER BY 使用文本列的自定义优先级

  • 舒服的sqlplus界面?[关闭]

  • 如何在数据库中找到最新的 SQL 语句?

  • 如何使用正则表达式查询名称?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve