无中生有?

有没有可能

SELECT "Hello world"
WHERE 1 = 1

在 SQL 中?

我想知道的主要问题是,我能否从无中选择(没有 FROM 子句)。

189082 次浏览

甲骨文:

SELECT 'Hello world' FROM dual

Dual equivalent in SQL Server:

SELECT 'Hello world'

You can. I'm using the following lines in a StackExchange Data Explorer query:

SELECT
(SELECT COUNT(*) FROM VotesOnPosts WHERE VoteTypeName = 'UpMod' AND UserId = @UserID AND PostTypeId = 2) AS TotalUpVotes,
(SELECT COUNT(*) FROM Answers WHERE UserId = @UserID) AS TotalAnswers

数据交换使用 Transact-SQL (SQL 的 SQLServer 专用扩展)。

您可以通过运行以下查询自己尝试:

SELECT 'Hello world'

不同厂商之间的支持不一致—— Oracle、 MySQL 和 DB2支持双重:

SELECT 'Hello world'
FROM DUAL

...while SQL Server, PostgreSQL, and SQLite don't require the FROM DUAL:

SELECT 'Hello world'

MySQL 确实支持这两种方式。

在标准 SQL 中,no. WHERE子句意味着表表达式。

From the SQL-92 spec:

7.6“地点条款”

功能

类派生的表 「查册条件」的适用范围 前面“从”的结果 条款”。

反过来:

7.4“从条款”

功能

指定从一个或多个命名表派生的表。

这样做的标准方法(即应该适用于任何 SQL 产品) :

SELECT DISTINCT 'Hello world' AS new_value
FROM AnyTableWithOneOrMoreRows
WHERE 1 = 1;

...assuming you want to change the WHERE clause to something more meaningful, otherwise it can be omitted.

在 SQLServer 类型中:

Select 'Your Text'

不需要 FROMWHERE子句。

我认为这是不可能的。理论上说: 选择执行两种类型的事情:

  • 缩小/拓宽集合(集合论) ;

  • 映射结果。

The first one can be seen as a horizontal diminishing opposed to the where-clause which can be seen as a vertical diminishing. On the other hand, a join can augment the set horizontally where a union can augment the set vertically.

               augmentation          diminishing
horizontal     join/select              select
vertical          union            where/inner-join

第二个是映射。一个映射,更多的是一个转换器。在 SQL 中,它接受一些字段并返回零个或多个字段。在 select 中,可以使用一些聚合函数,如 sum、 avg 等。或者将所有列值转换为字符串。在 C # linq 中,我们说 select 接受 T 类型的对象并返回 U 类型的对象。

我认为困惑来自于这样一个事实: 你可以做: select 'howdy' from <table_name>。这个特性就是映射,转换器部分的选择。您不是在打印什么东西,而是在转换!在你的例子中:

SELECT "
WHERE 1 = 1

you are converting nothing/null into "Hello world" and you narrow the set of nothing / no table into one row, which, imho make no sense at all.

您可能会注意到,如果不限制列的数量,将为表中的每个可用行打印 "Hello world"。我希望你现在明白为什么了。您的选择不从可用列获取任何内容,而是创建一个包含文本 "Hello world"的列。

So, my answer is NO. You can't just leave out the from-clause because the select always needs table-columns to perform on.

我知道这是一个老问题,但是解决这个问题的最好方法是使用一个虚拟子查询:

SELECT 'Hello World'
FROM (SELECT name='Nothing') n
WHERE 1=1

这样,在 select 语句之后就可以有 WHERE 和任何子句(如 Joins 或 Apply 等) ,因为虚拟子查询强制使用 FROM 子句而不更改结果。

I'm using firebird 首先,创建一个名为“ NoTable”的列表,如下所示

CREATE TABLE NOTABLE
(
NOCOLUMN              INTEGER
);
INSERT INTO NOTABLE VALUES (0); -- You can put any value

现在你可以写这个了

select 'hello world' as name

从著名的

您可以添加要显示的任何列

试试这个。

单身:

SELECT *  FROM (VALUES ('Hello world')) t1 (col1) WHERE 1 = 1

多元化:

SELECT *  FROM (VALUES ('Hello world'),('Hello world'),('Hello world')) t1 (col1) WHERE 1 = 1

more detail here : http://modern-sql.com/use-case/select-without-from

There is another possibility - standalone VALUES():

VALUES ('Hello World');

产出:

column1
Hello World

当您需要以简洁的方式指定多个值时,它非常有用:

VALUES (1, 'a'), (2, 'b'), (3, 'c');

产出:

column1     column2
1     a
2     b
3     c

DBFiddle 演示

SQLite/PostgreSQL/DB LUW/MariaDB 10.3支持此语法。

下面是来自 https://blog.jooq.org/tag/dual-table/的最完整的双重数据库支持列表:

在许多其他关系数据库管理系统中,不需要使用虚拟表,这是可以做到的 发表如下声明:

SELECT 1;
SELECT 1 + 1;
SELECT SQRT(2);

这些是关系数据库管理系统,在这些系统中通常可以实现上述功能:

  • H2
  • MySQL
  • 安格尔
  • 邮差
  • SQLite
  • SQL Server
  • Sybase ASE

在其他 RDBMS 中,需要使用虚表,如 Oracle, 你需要这样写:

SELECT 1       FROM DUAL;
SELECT 1 + 1   FROM DUAL;
SELECT SQRT(2) FROM DUAL;

这些是关系数据库管理系统及其各自的虚表:

  • DB2: SYSIBM.DUAL
  • Derby: SYSIBM.SYSDUMMY1
  • H2: 可选地支持 DUAL
  • INFORMATION _ SCHEMA. SYSTEM _ USERS
  • MySQL: 可选地支持 DUAL
  • 双人
  • SybaseSQLAnywhere: SYS.DUMMY

安格尔没有双机,但实际上需要它,因为在安格尔你不能 有 WHERE、 GROUPBY 或 HAVING 子句而没有 FROM 子句。

对于 ClickHouse 来说,什么都没有就是 system.one

SELECT 1 FROM system.one

在 Firebird 中,你可以这样做:

select "Hello world" from RDB$DATABASE;

RDB $DATABASE 是一个总是有一行的特殊表。

For DB2:

`VALUES('Hello world')`

你也可以做多个“行”:

`VALUES('Hello world'),('Goodbye world');`

只要类型匹配,您甚至可以在连接中使用它们:

VALUES(1,'Hello world')
UNION ALL
VALUES(2,'Goodbye world');