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
将开始抱怨查询的更新部分更新的列数多于提供的参数化列数。
我怎样才能让这样的东西发挥作用?
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);
update
子句中发生的 on conflict
的范围已经仅限于冲突行的上下文,它不是一个成熟的、独立的
update
,您必须专门针对才能获得在那里,所以 where
(现已删除)是不必要的。 您可以自由地重新排序更新列列表。
column=new_value
insert
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');
用户ID | 媒体网址 | 创建于 | 更新于 | |
---|---|---|---|---|
1 | example.com/a_completely_new_pic.jpg | 2023-12-07 13:53:14.593296 | 2023-12-07 13:53:15 |