How to merge two tables with possible NULL values in the UNIQUE index?
如何合并(upsert& delete orphan rows)到
1 2 3 4 5 6 7 8 9 10 11 12 13 | +---------+--------+----------+-------+ | company | OPTION | category | rates | +---------+--------+----------+-------+ | a | f | NULL | 2.5 | +---------+--------+----------+-------+ | a | f | d | 2 | * +---------+--------+----------+-------+ | a | g | e | 3 | ** +---------+--------+----------+-------+ | c | g | e | 4 | +---------+--------+----------+-------+ | d | f | d | 1 | +---------+--------+----------+-------+ |
仅触摸
1 2 3 4 5 6 7 8 9 | +---------+--------+----------+-------+ | company | OPTION | category | rates | +---------+--------+----------+-------+ | a | f | NULL | 2.5 | +---------+--------+----------+-------+ | a | g | e | 4 | +---------+--------+----------+-------+ | c | g | e | 4 | +---------+--------+----------+-------+ |
两个表中的
期望的结果
1 2 3 4 5 6 7 8 9 10 11 | +---------+--------+----------+-------+ | company | OPTION | category | rates | +---------+--------+----------+-------+ | a | f | NULL | 2.5 | +---------+--------+----------+-------+ | a | g | e | 4 | <- +---------+--------+----------+-------+ | c | g | e | 4 | +---------+--------+----------+-------+ | d | f | d | 1 | +---------+--------+----------+-------+ |
对于
这是一个小提琴:https://rextester.com/QUVC30763
我想先用这个删除孤儿行:
1 2 3 4 5 6 7 8 9 10 11 | DELETE FROM tableA USING tableB WHERE -- ignore rows with IDs that don't exist in tableB tableA.company = tableB.company -- ignore rows that have an exact all-column match in tableB AND NOT EXISTS (SELECT * FROM tableB WHERE tableB.company IS NOT DISTINCT FROM tableA.company AND tableB.option IS NOT DISTINCT FROM tableA.option AND tableB.category IS NOT DISTINCT FROM tableA.category ); |
然后用这个upsert:
1 2 3 4 5 6 7 8 9 | INSERT INTO tableA (company, OPTION, category, rates) SELECT company, OPTION, category, rates FROM tableB ON CONFLICT (company, OPTION, category) DO UPDATE SET rates= EXCLUDED.rates WHERE tableA.rates IS DISTINCT FROM EXCLUDED.rates; |
但upsert函数的问题在于它无法处理可空字段。我必须设置
注意:我发现
- 在PostgreSQL 9.5上制作MERGE
但我没有看到适合我的情况的查询。而且我不确定是否可以使用可空字段。因此问题是:
是否有一种与可空字段合并的简洁方法?
我认为你走的是正确的道路。但
列
也就是说,
1 2 3 4 5 6 7 8 9 10 | DELETE FROM tableA a WHERE EXISTS ( SELECT FROM tableB b WHERE a.company = b.company ) AND NOT EXISTS ( SELECT FROM tableB b WHERE (a.company, a.option, a.category) IS NOT DISTINCT FROM (b.company, b.option, b.category) ); |
如果您坚持使用
For
ON CONFLICT DO NOTHING , it is optional to specify a
conflict_target ; when omitted, conflicts with all usable constraints
(and unique indexes) are handled. ForON CONFLICT DO UPDATE , a
conflict_target must be provided.
但是,如果您使用工作
并确保没有并发写入表或您可能面临竞争条件和/或死锁,除非您做更多...