【问题标题】:SELECT from nothing?从无到有选择?
【发布时间】:2011-04-13 13:02:40
【问题描述】:

能不能有这样的说法

SELECT "Hello world"
WHERE 1 = 1

在 SQL 中?

我想知道的主要事情是,我可以从无到有 SELECT,即没有 FROM 子句。

【问题讨论】:

  • 查看您对@Rafael Belliard 的评论,您最好问问自己真正想做什么。例如,如果给定表存在值,您是否要返回一些字符串?
  • 是的,这正是我想要的。我知道我可以做到,我更想知道我是否需要在SELECTWHERE 之间的FROM NULL。措辞晦涩主要是因为这是家庭作业,如果我的直觉错了,我不想有人来告诉我答案。

标签: sql


【解决方案1】:

试试这个。

单身:

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

多:

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

更多细节在这里:http://modern-sql.com/use-case/select-without-from

【讨论】:

  • 唯一符合 ANSI SQL 的答案! (对于未指定 dbms 的问题。)
  • WHERE 1 = 1 的目的是什么?在 PostgreSQL 上没有它也可以工作。还是它涉及另一个 DMBS?
  • 只有SELECT * FROM (VALUES ("Hello world")) t1 (col1) 仍然可以。 Where只回答这个问题。
  • @chuongtv 如何选择多行?
  • @Hector 只需按照 SQL 的 struct insert 即可。像这样SELECT * FROM (VALUES ('Hello world'),('Hello world'),('Hello world')) t1 (col1) WHERE 1 = 1
【解决方案2】:

对于 DB2:

`VALUES('Hello world')`

你也可以做多个“行”:

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

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

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

【讨论】:

    【解决方案3】:

    在 Firebird 中,您可以这样做:

    select "Hello world" from RDB$DATABASE;
    

    RDB$DATABASE 是一个始终只有一行的特殊表。

    【讨论】:

      【解决方案4】:

      对于 ClickHouse,什么都不是 system.one

      SELECT 1 FROM system.one
      

      【讨论】:

        【解决方案5】:

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

        在许多其他 RDBMS 中,不需要虚拟表,因为您可以 发出这样的声明:

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

        这些是 RDBMS,上面通常是可能的:

        • H2
        • MySQL
        • 安格尔
        • Postgres
        • SQLite
        • SQL 服务器
        • Sybase ASE

        在其他 RDBMS 中,虚拟表是必需的,就像在 Oracle 中一样。因此, 您需要编写如下内容:

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

        这些是 RDBMS 及其各自的虚拟表:

        • DB2:SYSIBM.DUAL
        • 德比:SYSIBM.SYSDUMMY1
        • H2:可选择支持 DUAL
        • HSQLDB:INFORMATION_SCHEMA.SYSTEM_USERS
        • MySQL:可选择支持 DUAL
        • 甲骨文:双
        • Sybase SQL Anywhere:SYS.DUMMY

        Ingres 没有 DUAL,但实际上需要它,因为在 Ingres 中你不能 有没有 FROM 子句的 WHERE、GROUP BY 或 HAVING 子句。

        【讨论】:

          【解决方案6】:

          还有另一种可能——独立的VALUES()

          VALUES ('Hello World');
          

          输出:

          column1
          Hello World
          

          当您需要以紧凑的方式指定多个值时很有用:

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

          输出:

          column1     column2
                1     a
                2     b
                3     c
          

          DBFiddle Demo

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

          【讨论】:

            【解决方案7】:

            我正在使用火鸟 首先,像这样创建一个名为“NoTable”的单列表

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

            现在你可以写这个了

            select 'hello world' as name
            

            来自著名

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

            【讨论】:

              【解决方案8】:

              你可以。我在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
              

              Data Exchange 使用 Transact-SQL(SQL Server 专有的 SQL 扩展)。

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

              SELECT 'Hello world'
              

              【讨论】:

              • 数据交换是 Azure,基于 SQL Server。
              【解决方案9】:

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

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

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

              【讨论】:

              • 您的子查询中仍然有一个 SELECT 而没有 FROM,所以它在 Oracle 等中仍然会失败。
              • 在 Oracle 中更简单,因为您可以只使用 SELECT 'Hello' FROM dual WHERE 1=1 并跳过子查询。
              • OP 询问是否可以有一个没有FROM 子句的语句(即SELECT)。你没看问题吗?
              • 我确实阅读了这个问题,但除非您完全没有 SQL 经验(或没有阅读其他答案),否则您知道没有FROM 就无法拥有WHERE。鉴于此,我回复了 OP 问题的第一个陈述。
              • 嗯,我有超过 15 年的 SQL 经验,拥有计算学位,不记得现在拥有 WHERE 是否是标准 SQL。我也阅读了其他答案。顺便说一句:正确的是你不能有一个没有FROMSELECT,而不是“没有FROMWHERE”(?)。你的查询在哪里工作,@DomingoR?它仍然有一个没有FROMSELECT(在子查询中),因此在那些不允许在没有FROM 的情况下进行查询并且只处理那些偏离标准SQL 并且不允许没有FROMSELECT。所以你的答案毫无用处。
              【解决方案10】:

              在标准 SQL 中,没有。 WHERE 子句意味着一个表表达式。

              来自 SQL-92 规范:

              7.6“where子句”

              功能

              指定一个由 应用“搜索条件” 前面“从 子句”。

              反过来:

              7.4 “从子句”

              功能

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

              一种标准的做法(即应该适用于任何 SQL 产品):

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

              ...假设您要将WHERE 子句更改为更有意义的内容,否则可以省略。

              【讨论】:

              • 错误:my_table 中不存在列“hello world”查询失败 PostgreSQL 说:my_table 中不存在列“hello world”
              • @PålBrattberg:应该是单引号,现在已修复。
              • 在处理时间方面使用哪个表是否重要?或者 SELECT 不引用任何列这一事实是否使实际表无关紧要?
              • @AllenGould:它会“依赖于供应商”,但有明显的短路可以被利用,例如一种情况是优化器识别出SELECT 子句仅包含常量并且AnyTableWithOneOrMoreRows 是一个存储表,因此仅使用统计信息来验证该表是否有零行。
              【解决方案11】:

              我认为这是不可能的。理论上:select 执行两种操作:

              • 缩小/扩大集合(集合论);

              • 映射结果。

              第一个可以看作是水平递减,而 where 子句可以看作是垂直递减。另一方面,连接可以水平扩充集合,而联合可以垂直扩充集合。

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

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

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

              SELECT "
              WHERE 1 = 1
              

              您正在将 nothing/null 转换为 "Hello world",并且您将 none/no 表的集合缩小为一行,恕我直言,这根本没有意义。

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

              所以,我的答案是否定的。您不能只省略 from 子句,因为选择总是需要表列来执行。

              【讨论】:

                【解决方案12】:

                在 SQL Server 中输入:

                Select 'Your Text'
                

                不需要FROMWHERE 子句。

                【讨论】:

                  【解决方案13】:

                  Oracle:

                  SELECT 'Hello world' FROM dual
                  

                  Dual equivalent in SQL Server:

                  SELECT 'Hello world' 
                  

                  【讨论】:

                  • 我可以在后面加上WHERE (SELECT ... ) 之类的声明吗?
                  【解决方案14】:

                  供应商之间并不一致 - Oracle、MySQL 和 DB2 支持双重:

                  SELECT 'Hello world'
                    FROM DUAL
                  

                  ...而 SQL Server、PostgreSQL 和 SQLite 不需要 FROM DUAL

                  SELECT 'Hello world'
                  

                  MySQL 确实支持这两种方式。

                  【讨论】:

                  • 我一直想知道。为什么要为幻像表选择对偶这个词?
                  • @Alex:“原来的 DUAL 表中有两行(因此得名),但后来它只有一行。”
                  • 在 DB2 dual 上称为 'sysibm.sysdummy1'
                  • 在 Postgresql 上,可以创建一个名为 DUAL 的虚拟表并从类似幻像的表中执行查询。
                  • @AlexBlakemore “我创建了 DUAL 表作为 Oracle 数据字典中的基础对象。它本身并不打算被看到,而是在预期被查询的视图中使用。这个想法是您可以对 DUAL 表执行 JOIN 并在结果中为表中的每一行创建两行。然后,通过使用 GROUP BY,可以汇总生成的连接以显示 DATA 范围的存储量和对于 INDEX 范围。名称 DUAL 似乎适合从一个行创建一对行的过程" (en.wikipedia.org/wiki/DUAL_table)
                  猜你喜欢
                  • 1970-01-01
                  • 2021-12-07
                  • 1970-01-01
                  • 2015-02-02
                  • 2022-11-12
                  • 2013-09-08
                  • 1970-01-01
                  • 2012-02-09
                  相关资源
                  最近更新 更多