22

私はPostgreSQLを初めて使用し、SQLServerからクエリを変換しようとしています。

とりわけ、列bUsrActive、bUsrAdmin、およびsUsrClientCodeを持つテーブルUsersがあります。同じsUsrClientCode(bUsrAdmin=trueおよびbUsrActive=true)を持つ別のユーザーが存在しない場合は、Usersを更新し、bUsrActive=falseに設定します。

SQLServerではこのクエリがあります

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部分でテーブルUsersuを参照する方法がわかりません。

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)以下は機能していますが、joinを使用していません。

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は、行の一意の場所を指す疑似列です。テーブルに主キーがある場合は、代わりにそれを使用できます。

更新されたテーブルがFROM 句でUsers同じテーブルに結合されることはないため、質問のクエリ #2 は期待どおりに動作しません。Users uFROM 句にテーブル名を 2 回入力した場合と同様に、テーブル名は暗黙的に結合またはバインドされず、2 つの独立した行セットと見なされます。

于 2013-01-24T15:32:42.160 に答える