NodeJS 使用pg-promise的带子查询的多行插入

mepcadol  于 2023-05-06  发布在  Node.js
关注(0)|答案(1)|浏览(130)

我的Node.js应用当前使用多行插入将事件保存在表中:

var values = [{ start_time: '2023-05-01 11:15:00', end_time: '2023-05-01 17:35:00' },
              { start_time: '2023-01-01 19:20:00', end_time: '2023-01-02 23:35:00' }]
var machineId = 99;
const cs = new pgp.helpers.ColumnSet([ {name: 'machine_id', def: machineId },
                                        'start_time',
                                        'end_time'}],
                                      {table: 'events'});
const onConflict = `ON CONFLICT(machineId, start_time) 
                          DO UPDATE SET end_time = COALESCE(events.end_time, EXCLUDED.end_time)`;                                  
const query = pgp.helpers.insert(values, cs) + onConflict;

现在,我想扩展events表以包含另外两列数据,从而提供有关事件的详细信息。这些数据是从不同的表中检索的,如果能够在同一个插入查询中添加这些数据,那就太好了。
我尝试了以下方法:

var values = [{ start_time: '2023-05-01 11:15:00', end_time: '2023-05-01 17:35:00' },
                  { start_time: '2023-01-01 19:20:00', end_time: '2023-01-02 23:35:00' }]
var machineId = 99;
const cs = new pgp.helpers.ColumnSet(['machine_id',
                                      'start_time',
                                      'end_time',
                                      'task_at_start',
                                      'task_at_end'}],
                                    {table: 'events'});
const values = values.map((val) => ({
                                   machine_id: machineId,
                                   start_time: val.start_time,
                                   end_time: val.end_time,
                                   task_at_start: pgp.as.format('select task_id from tasks where time = $1', [val.start_time]),
                                   task_at_end: pgp.as.format('select task_id from tasks where time = $1', [val.end_time]) 
}))

const onConflict = `ON CONFLICT(machineId, start_time) 
                              DO UPDATE SET end_time = COALESCE(events.end_time, EXCLUDED.end_time)`;                                  
const query = pgp.helpers.insert(values, cs) + onConflict;

这会尝试将子查询作为文本插入到列task_at_starttask_at_end中。
有没有办法插入一个包含子查询的多行插入呢?
我已经对这个相关的问题发表了评论,我明白这可能不可能做到我想做的,但我决定自己创建一个问题,以充分详细说明我的情况。

w8f9ii69

w8f9ii691#

Column的语法是有据可查的。所以,它会是这样的:

const values = [{start_time: '2023-05-01 11:15:00', end_time: '2023-05-01 17:35:00'},
    {start_time: '2023-01-01 19:20:00', end_time: '2023-01-02 23:35:00'}]

const machineId = 99;

const cs = new pgp.helpers.ColumnSet(
    [
        {
            name: 'machine_id',
            prop: 'machineId',
            init: () => machineId
        },
        'start_time',
        'end_time',
        {
            name: 'task_at_start',
            init: c => pgp.as.format('select task_id from tasks where time = ${start_time}', c.source),
            mod: ':raw'
        },
        {
            name: 'task_at_end',
            init: c => pgp.as.format('select task_id from tasks where time = ${end_time}', c.source),
            mod: ':raw'
        }
    ],
    {table: 'events'});

const onConflict = `ON CONFLICT(machineId, start_time) 
                              DO UPDATE SET end_time = COALESCE(events.end_time, EXCLUDED.end_time)`;

const query = pgp.helpers.insert(values, cs) + onConflict;

一般来说,您在这里所做的并不是一个好的解决方案,因为您最终将为插入的每一行执行两个SELECT查询。
P.S.这里不需要额外的数据重新Map逻辑。

相关问题