Returning multiple values from UPDATE query in PostgreSQL

Shvalb

I'm new to writing DB functions and I need to return the value of 'last_login_at' as OUT parameter when performing an UPDATE query.

Here is a snippet of my function:

...
LOOP
    UPDATE "user" SET 
        last_login_at = current_timestamp, 
        first_name = p_first_name,
        last_name = p_last_name,
    WHERE ext_user_id = p_ext_user_id AND platform_id = p_platform_id
    RETURNING id INTO v_user_id;
    is_new := false;
    // The next 'CASE' is not valid - Need to replace it with a valid one.  
    has_logged_in_today = CASE
     WHEN date_part('day', age(current_timestamp, last_login_at)) > 1
     THEN true
     ELSE false
     END;
    IF FOUND THEN 
        EXIT;
    END IF;
..
..
END LOOP;

Is it possible to do multiple RETURNING x INTO y?
Can we use a CASE statement in RETURNING x INTO y?

EDIT

I was able to get better results and now it looks like this:

   ...
    LOOP
        UPDATE "user" SET 
            login_consecutive_days = CASE 
                WHEN date_part('day', age(current_timestamp, last_login_at)) > 1 
                THEN 0
                ELSE login_consecutive_days + date_part('day', age(current_timestamp, last_login_at))
                END,
        login_max_consecutive_days = CASE
        WHEN date_part('day', age(current_timestamp, last_login_at)) = 1
             AND (login_consecutive_days+1 > login_max_consecutive_days)
        THEN login_consecutive_days+1
        ELSE login_max_consecutive_days
        END,
        last_login_at = current_timestamp, 
            num_sessions = num_sessions + 1,
            last_update_source = 'L',
            first_name = p_first_name,
            last_name = p_last_name,
            additional_data = p_additional_data
        WHERE ext_user_id = p_ext_user_id AND platform_id = p_platform_id
        RETURNING id,
        CASE
        WHEN date_part('day', age(current_timestamp, last_login_at)) = 0
        THEN true
        ELSE false
        END
    INTO v_user_id, is_first_login_today;
        is_new := false;
        IF FOUND THEN 
            EXIT;
        END IF;
    ...

The only problem with this is that at the point of RETURNING the last_login_at has already been updated so CASE always returns TRUE.

Is there a magical solution to my problem?

Erwin Brandstetter

Is there a magical solution to my problem?

Actually, there is: Join to another instance of the "user" table in the FROM clause:

   UPDATE "user" u
   SET    login_consecutive_days = ...  -- unqualified column name

   FROM   "user" u1
   WHERE  u.ext_user_id = p_ext_user_id
   AND    u.platform_id = p_platform_id
   AND    u.id = u1.id                  -- must be unique not null (like the PK)
   RETURNING u.id, (u1.last_login_at < now() + interval '1 day')
   INTO   v_user_id, is_first_login_today;

   is_new := false;
   EXIT WHEN FOUND;

Now, the table alias u refers to the post-UPDATE state of the table, but u1 refers to a snapshot at the start of the query.

Detailed explanation:

Table-qualify all column references to be unambiguous, which is never a bad idea, but after the self-join it's required.

The manual about the short syntax EXIT WHEN FOUND.

You can use any expression in the RETURNING clause, including CASE statements. There just happens to be a simpler, cheaper way for this:

CASE WHEN date_part('day', age(current_timestamp, last_login_at)) = 0
THEN true ELSE false END

Step 1:

CASE WHEN last_login_at < now() + interval '1 day'
THEN true ELSE false END

Step 2:

(last_login_at < now() + interval '1 day')

Just use the boolean result. If last_login_at is NULL, you get NULL.


Asides:
As for the rest of the query: expressions can be simplified, the LOOP is suspicious, you should never use reserved words as identifiers, even though double-quoting makes it possible ("user"), the algorithm seems to depend on being executed in exact 24h intervals, which is error-prone.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Returning multiple values from function

Update multiple rows in same query using PostgreSQL

Returning multiple values from a C++ function

Update Returning Order by in postgresql

postgresql update multiple tables in single query

Returning multiple values from a function in C

Update multiple values in a jsonb data in PostgreSQL

In PHP PDO how to get "RETURNING" clause values of PostgreSQL upsert query

Returning unique values from multiple data attributes

UPDATE with multiple values from subquery

MYSQL UPDATE query for multiple values

How to update values of a column with multiple values from a query in one table in SQL Server?

Returning multiple values from PL/SQL function

Update query for multiple values starting with the same name

Loop and update LINQ query returning multiple objects

The right way of returning multiple values from a method

Returning null values with multiple table in a query

Update SQL query for multiple values

returning multiple values from functions

Returning values from a method with multiple variables

Returning multiple values from a combo box reference

Excel. Returning values from multiple columns

Returning multiple values from sql stored procedure

SQL Query returning multiple values

PostgreSQL query returning values that are not in my database

Returning ienumerable result from multiple query in dapper

Returning multiple values from a Prolog list

How to update multiple columns on PostgreSQL with values from another table

How to duplicate returning values from a query in MySQL

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    pump.io port in URL

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    flutter: dropdown item programmatically unselect problem

  14. 14

    How to use merge windows unallocated space into Ubuntu using GParted?

  15. 15

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  16. 16

    Nuget add packages gives access denied errors

  17. 17

    Svchost high CPU from Microsoft.BingWeather app errors

  18. 18

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  19. 19

    12.04.3--- Dconf Editor won't show com>canonical>unity option

  20. 20

    Any way to remove trailing whitespace *FOR EDITED* lines in Eclipse [for Java]?

  21. 21

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

HotTag

Archive