use*_*773 10 postgresql for-loop dynamic-sql plpgsql set-returning-functions
我是Postgres的新手,拥有一个具有相同结构的多个表的数据库.我需要从每个表中选择符合特定条件的数据.
我可以通过一堆UNION查询来做到这一点,但是我需要搜索的表的数量会随着时间的推移而改变,所以我不想像那样硬编码.我一直在尝试开发一个循环遍历特定表的函数(它们有一个共同的命名约定)并返回一个记录表,但是当我查询函数时,我没有得到任何结果.功能代码如下:
CREATE OR REPLACE FUNCTION public.internalid_formaltable_name_lookup()
RETURNS TABLE(natural_id text, name text, natural_id_numeric text) AS
$BODY$
DECLARE
formal_table text;
begin
FOR formal_table IN
select table_name from information_schema.tables
where table_schema = 'public' and table_name like 'formaltable%'
LOOP
EXECUTE 'SELECT natural_id, name, natural_id_numeric
FROM ' || formal_table ||
' WHERE natural_id_numeric IN (
select natural_id_numeric from internal_idlookup
where internal_id = ''7166571'')';
RETURN NEXT;
END LOOP;
Return;
END;
$BODY$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
我尝试使用该函数时没有收到任何错误,但它没有返回任何行:
SELECT * From internalid_formaltable_name_lookup();
Run Code Online (Sandbox Code Playgroud)
知道我哪里错了吗?
Erw*_*ter 18
CREATE OR REPLACE FUNCTION public.internalid_formaltable_name_lookup()
RETURNS TABLE(natural_id text, name text, natural_id_numeric text) AS
$func$
DECLARE
formal_table text;
BEGIN
FOR formal_table IN
SELECT quote_ident(table_name)
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name LIKE 'formaltable%'
LOOP
RETURN QUERY EXECUTE
'SELECT t.natural_id, t.name, t.natural_id_numeric
FROM internal_idlookup i
JOIN public.' || formal_table || ' t USING (natural_id_numeric)
WHERE i.internal_id = 7166571'; -- assuming internal_id is numeric
END LOOP;
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
您必须使用RETURN QUERY EXECUTE返回每组行.
EXECUTE,其次RETURN NEXT,不会做你似乎会发生什么,在所有.
您需要清理标识符.我在quote_ident()这里用.或者您的查询将破坏非标准标识符并允许SQL注入!
将您转换col IN (sub-select)为更高效的JOIN.
这与使用略有不同a bunch of UNION queries.它并不能去除重复行,和实际工作一样UNION ALL.
就个人而言,我宁愿在系统目录上构建它pg_class.细节:
然后,您可以自动使用pg_class.oid::regclassto escape和schema-qualify表名.细节:
但这取决于您的要求和品味的细节.