我try 在Postgres 16.2中使用MERGE语句,您可以找到以下示例:

MERGE INTO schema1.target_table AS t
USING schema2.source_table AS s
ON t.id = s.id
WHEN MATCHED THEN
    UPDATE SET
        data1 = s.data1,
        data2 = s.data2
WHEN NOT MATCHED BY TARGET
    INSERT (id, data1, data2,)
    VALUES (s.id, s.data1, s.data2)
WHEN NOT MATCHED BY SOURCE
    DELETE;

在try 此查询时,我发现Postgres从版本15开始就支持MERGE语句,但它不支持"BY TARGET"或"BY SOURCE"语句,从而引发以下错误:

SyntaxError: syntax error at or near "BY"
LINE 8: WHEN NOT MATCHED BY TARGET

在我寻找更Clean 替代品以实现同样的结果时,我遇到了这helpful but old answer个.虽然它工作得很好,但我发现它有点难以理解,我宁愿避免它,以保持我的代码尽可能干净.

你知道有什么方法可以用更干净的方式达到同样的效果吗?

推荐答案

你没有说old querynot clean,但这里有一个替代方案:demo

with cte as (
  delete from schema1.target_table 
  where id not in (select id from schema2.source_table) )
insert into schema1.target_table
table schema2.source_table
on conflict(id) do update set data1=excluded.data1,
                              data2=excluded.data2;

原理保持不变:这是一个老式的PostgreSQLupsert,用CTE来代替non-standard WHEN NOT MATCHED BY SOURCE extension found in Ms SQL Server.

the demo%中,你可以看到它们之间实际上几乎没有什么区别--如果你调整样本大小并重新排序测试,似乎这里相对于旧的测试的任何优势都归因于噪音.根据表的实际设置和索引方式,您可以调整这两者来执行反联接、exceptnot exists(也会导致散列的右反联接)等.

此外,将两个操作(删除+更新)包装在一个事务中与将它们粘合到一个语句中没有什么不同,但2in1当然更干净,使用起来也更方便一些.如果您考虑到不太容易出现与并发相关的错误,则会更安全.

DEMO还显示,@MatBailie‘S在一笔交易中立即从suggestiontruncate的速度可靠地快于这两种情况中的任何一种.就是warnedwhile it's transaction-safe, it's not MVCC-safe.

如果你决定不擦除和重新填充表,你可以考虑调整你的fillfactor storage parameter:默认是100,这样你的更新和插入就会转到新的页面.设置为50会使它们处于半空状态,并能够就地接受新的(版本的)行.我认为在加入这一点后,演示程序的执行时间缩短了25%.

Sql相关问答推荐

如何解决Error:operator is not unique:unknown—unknown在一个动态SQL查询?""""

如何用3个(半)固定位置建模团队,并有效地搜索相同/不同的团队?

SQL是否可以计算每年的所有日期变化?

R中对Arrow duckdb工作流的SQL查询

OVER子句WITH PARTITION BY和ORDER BY忽略主查询的WHERE子句

SQL:如何取上一年的平均值?

在SQL中为两个日期之间的每个日期添加行

SQL按日期分组字段和如果日期匹配则求和

按属性值 Select 数组元素Postgres Jsonb

我如何才能在付款人单列中拉出只有9个付款人单的人?

如果另一个表中不存在值列,则插入失败

用于SQL协助的XQUERY()

删除行而不使数据库超载

日期逻辑(查找过go 90 天内的第一个匹配行)

如何在TSQL中编写此窗口查询

删除重复记录但保留最新的SQL查询

Snowflake 中的对象是如何比较的?

如何在 PL/SQL 中区分返回的 XML 值?

聚合 Athena 中的列

从 Pyspark 转换为具有多个分组条件的语句时的情况