在 Postgres 中处理参数化更新插入查询

问题描述 投票: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
将开始抱怨查询的更新部分更新的列数多于提供的参数化列数。

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

node.js postgresql node-postgres
1个回答
0
投票
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. 您可以通过将其寻址为
    insert
    来重复使用
    excluded.media_url
    负载中的值。
© www.soinside.com 2019 - 2024. All rights reserved.