这并不完美,但它确实有效。这三个案例(删除、更新、插入)可能会组合成一个完整的外连接。
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE table_a (
zkey INTEGER NOT NULL PRIMARY KEY
, zvalue varchar NOT NULL
, CONSTRAINT a_zvalue_alt UNIQUE (zvalue)
);
INSERT INTO table_a(zkey, zvalue) VALUES
(1, 'dave' )
,(2, 'paul' )
,(3, 'michael' )
;
CREATE TABLE table_b (
zkey INTEGER NOT NULL PRIMARY KEY
, zvalue varchar NOT NULL
, CONSTRAINT b_zvalue_alt UNIQUE (zvalue)
);
INSERT INTO table_b(zkey, zvalue) VALUES
(1, 'dave' )
,(2, 'chris' )
,(5, 'Arnold' )
;
CREATE TABLE table_diff (
zkey INTEGER NOT NULL
, zvalue varchar NOT NULL
, opcode INTEGER NOT NULL DEFAULT 0
);
WITH xx AS (
DELETE FROM table_a aa
WHERE NOT EXISTS (
SELECT * FROM table_b bb
WHERE bb.zkey = aa.zkey
)
RETURNING aa.zkey, aa.zvalue
)
INSERT INTO table_diff(zkey,zvalue,opcode)
SELECT xx.zkey, xx.zvalue, -1
FROM xx
;
SELECT * FROM table_diff;
WITH xx AS (
UPDATE table_a aa
SET zvalue= bb.zvalue
FROM table_b bb
WHERE bb.zkey = aa.zkey
AND bb.zvalue <> aa.zvalue
RETURNING aa.zkey, aa.zvalue
)
INSERT INTO table_diff(zkey,zvalue,opcode)
SELECT xx.zkey, xx.zvalue, 0
FROM xx
;
SELECT * FROM table_diff;
WITH xx AS (
INSERT INTO table_a (zkey, zvalue)
SELECT bb.zkey, bb.zvalue
FROM table_b bb
WHERE NOT EXISTS (
SELECT * FROM table_a aa
WHERE bb.zkey = aa.zkey
AND bb.zvalue = aa.zvalue
)
RETURNING zkey, zvalue
)
INSERT INTO table_diff(zkey,zvalue,opcode)
SELECT xx.zkey, xx.zvalue, 1
FROM xx
;
SELECT * FROM table_a;
SELECT * FROM table_b;
SELECT * FROM table_diff;
结果:
INSERT 0 3
CREATE TABLE
INSERT 0 1
zkey | zvalue | opcode
------+---------+--------
3 | michael | -1
(1 row)
INSERT 0 1
zkey | zvalue | opcode
------+---------+--------
3 | michael | -1
2 | chris | 0
(2 rows)
INSERT 0 1
zkey | zvalue
------+--------
1 | dave
2 | chris
5 | Arnold
(3 rows)
zkey | zvalue
------+--------
1 | dave
2 | chris
5 | Arnold
(3 rows)
zkey | zvalue | opcode
------+---------+--------
3 | michael | -1
2 | chris | 0
5 | Arnold | 1
(3 rows)
顺便说一句:OQ 对要求非常模糊。如果 table_diff 是一个实际的历史表,则至少应该添加一个时间戳列,并且 zkey 和 ztimestamp 将是键的自然选择。此外,整个过程可以包含在一组规则或触发器中。