web-dev-qa-db-fra.com

Insertion de plusieurs enregistrements avec pg-promise

J'ai un scénario dans lequel je dois insérer plusieurs enregistrements. J'ai une structure de table comme id (c'est fk d'une autre table), key (char), value (char). L'entrée qui doit être enregistrée serait un tableau de données ci-dessus. exemple: j'ai quelques objets tableau comme:

lst = [];

obj = {};
obj.id= 123;
obj.key = 'somekey';
obj.value = '1234';
lst.Push(obj);

obj = {};
obj.id= 123;
obj.key = 'somekey1';
obj.value = '12345';
lst.Push(obj);

Dans MS SQL, j'aurais créé TVP et l'aurais passé. Je ne sais pas comment réussir en postgres. Alors maintenant, ce que je veux faire, c'est enregistrer tous les éléments de la liste en une seule requête dans PostgreSQL, en utilisant la bibliothèque pg-promise. Je ne trouve aucune documentation/compréhension à partir de la documentation. Toute aide appréciée. Merci.

21
Mandy

Je suis l'auteur de pg-promise .

Il existe deux façons d'insérer plusieurs enregistrements. La première et la plus courante consiste à effectuer une transaction pour s'assurer que tous les enregistrements sont correctement insérés, ou aucun d'entre eux.

Avec pg-promise cela se fait de la manière suivante:

db.tx(t => {
    const queries = lst.map(l => {
        return t.none('INSERT INTO table(id, key, value) VALUES(${id}, ${key}, ${value})', l);
    });
    return t.batch(queries);
})
    .then(data => {
        // SUCCESS
        // data = array of null-s
    })
    .catch(error => {
        // ERROR
    });

Vous lancez une transaction avec la méthode tx , puis créez toutes les promesses de requête INSERT, puis les résolvez toutes sous la forme batch .

La deuxième approche consiste à concaténer toutes les valeurs d'insertion dans une seule requête INSERT, que j'explique en détail dans Performance Boost . Voir aussi: Insertion sur plusieurs lignes avec pg-promise .

Pour plus d'exemples, voir Tâches et Transactions .

Addition

Il convient de noter que dans la plupart des cas, nous n'insérons pas un enregistrement id, mais le faisons générer automatiquement. Parfois, nous voulons récupérer les nouveaux identifiants, et dans d'autres cas, cela nous est égal.

Les exemples ci-dessus se résolvent avec un tableau de null- s, car batch se résout avec un tableau de résultats individuels et la méthode none se résout avec null, selon son API.

Supposons que nous voulons générer les nouveaux identifiants et que nous voulons tous les récupérer. Pour ce faire, nous changerions le code comme suit:

db.tx(t => {
    const queries = lst.map(l => {
        return t.one('INSERT INTO table(key, value) VALUES(${key}, ${value}) RETURNING id',
                       l, a => +a.id);
    });
    return t.batch(queries);
})
    .then(data => {
        // SUCCESS
        // data = array of new id-s;
    })
    .catch(error => {
        // ERROR
    });

c'est-à-dire que les changements sont:

  • nous n'insérons pas les valeurs id
  • nous remplaçons la méthode none par one , pour obtenir une ligne/un objet de chaque insert
  • nous ajoutons RETURNING id à la requête pour obtenir la valeur
  • nous ajoutons a => +a.id pour effectuer la transformation automatique des lignes. Voir aussi pg-promise renvoie des entiers sous forme de chaînes pour comprendre ce que cela + est pour.

MISE À JOUR-1

Pour une approche hautes performances via une seule requête INSERT, voir Insertion sur plusieurs lignes avec pg-promise .

MISE À JOUR-2

Un article incontournable: Data Imports .

37
vitaly-t