可写CTE被认为是9.5之前UPSERT的一种解决方案,如在PostgreSQL中重复更新时插入所述?
可以使用以下可写CTEs惯用语执行UPSERT,其中包含的信息是作为更新还是插入结束的:
WITH
update_cte AS (
UPDATE t SET v = $1 WHERE id = $2 RETURNING 'updated'::text status
),
insert_cte AS (
INSERT INTO t(id, v) SELECT $2, $1 WHERE NOT EXISTS
(SELECT 1 FROM update_cte) RETURNING 'inserted'::text status
)
(SELECT status FROM update_cte) UNION (SELECT status FROM insert_cte)
此查询将返回“更新”或“插入”,或者可能(很少)失败,违反了https://dba.stackexchange.com/questions/78510/why-is-cte-open-to-lost-updates中描述的约束
使用PostgreSQL 9.5新的“UPSERT”语法可以实现类似的功能吗?它可以从优化中获益,并避免可能的约束冲突?
在SQLServer
MERGE
语句中有返回字符串INSERT、UPDATE或DELETE的$action
。
对于Postgresql
,我找不到对返回的
执行类似操作的函数/变量。
一种解决方法是将列
is_updated
添加到表中:
DROP TABLE IF EXISTS tab;
CREATE TABLE tab(id INT PRIMARY KEY, col VARCHAR(100),
is_updated BOOLEAN DEFAULT false);
INSERT INTO tab(id, col) VALUES (1,'a'), (2, 'b');
-- main query
INSERT INTO tab(id, col)
VALUES (3, 'c'), (4, 'd'), (1,'aaaa')
ON CONFLICT (id) DO UPDATE SET col = EXCLUDED.col, is_updated = true
RETURNING id,col,
CASE WHEN is_updated THEN 'UPDATED' ELSE 'INSERTED' END AS action;
Rextester演示
输出:
╔════╦══════╦══════════╗
║ id ║ col ║ action ║
╠════╬══════╬══════════╣
║ 3 ║ c ║ INSERTED ║
║ 4 ║ d ║ INSERTED ║
║ 1 ║ aaaa ║ UPDATED ║
╚════╩══════╩══════════╝
根据@lad2025的答案,可以通过滥用设置和自定义选项,以及WHERE子句中的相关功能来获得所需的副作用。
CREATE TABLE t(id INT PRIMARY KEY, v TEXT);
INSERT INTO t (id, v)
SELECT $1, $2
WHERE 'inserted' = set_config('upsert.action', 'inserted', true)
ON CONFLICT (id) DO UPDATE
SET v = EXCLUDED.v
WHERE 'updated' = set_config('upsert.action', 'updated', true)
RETURNING current_setting('upsert.action') AS "upsert.action";
set_config
的第三个参数是is_local
:true
表示该设置将在事务结束时消失。更准确地说,current_setting('upsert.action')
将在会话结束前返回NULL(而不是抛出错误)。
我相信xmax::文本::int
so=# DROP TABLE IF EXISTS tab;
NOTICE: table "tab" does not exist, skipping
DROP TABLE
so=# CREATE TABLE tab(id INT PRIMARY KEY, col text);
CREATE TABLE
so=# INSERT INTO tab(id, col) VALUES (1,'a'), (2, 'b');
INSERT 0 2
so=# INSERT INTO tab(id, col)
VALUES (3, 'c'), (4, 'd'), (1,'aaaa')
ON CONFLICT (id) DO UPDATE SET col = EXCLUDED.col
returning *,case when xmax::text::int > 0 then 'updated' else 'inserted' end,ctid;
id | col | case | ctid
----+------+----------+-------
3 | c | inserted | (0,3)
4 | d | inserted | (0,4)
1 | aaaa | updated | (0,5)
(3 rows)
INSERT 0 3
so=# INSERT INTO tab(id, col)
VALUES (3, 'c'), (4, 'd'), (1,'aaaa')
ON CONFLICT (id) DO UPDATE SET col = EXCLUDED.col
returning *,case when xmax::text::int > 0 then 'updated' else 'inserted' end,ctid;
id | col | case | ctid
----+------+---------+-------
3 | c | updated | (0,6)
4 | d | updated | (0,7)
1 | aaaa | updated | (0,8)
(3 rows)
INSERT 0 3
问题内容: 我有一个需要用户输入密码的应用程序。 我想要做的是从控制台读取密码(如果操作系统支持unix)或显示JOptionPane并要求用户输入密码(如果操作系统支持图形界面(例如Windows))。 有人可能会争辩说,在上述两种情况下控制台始终可用,因此控制台输入就足够了。但是问题是,如果Java应用程序开始使用javaw.exe,则控制台不可用。因此,我需要一种方法来确定我是否可以做任何一
问题内容: 假设我有2个结构: 我想反映扩展结构来获取它的领域: 问题答案: 只需检查值的Kind()
汤姆教他的学生求一个数的阶乘。他想测试学生的理解力。为此,他提供了一个数字。他希望学生们告诉他这个数是哪个数的阶乘。 示例:如果Tom提供的数字为120,学生应该回答为5,因为5!=120。 通过编写一个程序来帮助学生做到这一点。请注意,输入应该是一个大于零的数字。如果输入小于或等于零,则输出应该是“无效输入”。此外,如果提供的输入不完全是一个数字的阶乘,例如,提供的输入是122,这不是一个数字的
问题内容: 我如何断言页面的CSS已在Watin 2.1中成功加载并应用了其样式? 问题答案: 在进行了一些研究并写下我的答案之后,我偶然发现了该链接,该链接解释了您需要了解的有关CSS的所有信息,何时加载CSS以及如何检查CSS。 实际上,所提供的链接对它的解释很好,以至于我在其中添加了一些引用以供将来参考。 如果您好奇,我的答案将是#2和#4的变体。 何时真正加载样式表? … 顺便说一句,让我
问题内容: 在JMS中,很容易找出连接是否丢失,是否发生异常。但是,如何确定连接是否再次存在? 场景:我使用JMS与服务器通信。现在我的连接断开了(服务器已关闭),这导致了异常。到目前为止,一切都很好。如果服务器再次启动并重新建立连接,我怎么知道? 我看不到任何可以提供此类信息的侦听器。 问题答案: 啊…旧的异常处理/重新连接难题。 有些传输提供程序将为您自动重新连接您的应用程序,而另一些传输提供
所以我有一个问题,当我计算一个数字时,比如说15,我必须显示这个:15=3x5,但我得到的是3x5x5,我不知道如何使它变成这样,所以它只显示3x5。还有一个问题是,我输入的数字是否是素数。有办法解决这个问题吗?我只需要这些,然后再编辑其他东西。