关于加入

时间:2017-11-17 22:48:28

标签: sql postgresql join

我正在尝试在Postgres上运行一些更新查询,其中表连接在公共字段上。这是使用SQL Server运行的,更新计数是1,这是预期的,而postgres更新计数是3.当目标表与连接中涉及的源表名称相同时,postgres似乎不执行隐式连接。脚本可能比所说的更具描述性,而且在这里:

drop table test;
drop table test2;
create table test(col1 int, col2 varchar(10));
insert into test values(1, 'aaa');
insert into test values(2, 'bbb');
insert into test values(3, 'ccc');
create table test2(col1 int);
insert into test2 values(2);
select * from test;
select * from test2;

// Select join = rowcount 1
select count(*) from test t2, test2 t3
where t2.col1 = t3.col1;

// SQL Server update = 1; postgres =3 
update test set col2 = 'changed'
from test t2, test2 t3
where t2.col1 = t3.col1;

上述查询可以简化为:

update test set col2 = 'changed'
from test2 where test.col1 = test2.col1;

但这不是我的意图,因为join子句可能涉及更多的join语句。 希望的目的是运行这样的查询:

UPDATE IDMAP_CHILD_JOBID SET RESTORESUCCESS = IDMAP_TABLE_JOBID.RESTORESUCCESS, RESTOREERRMSG = IDMAP_TABLE_JOBID.RESTOREERRMSG
FROM CHILD, IDMAP_TABLE_JOBID
WHERE CHILD.ID = IDMAP_CHILD_JOBID.OLDID AND CHILD.FK1 = IDMAP_TABLE_JOBID.OLDID
AND IDMAP_TABLE_JOBID.RESTORESUCCESS = $FALSE

如果IDMAP_CHILD_JOBID与IDMAP_TABLE_JOBID相同,Postgres会抱怨多次指定的表。怎么能改写? 我的应用程序应该生成一个更新语句,其中应该运行统一查询,而行为是不同的。很明显,在不进行更新时,select会在select上执行。

3 个答案:

答案 0 :(得分:1)

如果你需要两次(或更多)引用同一个表,你需要给它们不同的别名,以便你可以参考它们:

update test t1
 set col2 = 'changed'
from test t2    --      <<-- same table !!
JOIN  test2 t3 ON t2.col1 = t3.col1;
where t1.something =t3.something        --<<-- link  the target to the source
        ;
UPDATE idmap_child_jobid dst -- <<-- alias=dst
SET restoresuccess = src.restoresuccess
, restoreerrmsg = i.restoreerrmsg
FROM idmap_table_jobid src --   <<-- same table, different alias=src
JOIN child c ON c.fk1 = src.oldid
WHERE c.id = dst.oldid
AND dst.restoresuccess = false 
        ;

[未经测试,因为我不知道表格定义或查询的意图]

This is run with SQL Server

SQL-server的更新语法(和语义)略有不同,在:

UPDATE test
 SET field= 'OMG'
FROM test t1
JOIN othertable t2 ON t1.field = t2.field
    ;

...范围表中只有仅两张表;即使test被提及两次,它也是同一个实体)这是Microsoft / Sybase 功能

答案 1 :(得分:0)

对于此SQL查询:

update test
    set col2 = 'changed'
    from test t2, test2 t3
    where t2.col1 = t3.col1;

等效的Postgres语法是:

update test
    set col2 = 'changed'
    from test2 t3
    where test.col1 = t3.col1;

update / join语法在两个数据库中有所不同(尽管我认为上述内容也适用于SQL Server)。

答案 2 :(得分:0)

我有点困惑,因为简化查询(SQry)之间似乎有区别 2 tables: test,test2和 最终查询(FQry) 3 tables: IDMAP_CHILD_JOBID, CHILD, IDMAP_TABLE_JOBID

更新SQry中的单行:(注意t1别名以防止table specified more than once错误)

update test t1
   set col2 = 'changed'
  from test t2, test2 t3
 where t2.col1   = t3.col1
   and t1.col1 = t3.col1;

因此FQry将更新从此查询返回的行,如果IDMAP_CHILD_JOBID中有多个与CHILD.ID匹配的行,则它们都将更新。

select IDMAP_CHILD_JOBID.RESTORESUCCESS,
       IDMAP_TABLE_JOBID.RESTORESUCCESS, RESTOREERRMSG,
       IDMAP_TABLE_JOBID.RESTOREERRMSG
FROM IDMAP_CHILD_JOBID, CHILD, IDMAP_TABLE_JOBID
WHERE CHILD.ID = IDMAP_CHILD_JOBID.OLDID
  AND CHILD.FK1 = IDMAP_TABLE_JOBID.OLDID
  AND IDMAP_TABLE_JOBID.RESTORESUCCESS = $FALSE
相关问题