sql - 删除新 Feed 中不存在的旧行
问题描述
我有一个每天更新的数据提要,我需要将它插入到表格中。我想更新具有相同 id 但具有不同数据的行,添加不存在的数据并删除不再存在的行。我在最后一项任务中遇到问题,我似乎无法从以前的运行中删除新提要中不再存在的行。
这就是我所拥有的,带有一些测试数据的“列表”表:
INSERT INTO public.listings(
id, price, pub_date, rooms, publisher, updated_date)
VALUES
(1, 100, '2021-05-03', 3, 'mf', '2021-01-01'),
(2, 200, '2021-05-03', 4, 'pmf', '2021-01-01'),
(3, 300, '2021-05-04', 5, 'jorge', '2021-01-01'),
(4, 400, '2021-05-05', 3, 'yuyu', '2021-01-01'),
(5, 500, '2021-05-06', 3, 'papo', '2021-01-01');
一个新的插入子句(更新提要):
INSERT INTO listings AS p (id, price, pub_date, rooms, publisher, updated_date)
VALUES
(1, 125, '2021-04-30', 4, 'mf', '2021-10-30')
, (2, 200, '2021-05-03', 4, 'pmf', '2021-01-01')
, (6, 250, '2021-04-30', 3, 'mf', '2021-10-30')
ON CONFLICT (id) -- simple clause
DO UPDATE
SET pub_date = EXCLUDED.pub_date
, price = EXCLUDED.price
, rooms = EXCLUDED.rooms
, updated_date = EXCLUDED.updated_date
WHERE (p.pub_date, p.price, p.rooms, p.updated_date) IS DISTINCT FROM
(EXCLUDED.pub_date, EXCLUDED.price, EXCLUDED.rooms, EXCLUDED.updated_date);
这是触发器:
CREATE OR REPLACE FUNCTION trg_prop_backup()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
INSERT INTO old_listings
VALUES (OLD.*);
DELETE FROM listings --this sentence generates an error on id duplicity
WHERE listings.id = OLD.id;
RETURN NEW;
END
$func$;
CREATE TRIGGER prop_listings_upd_bef
BEFORE UPDATE OR DELETE ON listings
FOR EACH ROW EXECUTE FUNCTION trg_prop_backup();
这已经适用于更新现有行并插入新行,但它不适用于更新提要中不再存在的行。有些事情我做错了(或没有做),但我似乎无法提出解决方案。
“old_listings”表包含新提要中不存在的行,因为数据已更新或删除。
运行两个插入查询的结果必须是(对于列表表):
(1, 125, '2021-04-30', 4, 'mf', '2021-10-30')
, (2, 200, '2021-05-03', 4, 'pmf', '2021-01-01')
, (6, 250, '2021-04-30', 3, 'mf', '2021-10-30')
和 old_listings 表:
(1, 100, '2021-05-03', 3, 'mf', '2021-01-01'),
(3, 300, '2021-05-04', 5, 'jorge', '2021-01-01'),
(4, 400, '2021-05-05', 3, 'yuyu', '2021-01-01'),
(5, 500, '2021-05-06', 3, 'papo', '2021-01-01');
解决方案
这是我的建议:
series_ts
在表中添加一个额外的时间戳字段,并在插入或更新时将listings
其值设置为;current_timestamp
- 删除查询的
where
子句,insert on conflict update
以便series_ts
即使对于等效记录也会更新; - 使用插入查询删除同一事务中不等于的所有
listings
记录。series_ts
current_timestamp
为了做到这一点,首先创建一个执行此函数的“在插入或更新每一行之前”触发器:
create function set_listings_series_ts() returns trigger language plpgsql as $$
begin
new.series_ts := current_timestamp;
return new;
end; $$;
完成后运行:
BEGIN TRANSACTION;
INSERT INTO listings AS p (id, price, pub_date, rooms, publisher, updated_date)
VALUES
(1, 125, '2021-04-30', 4, 'mf', '2021-10-30')
, (2, 200, '2021-05-03', 4, 'pmf', '2021-01-01')
, (6, 250, '2021-04-30', 3, 'mf', '2021-10-30')
ON CONFLICT (id) -- simple clause
DO UPDATE
SET pub_date = EXCLUDED.pub_date
, price = EXCLUDED.price
, rooms = EXCLUDED.rooms
, updated_date = EXCLUDED.updated_date; -- your query w/o WHERE
WITH t as
(
delete from listings
where series_ts < current_timestamp
returning *
)
insert into old_listings select * from t; -- delete old data, save in old_listings
COMMIT TRANSACTION;
如果您更改“插入...更新”查询,您也可以使用 oa 触发器执行此操作。
推荐阅读
- python - 带有 TypeError 的 Tkinter 回调中的异常
- javascript - 更改网页中的日期格式
- html - Django:无法更新 CSS 更改
- keras - 为什么我的模型的训练和验证准确度在一个 epoch 之后保持不变?[凯拉斯]
- compiler-errors - 推力集差异无法通过从 __host__ __device__ 函数调用 __host__ 函数进行编译是不允许的
- docker - 在 Docker 撰写文件中定义任务
- python - 从数学绘图库窗口中提取图像 (jpg)
- visualization - 可视化强化学习代理的进度
- postgresql-11 - 错误:运算符不存在:字符 <> 整数
- c++ - 为什么这些源代码(C++)为化学反应提供了不同的结果?