我是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;
我可能会选择最后一个解决方案。我只是想知道是否可以使用左连接做我想做的事。
答案 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;