web-dev-qa-db-fra.com

Puis-je utiliser la valeur de retour INSERT ... RETURNING dans un autre INSERT?

Est-ce que quelque chose comme ça est possible?

INSERT INTO Table2 (val)
VALUES ((INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id));

vous aimez utiliser la valeur de retour comme valeur pour insérer une ligne dans une deuxième table avec une référence à la première table?

65
Eike Cochu

Vous pouvez le faire à partir de Postgres 9.1:

with rows as (
INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id
)
INSERT INTO Table2 (val)
SELECT id
FROM rows

En attendant, si vous ne vous intéressez qu'à l'ID, vous pouvez le faire avec un déclencheur:

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();
79
Denis de Bernardy

La meilleure pratique pour cette situation. Utilisation RETURNING … INTO .

INSERT INTO teams VALUES (...) RETURNING id INTO last_id;
46
Alexandre Assi

En ligne avec la réponse donnée par Denis de Bernardy.

Si vous souhaitez que l'identifiant soit également renvoyé après et que vous souhaitiez insérer davantage d'éléments dans 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
8
Bhindi

Vous pouvez utiliser la fonction lastval() :

Renvoie la valeur la plus récente obtenue avec nextval pour toute séquence

Donc, quelque chose comme ça:

INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val)  VALUES (lastval());

Cela fonctionnera correctement tant que personne n’appellera nextval() sur aucune autre séquence (de la session en cours) entre vos INSERT.

Comme Denis notée ci-dessous et comme je l'avais déjà signalé, l'utilisation de lastval() peut vous causer des problèmes si vous accédez à une autre séquence à l'aide de nextval() entre vos INSERT. Cela peut arriver s'il y a un déclencheur INSERT sur Table1 Qui appelle manuellement nextval() sur une séquence ou, plus vraisemblablement, un INSERT sur une table avec un SERIAL ou BIGSERIAL clé primaire. Si vous voulez être vraiment paranoïaque (une bonne chose, , ils devez-vous vraiment vous avoir après tout), alors vous pouvez utiliser currval() mais vous devez connaître le nom de la séquence pertinente:

INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val)  VALUES (currval('Table1_id_seq'::regclass));

La séquence générée automatiquement est généralement nommée t_c_seq, Où t est le nom de la table et c est le nom de la colonne, mais vous pouvez toujours le savoir en entrant dans psql. et en disant:

=> \d table_name;

puis en regardant la valeur par défaut pour la colonne en question, par exemple:

id | integer | not null default nextval('people_id_seq'::regclass)

FYI: lastval() est plus ou moins la version PostgreSQL de MySQL LAST_INSERT_ID . Je le mentionne seulement parce que beaucoup de gens sont plus familiers avec MySQL que PostgreSQL, aussi relier lastval() à quelque chose de familier peut clarifier les choses.

7
mu is too short
DO $$
DECLARE tableId integer;
BEGIN
  INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id INTO tableId;
  INSERT INTO Table2 (val) VALUES (tableId);
END $$;

Testé avec psql (10.3, serveur 9.6.8)

3
Anders B

table_ex

id default nextval ('table_id_seq' :: regclass),

camp1 varchar

camp2 varchar

INSERT INTO table_ex(camp1,camp2) VALUES ('xxx','123') RETURNING id 
0
kemado77