postgresql - ¿Puedo usar el valor de retorno de INSERTAR... VOLVER en otro INSERTAR?
sql-returning (6)
Es algo como esto posible?
INSERT INTO Table2 (val)
VALUES ((INSERT INTO Table1 (name) VALUES (''a_title'') RETURNING id));
como usar el valor de retorno como valor para insertar una fila en una segunda tabla con una referencia a la primera tabla?
table_ex
id default nextval (''table_id_seq'' :: regclass),
camp1 varchar
camp2 varchar
INSERT INTO table_ex(camp1,camp2) VALUES (''xxx'',''123'') RETURNING id
De acuerdo con la respuesta de Denis de Bernardy.
Si también desea que se devuelva el id posteriormente y desea insertar más elementos en Table2:
with rows as (
INSERT INTO Table1 (name) VALUES (''a_title'') RETURNING id
)
INSERT INTO Table2 (val, val2, val3)
SELECT id, ''val2value'', ''val3value''
FROM rows
RETURNING val
La mejor práctica para esta situación. Use RETURNING … INTO
INSERT INTO teams VALUES (...) RETURNING id INTO last_id;
Puede usar la función lastval()
:
Valor de retorno obtenido más recientemente con
nextval
para cualquier secuencia
Entonces algo como esto:
INSERT INTO Table1 (name) VALUES (''a_title'');
INSERT INTO Table2 (val) VALUES (lastval());
Esto funcionará bien siempre que nadie llame a nextval()
en cualquier otra secuencia (en la sesión actual) entre sus INSERT.
Como Denis señaló a continuación y advertí sobre lo anterior, usar lastval()
puede lastval()
problemas si se accede a otra secuencia usando nextval()
entre sus INSERT. Esto podría suceder si hubiera un disparador INSERT en la Table1
que llamara manualmente a nextval()
en una secuencia o, más probablemente, hiciera un INSERTAR en una tabla con una clave primaria SERIAL
o BIGSERIAL
. Si quieres ser realmente paranoico (algo bueno, ellos realmente son tú para lastval() después de todo), entonces podrías usar lastval() pero necesitarías saber el nombre de la secuencia relevante:
INSERT INTO Table1 (name) VALUES (''a_title'');
INSERT INTO Table2 (val) VALUES (currval(''Table1_id_seq''::regclass));
La secuencia generada automáticamente suele llamarse t_c_seq
donde t
es el nombre de la tabla c
es el nombre de la columna, pero siempre puede averiguar yendo a psql
y diciendo:
=> /d table_name;
y luego mirando el valor predeterminado para la columna en cuestión, por ejemplo:
id | integer | not null default nextval(''people_id_seq''::regclass)
FYI: lastval()
es, más o menos, la versión de PostgreSQL de LAST_INSERT_ID
de MySQL. Solo menciono esto porque mucha gente está más familiarizada con MySQL que con PostgreSQL, por lo que vincular a lastval()
con algo familiar podría aclarar las cosas.
Puedes hacerlo comenzando con Postgres 9.1:
with rows as (
INSERT INTO Table1 (name) VALUES (''a_title'') RETURNING id
)
INSERT INTO Table2 (val)
SELECT id
FROM rows
Mientras tanto, si solo estás interesado en la identificación, puedes hacerlo con un desencadenador:
create function t1_ins_into_t2()
returns trigger
as $$
begin
insert into table2 (val) values (new.id);
return new;
end;
$$ language plpgsql;
create trigger t1_ins_into_t2
after insert on table1
for each row
execute procedure t1_ins_into_t2();
DO $$
DECLARE tableId integer;
BEGIN
INSERT INTO Table1 (name) VALUES (''a_title'') RETURNING id INTO tableId;
INSERT INTO Table2 (val) VALUES (tableId);
END $$;
Probado con psql (10.3, servidor 9.6.8)