首页 文章

Postgres关于加入的错误更新

提问于
浏览
0

我试图在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

    如果需要两次(或更多)引用同一个表,则需要为它们指定不同的别名,以便您可以参考每个别名:


    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
        ;
    

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

  • 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) .

  • 1

    我有点困惑,因为简化查询(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
    

相关问题