I have two tables, users and groups:
users(user_id BIGSERIAL, email TEXT UNIQUE NOT NULL, state TEXT NOT NULL)
groups(group_id BIGSERIAL, name TEXT, members []BIGINT)
As you can see from above, the users table contains a user records, where each record is uniquely identified by an email address and an auto-generated user_id field. The groups table contains a members array which contains a bunch of BIGINTs that refer to user_id in the users table.
Now I need a query, which when given two incoming parameters, email and a group_id:
- Checks if the
userstable already contains a record with that email address INSERTa new record if no row already contains that email addressSELECTtheuser_idof the row (either newly created or already existing)- Append that
user_idobtained in above step and append that into themembersfield of the groups table where thegroup_idmatches with the incoming parameter. There is a chance that the members field already contains theuser_idin which case no action needs to be done (IOW, there should be no duplicate values for themembersfield for each row in thegroupstable).
For, 1, 2 and 3, I have written the following query:
WITH new_row AS (
INSERT INTO users (email, state)
SELECT '[email protected]', 'Referred'
WHERE NOT EXISTS (SELECT * FROM users WHERE email = '[email protected]')
RETURNING *
)
SELECT user_id FROM new_row
UNION
SELECT user_id FROM users WHERE email='[email protected]';
For 4, I have written the following query:
UPDATE groups SET members = (
SELECT ARRAY(
SELECT DISTINCT unnest(members || array[RANDOM_USER_ID]::bigint[]) ) )
WHERE group_id = INCOMING_GROUP_ID
RETURNING group_id, members;
where RANDOM_USER_ID in the second query should be replaced with the user_id that is obtained in the first query.
Now what is the way to combine both of these queries atomically as a single query, where the user_id from the first query is piped to the second query ? I do not want to create a transaction and run the two individual queries independently and keep the user_id field in a temporary place (in my server program). I want all of these to be done in a single query. Is it possible ?
I will be using Postgresql 9.6.4 (or later) on RDS/Google CloudSQL, if it matters.