Mettre à jour ou insérer (plusieurs lignes et colonnes) à partir d'une sous-requête dans PostgreSQL


106

J'essaye de faire quelque chose comme ça dans postgres:

  • UPDATE table1 SET (col1, col2) = (SELECT col2, col3 FROM othertable WHERE othertable.col1 = 123);

  • INSERT INTO table1 (col1, col2) VALUES (SELECT col1, col2 FROM othertable)

Mais le point 1 n'est pas possible même avec postgres 9.0 comme mentionné dans la documentation ( http://www.postgresql.org/docs/9.0/static/sql-update.html )

Le point 2 semble également ne pas fonctionner. j'obtiens l'erreur suivante: la sous-requête ne doit renvoyer qu'une seule colonne.

J'espère que quelqu'un a une solution de contournement pour moi. sinon, les requêtes prendront un certain temps :(.

FYI: J'essaie de sélectionner différentes colonnes de plusieurs tables et de les stocker dans une table temporaire, afin qu'une autre application puisse facilement récupérer les données préparées.

Réponses:


175

Pour la MISE À JOUR

Utilisation:

UPDATE table1 
   SET col1 = othertable.col2,
       col2 = othertable.col3 
  FROM othertable 
 WHERE othertable.col1 = 123;

Pour l'INSERT

Utilisation:

INSERT INTO table1 (col1, col2) 
SELECT col1, col2 
  FROM othertable

Vous n'avez pas besoin de la VALUESsyntaxe si vous utilisez un SELECT pour remplir les valeurs INSERT.


1
Est-il possible de combiner Update & Insert de sorte que si l'un échoue, l'autre sera utilisé sans générer d'erreur (indépendamment pour chaque ligne). Je pense que ce serait une solution plus complète à la question (par exemple: stackoverflow.com/a/6527838/781695 )
utilisateur

26

La réponse d'OMG Ponies fonctionne parfaitement, mais juste au cas où vous auriez besoin de quelque chose de plus complexe, voici un exemple de requête de mise à jour légèrement plus avancée:

UPDATE table1 
SET col1 = subquery.col2,
    col2 = subquery.col3 
FROM (
    SELECT t2.foo as col1, t3.bar as col2, t3.foobar as col3 
    FROM table2 t2 INNER JOIN table3 t3 ON t2.id = t3.t2_id
    WHERE t2.created_at > '2016-01-01'
) AS subquery
WHERE table1.id = subquery.col1;

1
You're the best :) :)
Ashwini

1
parfait. cela fonctionne mieux dans lequel vous devez choisir un sous-ensemble basé sur une condition impliquant la table mise à jour elle-même.
mythicalcoder

@David Namenyi pouvez-vous expliquer cette requête?
Chintan Pathak

15
UPDATE table1 SET (col1, col2) = (col2, col3) FROM othertable WHERE othertable.col1 = 123;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.