Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51161
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 145
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-16 18:31
个人简介

关注PostgreSQL,关注数据库技术以及分布式系统,热爱开源,享受生活

文章分类

全部博文(9)

文章存档

2015年(1)

2014年(6)

2013年(2)

我的朋友

分类: Mysql/postgreSQL

2013-11-11 14:09:55

在PostgreSQL9.3中执行下边的SQL语句:

点击(此处)折叠或打开

  1. WITH
  2.   tblA (a_id, a_val) AS ( VALUES (1::integer, 'one-1'::varchar) )
  3. , tblB (b_id, b_val) AS ( VALUES (1::integer, 'one-b'::varchar) )
  4. , tblC (c_id, c_val) AS ( VALUES (1::integer, 'one-c'::varchar) )

  5. select *
  6. from tblA
  7.     join tblB on tblA.a_id = tblB.b_id
  8.     join (
  9.                      tblB
  10.                 join tblC on tblC.c_id = tblB.b_id
  11.             ) as x on tblA.a_id = x.c_id;
会得到这样的错误提示:ERROR:  table name "tblb" specified more than once

在PostgreSQL9.1中执行同样的SQL语句,却可以正常执行,这是为什么呢?9.3中对于表别名的约束规则有了那些限制呢?

以下是对Tom Lane大神的一些总结:
在SQL标准中,明确说明不允许在一个SELECT层次上多次使用相同的表别名,但在PG之前的版本中却允许出现相同的别名,只在真正产生歧义引用时才会给出提示。我们可以用同样的方法来处理LATERAL引用(LATERAL是9.3中新添加的特性,使用LATERAL修饰的子句可以引用它前边声明的表,详细信息参考文档)。

出现文章开头这种错误提示的主要原因在于checkNameSpaceConflicts 函数的使用,该函数在transformFromClauseItem中调用,如果JOIN左侧的别名已经在FROM子句中出现,则会抛出一个错误。Tom Lane认为这样做不是很合理,他给出的解决方案是:允许以上查询正常运行,在真正发生歧义时抛出一个错误提示:

点击(此处)折叠或打开

  1. select * from tenk1 a left join (int4_tbl a cross join lateral (select a.f1) b) c on unique1 = f1;
  2. ERROR: table reference "a" is ambiguous
  3. LINE 1: ... left join (int4_tbl a cross join lateral (select a.f1) b) ...
  4. ^

另外,在9.3中还有一个很有意思的情况:

点击(此处)折叠或打开

  1. select * from tenk1 a left join (int4_tbl a cross join int8_tbl b) c on unique1 = f1;
执行该语句将会抛出错误;但执行以下这个语句却没有任何问题

点击(此处)折叠或打开

  1. select * from tenk1 a left join (int4_tbl b cross join int8_tbl a) c on unique1 = f1;

总之,Tom认为应该删除9.3中添加的别名约束检测,添加一个测试,并在有歧义时给出提示。

 参考
1. 2. 3. 


阅读(3304) | 评论(0) | 转发(0) |
0

上一篇:PostgreSQL9.4之并行进程

下一篇:GCC常用选项

给主人留下些什么吧!~~