I want to store an update's RETURNING values into a data structure so that I can use it in a subsequent query.
In this example, I'm given a list of "parent_ids", and I want to find all children whose parent is in that array. Then, I wish to update some value on them, and do other stuff.
CREATE OR REPLACE FUNCTION plpgsql_is_really_great(parent_ids bigint[])
RETURNS void AS
$$
DECLARE
found_ids bigint[];
BEGIN
UPDATE child SET
foo = bar
FROM
(SELECT id
FROM child
WHERE parent_id=ANY(parent_ids)
) as children_ids
WHERE
child.id = children_ids.id
RETURNING children_ids.id INTO found_ids; -- ???
-- do more stuff with found_ids
$$ LANGUAGE plpgsql
CREATE OR REPLACE FUNCTION contact_countries_array(INT) RETURNS ANYARRAY AS ' SELECT ARRAY[contacts_primarycountry, contacts_othercountry] FROM contacts WHERE contacts_id = $1' LANGUAGE SQL; The data type of contacts_primarycountry and contacts_othercountry is integer. contacts_id is unique and integer.
A common shorthand is RETURNING * , which selects all columns of the target table in order. In an INSERT , the data available to RETURNING is the row as it was inserted. This is not so useful in trivial inserts, since it would just repeat the data provided by the client.
The select ... for update acquires a ROW SHARE LOCK on a table. This lock conflicts with the EXCLUSIVE lock needed for an update statement, and prevents any changes that could happen concurrently. All the locks will be released when the transaction ends.
There are a few ways to go about this.
Say you want to call some f(id)
for each id
affected by the UPDATE
.
In PL/pgSQL:
$$
DECLARE found_id BIGINT;
BEGIN
FOR found_id IN (UPDATE child SET foo=bar RETURNING id) LOOP
PERFORM f(found_id);
END LOOP;
END
$$
In pure SQL:
WITH updated(found_id) AS (
UPDATE child SET foo=bar RETURNING id
)
SELECT f(found_id) FROM updated;
If you want to collect all the found_id
s in an array, you can simply:
$$
DECLARE array_var BIGINT[];
BEGIN
WITH updated(found_id) AS (
UPDATE child SET foo=bar RETURNING id
)
SELECT array_agg(found_id) FROM updated INTO array_var;
END
$$
Here is an example:
CREATE OR REPLACE FUNCTION exemplary ( parent_ids bigint[] )
RETURNS VOID AS $$
DECLARE
_found_ids bigint[];
BEGIN
WITH matching_children AS (
UPDATE child
SET foo = 1
WHERE parent_id = ANY ( parent_ids )
RETURNING id
)
SELECT array_agg ( id )
FROM matching_children
INTO _found_ids;
RAISE NOTICE '%', _found_ids;
RETURN;
END $$ LANGUAGE plpgsql;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With