【发布时间】:2021-10-05 07:19:54
【问题描述】:
我有一个问题,我想使用 SQL 查询和触发器消除不相关的信息
表是
create table z_test(id, fyear smallint, byear text);
要插入的数据。
insert into z_test (fyear, byear) values (Null, '2018 2019 2020');
insert into z_test (fyear, byear) values (null, '2018 2019 2020');
insert into z_test (fyear, byear) values (null, '2018 2019 2020');
问题定义:我希望第一行的 fyear 为 2018,第二行的 fyear 为 2019, 2020 年为第三排。如果我插入的行数等于年数 在byear,它应该被插入。如果不相等,则可以将 Null 插入 fyear
另外,我也可以获得这样的数据。
insert into z_test (fyear, byear) values (Null, '2018 2019 ');
insert into z_test (fyear, byear) values (null, '2018 2019 ');
在这种情况下,2018 应该是第一行,2019 应该是第二行。
到目前为止我已经尝试过。试图在插入 z_test 的触发器中创建 CTE。里面 触发器,我使用 regexp_split_to_table 将 byear 拆分为行。然后我尝试把第一个 第一行是一年,第二行是第二年,以此类推。我正在使用事务和 psycopg2。不幸的是,问题是触发器无法在表中找到以前未提交的行,我被困在这里。请帮忙。所以所有值都为空。有没有办法使用 SQL 查询,最好是触发器?
CREATE TRIGGER z_test_trigger
AFTER INSERT
ON public.z_test
FOR EACH ROW
EXECUTE PROCEDURE public.z_test_procedure();
CREATE FUNCTION public.z_test_procedure()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
WITH cte AS(
select numyr::SMALLINT,byear from
(select trim(regexp_split_to_table(NEW.ner_text, '\s+')) AS numyr
)x where is_numeric(numyr) =true and length(numyr)=4 and numyr like '20%' )
SELECT numyr INTO NEW.fyear FROM cte WHERE numyr NOT IN (SELECT byear FROM z_test WHERE
NEW.byear = cte.byear ) LIMIT 1 ;
RETURN NEW;
END;
$BODY$;
【问题讨论】:
-
解决方案是清理
INSERT之前的数据。一个函数在它自己的事务中运行,它不会像你发现的那样在其他事务中看到未提交的信息。 -
它是单个事务的一部分。我将行作为单个事务的一部分插入到表中。我可以忽略我没有插入的其他交易,因为这将是一个完全不同的过程。我的问题是,为什么触发器没有“看到”我之前插入的数据,即使它是同一个事务? Postgre 文档“Read Committed 是 PostgreSQL 中的默认隔离级别。...但是,SELECT 确实会看到在其自己的事务中执行的先前更新的影响,即使它们尚未提交。”
-
对于初学者来说,它是
AFTER TRIGGER,所以RETURN NEW;无效。见plpgsql trigger。
标签: sql postgresql triggers