首页 > 解决方案 > 使用数组中的 2 个不同参数在 PostgreSQL 中插入记录

问题描述

我正在尝试从数组中批量插入 postgresql。我目前正在做的是循环内的以下内容。

INSERT INTO table_name (
  first, second, third, forth
) VALUES (
  $1, $2, $3, $4
)

大约有 8 到 9 个其他字段,每次迭代中只有 2 个字段发生变化。理想情况下,我想做的是类似于此伪代码的内容

FOREACH (obj IN $5)
  INSERT INTO table_name (
    first, second, third, forth
  ) VALUES (
    obj.fieldOne, $2, obj.fieldThree, $4
  ) 

并且只提供$2$4(不变的属性),$5它是一个像这样的不断变化的属性数组

[{one: 123, two: 63}]


我知道 PostgreSQL 允许在一个 INSERT 语句中插入多个值,但是构造查询和管理它的参数可能很麻烦,老实说,我只是因为参数和查询字符串地狱而逃避它。

INSERT INTO tabel_name (
  first, second, third, forth
) VALUES (
  $1, $2, $3, $4
) VALUES (
  $5, $2, $6, $4
) VALUES (
  $7, $2, $8, $4
)

我还读到 PostgreSQL 有 FOR 和 FOREACH 之类的循环,但我不知道如何在这种情况下使用它们。pg-promise如果相关,我正在使用 NodeJS 。任何帮助表示赞赏!

标签: javascriptsqlpostgresqlpg-promise

解决方案


使用与多行插入相同的方法,您有两个选择:

  • 将其他固定的 7 个属性添加到数组中的每个对象;

或者

  • 对仅在开头设置的列使用预定义值

第一个选项的解决方案很明显,您只需遍历数组并为 7 个属性设置相同的值。

对于第二个选项,您可以使用Columninit的属性将值重定向到静态对象:

/* You can set this once, since you do not need to change it; */
const staticValues = {
  one: 111, three: 333, five: 555, six: 666, seven: 777, eight: 888, nine: 999
};

然后你可以ColumnSet像这样定义你的对象:

/* helper for defining our static-value column: */
const col = name => ({name, init: ()=> staticValues[name]});

/* Our ColumnSet object: */
const cs = new pgp.helpers.ColumnSet([
    col('one'),
    'two',
    col('three'),
    'four',
    col('five'),
    col('six'),
    col('seven'),
    col('eight'),
    col('nine')],
{table: 'table_name'});

现在,当您要生成完整的插入查询时,将所有固定值设置到staticValues对象中,然后生成查询:

const query = pgp.helpers.insert(data, cs);

这将根据您的原始想法生成查询字符串,您可以data仅使用属性传递它twofour为其中的每个对象进行设置。

然后你可以执行查询:

db.none(query).then().catch();

我的几个专栏依赖于一个以上的参数。我该怎么做?

你可以用任何你想要的方式定义这样的列,因为Column类型非常灵活:

{
    name: 'col-name',
    init: c => pgp.as.format('myFunction(${one}, ${two}, ${three})', c.source),
    mod: ':raw'
}

或使用任何其他格式模板。


推荐阅读