skip to Main Content

I have the following query:

UPDATE items SET quantity = quantity - 1 
WHERE quantity > 0 AND user_id = $1 AND item_id IN (5, 6, 7);

I’d like to modify it such that the update will only occur if all three rows are updated.

That is, unless that user has items 5, 6, 7 with quantities greater than 0 for each of them, 0 rows will be updated. However, if the condition is true for each, then all three rows are updated.

I’m not sure of a simple way to do this. My gut solution is to use a CTE where the initial query gets the COUNT and then you only perform the update if the count = 3, but I think there must be a better way?

Also, I am using 3 items here as an example. The number of item_ids is variable, and can be anywhere between 1 and 20 in my case (passed from the app server as an array)

3

Answers


  1. Chosen as BEST ANSWER

    Added a check constraint to the table quantity >= 0 and then just did this:

    UPDATE items SET quantity = quantity - 1 
    WHERE user_id = $1 AND item_id IN (5, 6, 7);
    

  2. Use transaction. Inside the transaction, execute the UPDATE. Check the number of rows updated. If that number is less than the length of the list of IDs, abort the transaction with ROLLBACK, else COMMIT.

    Login or Signup to reply.
  3. Yet another option is to check when the couple of <user_id, item_id> is not present with a quantity equal to 0, using the NOT EXISTS operator.

    UPDATE items i
    SET quantity = quantity - 1 
    WHERE user_id = $1 
      AND item_id IN (5, 6, 7)
      AND NOT EXISTS (SELECT user_id, item_id 
                      FROM items 
                      WHERE i.user_id = user_id AND i.item_id = item_id 
                        AND quantity = 0);
    

    Check the demo here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search