重新使用传递给node-postgres upsert查询的参数

问题描述 投票:0回答:1

我正在使用

node-pg
并且我决定重构一些代码,首先进行选择查询以查看记录是否存在,然后进行第二次查询以插入或更新记录。

假设如下表结构:

CREATE TABLE IF NOT EXISTS my_schema.user_profile (
    id SERIAL PRIMARY KEY,
    user_id BIGINT REFERENCES %%.user (id) UNIQUE NOT NULL,
    media_url VARCHAR(50) NOT NULL,
    created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE 'utc'),
    updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE 'utc')
);

我发现了类似下面的东西,

const request = {
    userId: 123,
    mediaUrl: 'https://...'
};
const query = `
    INSERT INTO my_schema.user_profile
        (user_id, media_url)
    VALUES
        ($1, $2)
    ON CONFLICT (user_id)
        DO UPDATE SET (
            updated_at,
            media_url
        ) = (
            CURRENT_TIMESTAMP(0) AT TIME ZONE 'UTC',
            $1
        )
`;

const values = [
    request.userId,
    request.mediaUrl
];

const result = await client.query(query, values);

但是这里的问题是

values
仅对查询的插入部分有效。如果存在需要更新的记录,则该值数组不正确,它必须是:

const values = [
    request.mediaUrl,
];

但是随后

node-pg
将开始抱怨查询的更新部分更新的列数多于提供的参数化列数。

我怎样才能让这样的东西发挥作用?

sql node.js postgresql upsert node-postgres
1个回答
2
投票
const request = {
    userId: 123,
    mediaUrl: 'https://...'
};
const query = `
    INSERT INTO my_schema.user_profile
        (user_id, media_url)
    VALUES
        ($1, $2)
    ON CONFLICT (user_id)
        DO UPDATE SET
            updated_at = CURRENT_TIMESTAMP(0) AT TIME ZONE 'UTC',
            media_url  = excluded.media_url
`;

const values = [
    request.userId,
    request.mediaUrl
];

const result = await client.query(query, values);
  1. update
    子句中发生的 on conflict
     的范围已经仅限于冲突行的上下文,它不是一个成熟的、独立的 
    update
    ,您必须专门针对才能获得在那里,所以
    where
    现已删除
    )是不必要的。 您可以自由地重新排序更新列列表。
  2. 当值顺序有问题时,您可以替换带括号的语法来代替逗号分隔的
  3. column=new_value
  4. 对。
    您可以通过将其寻址为 
  5. insert
  6. 来重复使用
    excluded.media_url
    负载中的值:
    demo at db<>fiddle
    prepare insert_s(bigint,text) as INSERT INTO my_schema.user_profile (user_id, media_url) VALUES ($1, $2) ON CONFLICT (user_id) DO UPDATE SET ( updated_at, media_url ) = ( CURRENT_TIMESTAMP(0) AT TIME ZONE 'UTC', excluded.media_url ) RETURNING *; execute insert_s(1,'example.com/a_completely_new_pic.jpg');
    
    
    id1
    用户ID 媒体网址 创建于 更新于
    1 example.com/a_completely_new_pic.jpg 2023-12-07 13:53:14.593296 2023-12-07 13:53:15
© www.soinside.com 2019 - 2024. All rights reserved.