在Upsert上跳过空值

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

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

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

现在的问题是,在某些情况下,我得到一个或多个字段为空,我希望数据库保留旧值,而不是用空值replace它。

有什么build议么?

使用助手方法来生成查询:

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

请参见typesColumnSet和Column 。

从样本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 * 

但要注意,按照方法设置的 API,如果所有的条件列都是空的,它将返回一个空string,所以生成的查询将是无效的。 你会想添加一个检查;)

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

也可以看看:

  • 用pg-promise跳过更新列