我想循环查询,但也保留下一个循环的实际记录,所以我可以比较两个相邻的行。
CREATE OR REPLACE FUNCTION public.test ()
RETURNS void AS
$body$
DECLARE
previous RECORD;
actual RECORD;
query TEXT;
isdistinct BOOLEAN;
tablename VARCHAR;
columnname VARCHAR;
firstrow BOOLEAN DEFAULT TRUE;
BEGIN
tablename = 'naplo.esemeny';
columnname = 'esemeny_id';
query = 'SELECT * FROM ' || tablename || ' LIMIT 2';
FOR actual IN EXECUTE query LOOP
--do stuff
--save previous record
IF NOT firstrow THEN
EXECUTE 'SELECT ($1).' || columnname || ' IS DISTINCT FROM ($2).' || columnname
INTO isdistinct USING previous, actual;
RAISE NOTICE 'previous: %', previous.esemeny_id;
RAISE NOTICE 'actual: %', actual.esemeny_id;
RAISE NOTICE 'isdistinct: %', isdistinct;
ELSE
firstrow = false;
END IF;
previous = actual;
END LOOP;
RETURN;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
表格:
CREATE TABLE naplo.esemeny (
esemeny_id SERIAL,
felhasznalo_id VARCHAR DEFAULT "current_user"() NOT NULL,
kotesszam VARCHAR(10),
idegen_azonosito INTEGER,
esemenytipus_id VARCHAR(10),
letrehozva TIMESTAMP WITHOUT TIME ZONE DEFAULT now() NOT NULL,
szoveg VARCHAR,
munkalap_id VARCHAR(13),
ajanlat_id INTEGER,
CONSTRAINT esemeny_pkey PRIMARY KEY(esemeny_id),
CONSTRAINT esemeny_fk_esemenytipus FOREIGN KEY (esemenytipus_id)
REFERENCES naplo.esemenytipus(esemenytipus_id)
ON DELETE RESTRICT
ON UPDATE RESTRICT
NOT DEFERRABLE
)
WITH (oids = true);
上面的代码不起作用,抛出以下错误消息:
ERROR: could not identify column "esemeny_id" in record data type
LINE 1: SELECT ($1).esemeny_id IS DISTINCT FROM ($2).esemeny_id
^
QUERY: SELECT ($1).esemeny_id IS DISTINCT FROM ($2).esemeny_id
CONTEXT: PL/pgSQL function "test" line 18 at EXECUTE statement
LOG: duration: 0.000 ms statement: SET DateStyle TO 'ISO'
我错过了什么?
免责声明:我知道代码没有多大意义,我只是创建了所以我可以证明这个问题。
答案 0 :(得分:2)
这并不能直接回答你的问题,也可能完全无用,因为你并没有真正描述你的最终目标。
如果最终目标是能够将当前行中列的值与前一行中相同列的值进行比较,那么使用窗口查询可能会好得多:
SELECT actual, previous
FROM (
SELECT mycolumn AS actual,
lag(mycolumn) OVER () AS previous
FROM mytable
ORDER BY somecriteria
) as q
WHERE previous IS NOT NULL
AND actual IS DISTINCT FROM previous
此示例打印当前行与上一行不同的行。
请注意,我添加了一个ORDER BY子句 - 谈论"前一行"是没有意义的。没有指定排序,否则你会得到随机结果。
这是普通的SQL,而不是PlPgSQL,但如果你想动态生成查询,可以将它包装在一个函数中。
答案 1 :(得分:1)
我很确定,您的实际问题有更好的解决方案。但回答问题,这是一个多态类型的解决方案:
主要问题是您需要众所周知的复合类型才能使用。在分配之前,匿名记录的结构是未定义的。
CREATE OR REPLACE FUNCTION public.test (actual anyelement, _col text
, OUT previous anyelement) AS
$func$
DECLARE
isdistinct bool;
BEGIN
FOR actual IN
EXECUTE format('SELECT * FROM %s LIMIT 3', pg_typeof(actual))
LOOP
EXECUTE format('SELECT ($1).%1$I IS DISTINCT FROM ($2).%1$I', _col)
INTO isdistinct
USING previous, actual;
RAISE NOTICE 'previous: %; actual: %; isdistinct: %'
, previous, actual, isdistinct;
previous := actual;
END LOOP;
previous := NULL; -- reset dummy output (optional)
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT public.test(NULL::naplo.esemeny, 'esemeny_id')
我滥用OUT
参数,因为无法使用多态复合类型声明其他变量(至少我反复失败)。
如果您的列名称稳定,则可以使用简单表达式替换第二个EXECUTE
。
我的时间不多了,在这些相关答案中有解释:
旁白:
WITH (oids = true)
在你的桌子上吗?这仍然是允许的,但在现代Postgres中基本上已被弃用。