暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL中FROM子句中子选项的别名

原创 eternity 2022-08-18
524

SQL中的别名是什么?

FROM子句中的SQL别名用于为结果集提供临时名称。结果集可以由表或视图名称、子选择和/或VALUES子句生成。别名是用AS关键字创建的,但语法允许我们省略它。别名仅在查询期间存在,通常用于提高结果集和列名的可读性。

SELECT r.rolname, s.usesuper, sub.datname, val.s
FROM
 pg_roles AS r,
 pg_shadow AS s,
 LATERAL (SELECT datname FROM pg_database d WHERE d.datdba = r.oid) AS sub,
 (VALUES (10, 'foo'), (13, 'bar')) AS val(i, s)
WHERE r.oid = val.i;

在这段无用的SQL代码中,我们有4个别名:r、s、sub和val。对于最后一个结果集,我们不仅使用了它的名称,还为它的列定义了别名:i和s。

定义别名的规则

有趣的是,对于常规表、视图和函数引用可能不使用别名。但根据SQL标准,我们必须为子选择和值子句使用别名。PostgreSQL几十年来严格遵循这一规则:

SELECT * FROM (SELECT generate_series(1, 3)), (VALUES (10, 'foo'), (13, 'bar'));
 
SQL Error [42601]: ERROR: subquery in FROM must have an alias
  Hint: For example, FROM (SELECT ...) [AS] foo.

直到PostgreSQL成为一种流行的数据库,许多人开始从Oracle和其他RDBMS迁移之前,这并不是一个大问题。因为在Oracle语法中,这类子句不必使用别名。5年前,Bernd Helmle首次发现了这种情况:
不时地,尤其是在从Oracle到PostgreSQL,我面临着人们的质疑,为什么这个别名来自PostgreSQL中子查询的子句是必需的。默认答案这里是SQL标准要求的。

这也正是我们的解析器中关于这个主题的评论:


*SQL规范不允许进行子选择

*()没有别名子句,

*所以我们也没有。这避免了该问题

*需要为它发明一个唯一的refname。

*如果有足够的资源,这是可以克服的

*受欢迎的需求,但现在让我们只是实施

*看看有没有人抱怨。

*然而,这看起来确实是一个好主意

*比“语法错误”更好的错误消息。

*/

Bernd立即提供了一个补丁,但由于对解决方案缺乏共识而被拒绝。

我的理解是,当时没有就取消这一规则的重要性达成共识。所以这是一个政治问题,而不是技术问题。在长达五年的时间里,PostgreSQL一直遵循这一规则。并将在即将到来的v15主要版本中继续发布。

在下一个PostgreSQL主要版本中,使子查询别名可选,但最近Dean Rasheed向开发分支提出了一个新的承诺:在FROM子句中使子查询别名可选。这允许FROM中的子SELECTs和VALUES子句使用别名从句省略。

这是SQL标准的扩展,由一些其他标准支持从而简化了从这些系统的转换以及消除由于需要这些设备而造成的微小不便别名。

汤姆·莱恩评论。

讨论:https://postgr.es/m/CAEZATCUCGCf82=hxd9N5n6xGHPyYpQnxW8HneeH+uP7yNALkWA@mail.gmail.com

我建议您检查Bernd和Dean提供的补丁,了解如何以不同的方式解决相同的问题。简而言之,Bernd的方法是自动为子句生成唯一别名,而Dean的方法根本不生成别名,这似乎比尝试生成唯一别名更简洁,代码更少。

让我们看看这是否有效。为了做到这一点,我从源代码构建了PostgreSQL,并运行了以下测试查询:

test=# SELECT version();
                                                 version                                                  
----------------------------------------------------------------------------------------------------------
 PostgreSQL 16devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
(1 row)
 
test=# SELECT * FROM (SELECT generate_series(1, 3)), (VALUES (10, 'foo'), (13, 'bar'));
 generate_series | column1 | column2 
-----------------+---------+---------
               1 |      10 | foo
               1 |      13 | bar
               2 |      10 | foo
               2 |      13 | bar
               3 |      10 | foo
               3 |      13 | bar
(6 rows)

结论

由于此功能,PostgreSQL将更兼容Oracle语法,这将大大简化迁移。但是,如果您真的想拥有从Oracle到PostgreSQL的平滑迁移体验,请给我们增强的Cybertec Migrator一个机会!您可以先观看演示视频,然后下载并在您的环境中进行测试。

作者相关

image.png
我是Cybertec的PostgreSQL专家和开发人员。自2002年以来,我一直在使用PostgreSQL。

原文标题:ALIASES FOR SUB-SELECTS IN FROM CLAUSE
原文作者:Pavlo Golub
原文链接:https://www.cybertec-postgresql.com/en/aliases-for-sub-selects-in-from-clause/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论