Postgres:相关子查询与NOT EXISTS

时间:2014-05-11 15:00:01

标签: sql oracle postgresql

在Oracle SQL中,您可以根据相关子查询中的NOT EXISTS条件轻松进行更新。这对于根据其他查询或ID列表进行更新非常有用。

Postgres中子查询的机制不同......我怎样才能达到同样的目标? http://sqlfiddle.com/#!1/1dbb8/55

如何在Oracle上执行

UPDATE UserInfo a
SET a.username = 'not found'
WHERE NOT EXISTS (SELECT 'X' 
              FROM UserOrder b
              WHERE b.userid = a.userid)
AND a.userid in (1,2,3);

Postgres NOT EXISTS查询:此方法

SELECT u.userid, u.username
FROM UserInfo AS u
WHERE NOT EXISTS
  ( SELECT *
    FROM UserOrder AS o
    WHERE o.userid = u.userid
);

Postgres NOT EXISTS更新:不起作用

UPDATE UserInfo
SET username = 'not found'
FROM (SELECT u.userid
    FROM UserInfo AS u
    WHERE NOT EXISTS
       ( SELECT *
         FROM UserOrder AS o
         WHERE o.userid = u.userid
       )) em
WHERE em.userid = UserInfo.userid;

3 个答案:

答案 0 :(得分:2)

为什么让update比原始选择更复杂。这段代码应该适用于Postgres和Oracle:

UPDATE UserInfo ui
  SET username = 'not found'
  WHERE NOT EXISTS (SELECT 'X' 
                    FROM UserOrder uo
                    WHERE uo.userid = ui.userid
                   ) AND
        ui.userid in (1,2,3);

问题是SET ui.username。 Postgres不允许在set子句中使用表别名(因为您一次只能更新一个表)。

有一个"问题"与嵌套相关的子查询。它适用于某些数据库,但不适用于其他数据库。我知道它在SQL Server中有效,并且它在MySQL和Oracle中不起作用。我想它在Postgres中也不起作用。

答案 1 :(得分:2)

UPDATE UserInfo a
SET username = 'not found'
WHERE NOT EXISTS (
      SELECT 'X' 
      FROM UserOrder b
      WHERE b.userid = a.userid
      )
AND a.userid in (1,2,3)
  ;

绝对可以在Postgres中使用。

答案 2 :(得分:2)

显然,Sqlfiddle会在每次“运行脚本”时重新生成db内容。在与更新相同的脚本中运行select。

来自sqlfiddle的Oracle查询几乎可以正常工作,但是您忘了为userid参数添加别名。正确的查询:

/* How you would do it on Oracle */
UPDATE UserInfo
SET username = 'not found'
WHERE NOT EXISTS (SELECT 'X' 
                  FROM UserOrder b
                  WHERE b.userid = userinfo.userid);