Question

In Oracle SQL, you can easily do an update based on a NOT EXISTS condition in a correlated subquery. This is useful for doing updates based on another query or list of ids.

The mechanism for subqueries is different in Postgres... how can I achieve the same goal? http://sqlfiddle.com/#!1/1dbb8/55

How you would do it on 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 query: this works

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 : does not work

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;
Was it helpful?

Solution

Sqlfiddle does regenerate the db contents for each time you "run script", apparently. Run the select in the same script as the update.

Your Oracle query from sqlfiddle almost works, but You forgot to alias the userid parameter. Correct query:

/* 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);

OTHER TIPS

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

Should definitely work in Postgres.

Why are you making the update more complicated than the original select. This code should work in both Postgres and 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);

The problem is the SET ui.username. Postgres does not allow table aliases in the set clause (because you can only update one table at a time).

There is a "problem" with nesting correlated subqueries. It works in some databases, but not in others. I know it works in SQL Server, and that it does not work in MySQL and Oracle. I guess it doesn't work in Postgres either.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top