Oracal里的select 1 from dual

今天在看公司代码的时候,发现有这一句SQL:

1
select 1 from dual

然后觉得有点奇怪,数据库里面都没有创建这个dual表,这个表是从何而来呢?

首先,公司用的是Oracle数据库,关于Oracle数据库中的dual表,官方文档说明(The DUAL Table):

DUAL是一个在数据字典里的很小的表,Oracle数据库和用户写的程序可以引用它来保证一个已知的结果。当一个值(比如当前date和time)有且仅需返回一次的时候,这个dual表还是很管用的。所有数据库用户都可以访问DUAL

DUAL是一个随着Oracle数据库创建数据字典时自动创建的表。虽然DUAL在用户SYS模式下,但是还是可以被所有用户访问的。它有一列,DUMMY,定义为VARCHAR2(1),和包含一行数据,值为X

对于用SELECT计算一个常量表达式来说,从DUAL选择是比较好用的。因为DUAL只有一行,所以常量只会返回一次。或者,你可以从任意一个表中选择常量、伪列和表达式,但是这个值将返回多次,次数和表的行数一样多。

1
2
3
4
SQL> select * from dual;
DUMMY
-----
X

好的,现在我们知道了dual这个表是长什么样了,也知道为什么会用这个表了。划重点:当一个值必须返回,且只返回一次,可以从dual表选择返回。

我看了一下项目代码,这句SQL是传给数据库连接池验证连接的,这样就很合理了:不需要返回太多的值,但是有必须有返回,选择从dual返回再正确不过了。

mysql里的select 1 from dual

SELECT can also be used to retrieve rows computed without reference to any table.
SELECT也可以在没有引用任何表,用来检索行。比如:

1
2
mysql> SELECT 1 + 1;
-> 2

在没有引用表的情况下,你可以指定DUAL为一个虚拟表名。比如:

1
2
mysql> SELECT 1 + 1 FROM DUAL;
-> 2

DUAL单纯是为那些要求所有SELECT语句应该有FROM或者其他子句的人们提供便利。MySQL可能忽略这个子句。因为即使没有表引用,MySQL也不要求FROM DUAL

并且,在MySQL中使用dual表并不总是对的:

1
2
mysql> select 1 from dual;
3013 - Unknown table ****.dual

所以其实MySQL就直接SELECT就行,不用加上from dual