25

我有一个需要插入多条记录的场景。我有一个表结构,如 id(它是来自其他表的 fk)、key(char)、value(char)。需要保存的输入将是上述数据的数组。示例:我有一些数组对象,例如:

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);

在 MS SQL 中,我会创建 TVP 并通过它。我不知道如何在 postgres 中实现。所以现在我想做的是使用 pg-promise 库将列表中的所有项目保存在 postgres sql 的单个查询中。我无法从文档中找到任何文档/理解。任何帮助表示赞赏。谢谢。

4

1 回答 1

44

我是pg-promise的作者。

插入多条记录有两种方法。第一种也是最典型的方式是通过事务,以确保正确插入所有记录,或者一个都不插入。

使用pg-promise可以通过以下方式完成:

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
    });

您使用方法tx启动事务,然后创建所有INSERT查询承诺,然后将它们全部解析为batch

第二种方法是将所有插入值连接到一个INSERT查询中,我在Performance Boost中对此进行了详细说明。另请参阅:使用 pg-promise 进行多行插入

有关更多示例,请参阅任务事务

添加

值得指出的是,在大多数情况下,我们不会插入记录id,而是让它自动生成。有时我们想取回新的 id-s,而在其他情况下我们不在乎。

上面的示例使用null-s 数组解析,因为根据其 API , batch使用单个结果数组解析,方法none使用 解析。null

假设我们想要生成新的 id-s,并且想要将它们全部取回。为此,我们将代码更改为以下内容:

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
    });

即变化是:

  • 我们不插入id
  • 我们将方法none替换为one,以从每个插入中获取一行/对象
  • 我们追加RETURNING id到查询中以获取值
  • 我们添加a => +a.id做自动行转换。另请参阅pg-promise 将整数作为字符串返回以了解其+用途。

更新-1

INSERT有关通过单个查询的高性能方法,请参阅使用 pg-promise 的多行插入

更新-2

必读文章:数据导入

于 2016-03-26T10:35:19.360 回答