在Upsert上跳过空值

时间:2017-07-22 11:11:05

标签: javascript node.js pg-promise

我正在使用pg-promise来处理我的Postgres查询,我遇到了解决以下查询的麻烦:

我正在尝试创建一个单独批量插入多行的方法, 这是我的代码:

massUpsert: (orgId, entities) => db.tx((t) => {
    const queries = [];
    entities.forEach((entity) => {
      const { id, name, age, type } = entity;
      queries.push(
        t.one(`INSERT INTO public.table (id, name, age, type) 
             VALUES ($1, $2, $3, $4)
              ON CONFLICT (id) DO update
                SET 
                 name = $2,
                 age = $3,
                 type = $4
              RETURNING *`,
        [id, name, age, type]));
    });
    return t.batch(queries);
}),

现在的问题是,在某些情况下,我为一个或多个字段获取null,并且我希望数据库保留旧值而不是用null替换它。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

使用helpers方法生成查询:

const skipIfNull = name => ({name, skip: c => c.value === null});

const cs = new pgp.helpers.ColumnSet([
    '?id',
    skipIfNull('name'),
    skipIfNull('age'),
    skipIfNull('type')
], {table: 'table'});

查看类型ColumnSetColumn

从示例data生成查询:

const data = {
    id: 1,
    name: null, // will be skipped
    age: 123,
    type: 'tt'
};

const query = pgp.helpers.insert(data, cs) + ' ON CONFLICT(id) DO UPDATE SET ' +
    pgp.helpers.sets(data, cs) + ' RETURNING *';

将生成:

INSERT INTO "table"("id","name","age","type") VALUES(1,null,123,'tt')
ON CONFLICT(id) DO UPDATE SET "age"=123,"type"='tt' RETURNING *

但要注意,根据方法set API,如果所有条件列都变成null,它将返回一个空字符串,因此生成的查询将无效。你需要为它添加一个检查;)

另外,考虑到您正在生成多插入,可以生成一个可提供更好性能的多行插入。为此,请参阅Multi-row insert with pg-promise

另见: