Postgres从左连接更新

时间:2013-01-24 09:41:15

标签: sql sql-server postgresql sql-update

我是PostgreSQL的新手,并尝试从SQL Server转换查询。

我有一个表用户,其中包括bUsrActive,bUsrAdmin和sUsrClientCode列。我想更新用户并设置bUsrActive = false如果不存在具有相同sUsrClientCode的另一个用户,其中bUsrAdmin = true且bUsrActive = true。

在SQL Server中,我有这个查询

UPDATE u SET u.bUsrActive = 0
FROM Users u
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL

我正在尝试将其转换为postgres。我写了3种方法。

1)我的第一次尝试。显然不行。

UPDATE Users u
    SET bUsrActive = false
FROM Users u2
WHERE u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true
AND u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL;

2)我理解为什么它不起作用(它更新所有用户)。我只是想不通如何在UPDATE ... SET部分中引用表用户u。

UPDATE Users
    SET bUsrActive = false
FROM Users u
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true
WHERE u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL;

3)以下工作正常,但未使用连接。

UPDATE Users
    SET bUsrActive = false
WHERE  NOT EXISTS (
    SELECT 1
    FROM Users u
    WHERE u.sUsrClientCode = Users.sUsrClientCode AND u.bUsrAdmin = true AND u.bUsrActive = true
) AND Users.bUsrAdmin = false AND Users.bUsrActive = true;

我可能会选择最后一个解决方案。我只是想知道是否可以使用左连接做我想做的事。

2 个答案:

答案 0 :(得分:16)

这是将此更新查询从SQL服务器表单转换为PostgreSQL的通用方法:

UPDATE Users
 SET bUsrActive = false
WHERE
 ctid IN (
   SELECT u.ctid FROM Users u
      LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1
    WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL
)

ctid是一个伪列,指向行的唯一位置。如果有一个主键,则可以使用表的主键。

问题中的查询#2没有达到您的预期,因为更新的表Users永远不会加入FROM子句中的同一个表Users u。就像在FROM子句中将表名两次放置一样,它们不会被隐式连接或绑定在一起,它们被视为两个独立的行集。

答案 1 :(得分:2)

我认为这是正确的做法2)我相信它比做次选择更优/更有效。

UPDATE Users uOrig
    SET bUsrActive = false
FROM Users u
      LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL
    and uOrig.sUsrClientCode = u.sUsrClientCode;