我已经找到答案,但没找到.
所以我有一张桌子 types
CREATE TABLE types
(
type_id serial NOT NULL,
type_name character varying,
CONSTRAINT un_type_name UNIQUE (type_name)
)
Run Code Online (Sandbox Code Playgroud)
其中包含类型名称,让我们说users- 这是相应表的名称users.这个设计可能有点难看,但它是为了让用户创建自己的类型.(有更好的方法可以解决这个问题吗?)
现在我想执行像这样的查询:
select type_name, (select count(*) from ???) from types
Run Code Online (Sandbox Code Playgroud)
获取每种类型的所有类型名称和对象的列表.
可以这样做吗?
你不能直接在SQL中做到这一点
您可以使用PLpgSQL函数和动态SQL
CREATE OR REPLACE FUNCTION tables_count(OUT type_name character varying, OUT rows bigint)
RETURNS SETOF record AS $$
BEGIN
FOR tables_count.type_name IN SELECT types.type_name FROM types
LOOP
EXECUTE 'SELECT COUNT(*) FROM ' || quote_ident(tables_count.type_name) INTO tables_count.rows;
RETURN NEXT;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM tables_count();
Run Code Online (Sandbox Code Playgroud)
我没有足够的信息,但我确实怀疑您的设计有问题。您不应该为每种类型都需要一个额外的表。
尽管如此,您想要做的事情无法完成 - 在纯 SQL 中。不过,它可以通过执行动态 SQL 的 plpgsql 函数来完成:
CREATE OR REPLACE FUNCTION f_type_ct()
RETURNS TABLE (type_name text, ct bigint) AS
$BODY$
DECLARE
tbl text;
BEGIN
FOR tbl IN SELECT t.type_name FROM types t ORDER BY t.type_name
LOOP
RETURN QUERY EXECUTE
'SELECT $1, count(*) FROM ' || tbl::regclass
USING tbl;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
称呼:
SELECT * FROM f_type_ct();
Run Code Online (Sandbox Code Playgroud)
您需要学习手册中有关 plpgsql 的大部分章节,以了解这里发生的事情。
一个特别提示:强制转换regclass为防止 SQLi。您也可以使用更普遍适用quote_ident()的方法,但这不能正确处理模式限定的表名,而强制转换regclass则可以。它还只接受调用用户可见的表名。