Reputation: 3278
I'm trying to perform multiple inserts from 1 sql query. To break down what I'm trying to do here is the DB structure:
links:
- id // uuid_generate_v4()
- hash
permissions:
- id // uuid_generate_v4()
- name
photos:
- id // uuid_generate_v4()
- url
link_permissions:
- link_id
- permission_id
link_photo:
- link_id
- photo_id
Now whenever I insert a link I need to also insert its permissions and photos. This is the sql queries I've attempted so far.
WITH link as (
INSERT INTO links(hash) VALUES ('my-random-hash')
RETURNING *
)
INSERT INTO link_photo(link_id, photo_id)
VALUES ((select link.id from link), '095ccacf-ebc1-4991-8ab0-cac13dac02b7'),
INSERT INTO link_permission(link_id, permission_id)
VALUES ((select link.id from link), '506f3302-fe9f-4982-8439-d6781f646d01')
and
WITH link as (
INSERT INTO links(hash) VALUES ('my-random-hash')
RETURNING *
)
(INSERT INTO link_photo(link_id, photo_id)
VALUES ((select link.id from link), '095ccacf-ebc1-4991-8ab0-cac13dac02b7')),
INSERT INTO link_permission(link_id, permission_id)
VALUES ((select link.id from link), '506f3302-fe9f-4982-8439-d6781f646d01')
How would I write this query?
Upvotes: 4
Views: 327
Reputation:
Just put the the second insert into another CTE:
WITH link as (
INSERT INTO links(hash) VALUES ('my-random-hash')
RETURNING *
) , lp as (
INSERT INTO link_photo(link_id, photo_id)
VALUES ((select link.id from link), '095ccacf-ebc1-4991-8ab0-cac13dac02b7')
)
INSERT INTO link_permission(link_id, permission_id)
VALUES ((select link.id from link), '506f3302-fe9f-4982-8439-d6781f646d01');
Alternatively, don't use values
, that makes the query a bit easier to read (I think)
WITH link as (
INSERT INTO links(hash) VALUES ('my-random-hash')
RETURNING *
) , lp as (
INSERT INTO link_photo(link_id, photo_id)
select id, '095ccacf-ebc1-4991-8ab0-cac13dac02b7'
from link
)
INSERT INTO link_permission(link_id, permission_id)
select id, '506f3302-fe9f-4982-8439-d6781f646d01'
from link;
Upvotes: 3
Reputation: 164679
Now whenever I insert a link I need to also insert its permissions and photos.
There's several ways you can accomplish this. You can use returning id into link_id
to place the link id into the variable link_id
and reference that in later statements.
Since this all has to happen in concert, you can write a function to handle it. This ensures it always happens together, you don't have to try and cram it all into one statement, and it makes it easier to use variables. You can also add a transaction and error handling should any part fail.
create function add_link( photo_id uuid, permission_id uuid)
returns uuid
as
$func$
declare
link_id uuid;
begin
insert into links(id, hash)
values (default, 'probably have the function generate this?')
returning id into link_id;
insert into link_photo(link_id, photo_id)
values (link_id, photo_id);
insert into link_permission(link_id, permission_id)
values (link_id, permission_id);
return link_id;
end
$func$ language plpgsql;
test=# select * from add_link(uuid_generate_v4(), uuid_generate_v4());
add_link
--------------------------------------
1c18b24c-c7ac-4169-8449-1c18c9087f8b
(1 row)
Upvotes: 1
Reputation: 51882
Wouldn't your first attempt work (I haven't tried myself) if you replaced "RETURNING *" with "RETURNING id" and selecting that.
See the answer to this question for the full query
Upvotes: 0
Reputation: 657
Postgresql's "with query" only works with one statetment.
You can do it in "one run" by using an anonymous code block, but it will probably be a better idea to create a proper plpgsql insert function.
Upvotes: 1