22

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

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

在 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;

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

4

2 回答 2

27

这是将此更新查询从 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从未连接到Users uFROM 子句中的同一个表。就像您在 FROM 子句中两次输入表名一样,它们不会被隐式连接或绑定在一起,它们被视为两组独立的行。

于 2013-01-24T15:32:42.160 回答
13

我认为这是正确的做法 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;
于 2016-01-15T07:42:53.243 回答