bca*_*tle 6 postgresql datatypes view functions set-returning-functions
我想编写一个 PostgreSQL 函数,它返回一个表和一个附加列。有没有办法在不手动指定的情况下做到这一点RETURNS TABLE (col1 type, col2 type, ...)
?
例如,考虑以下函数:
CREATE FUNCTION get_users_with_most_videos_since_time(ts TIMESTAMPTZ)
RETURNS SETOF "user" AS $$
SELECT
u.*,
count(v.id) AS vids_since
FROM "user" AS u
INNER JOIN "video" AS v ON v.creator_id = u.id
WHERE v.created_at > ts
GROUP BY u.id
ORDER BY vids_since DESC;
$$ LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)
这失败并出现错误:
Run Code Online (Sandbox Code Playgroud)ERROR: return type mismatch in function declared to return "user" DETAIL: Final statement returns too many columns.
公平地说,我们包括了该vids_since
列,该列不存在于"user"
表中。
因此,要解决此问题,我想将其更改为:
CREATE FUNCTION get_users_with_most_videos_since_time(ts TIMESTAMPTZ)
RETURNS
TABLE (<<< all columns from table "user" >>>, vids_since BIGINT)
AS $$
...
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点而不必在"user"
此处重新复制表的整个架构?
AIUI,您的愿望是缩短RETURNS
函数的子句。不确定您是否想同时建立对表的行类型的依赖关系,但这在这里也是有意义的。
该表单RETURNS SETOF
rettype
依赖于存储在系统目录中的使用类型。手册:
返回类型可以是基类型、复合类型或域类型,也可以引用表列的类型。
因此,只需在系统中注册您想要的行类型(一次)。您可以使用 显式创建复合类型CREATE TYPE
。或者您可以通过创建另一个表、视图或物化视图来隐式地执行此操作。即使只是临时函数的临时视图或表(在会话结束时死亡)。就像@Abelisto 评论的那样:
CREATE VIEW user_plus AS
SELECT *, null::bigint AS vids_since
FROM "user"
WHERE false;
Run Code Online (Sandbox Code Playgroud)
但是,被解析为视图创建时的SELECT *
列列表(“早期绑定”)。如果您稍后向基础表添加列,则视图及其行类型不会更新,并且在执行函数时会出现另一种类型不匹配的情况。但是,尝试从基础表中删除列会抱怨视图中依赖于它的列。你必须改变观点和功能。
顺便说一句,您的功能可以简化且更快:
CREATE FUNCTION get_users_with_most_videos_since_time(_ts timestamptz)
RETURNS SETOF user_plus AS
$func$
SELECT * -- effectively the same as: u.*, v.vids_since
FROM "user" AS u
JOIN ( -- aggregate *before* you join
SELECT creator_id AS id, count(*) AS vids_since -- note the column alias
FROM video v
WHERE created_at > _ts
GROUP BY 1
) v USING (id) -- USING only retains one id column
ORDER BY v.vids_since DESC;
$func$ LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)
拥有这个功能实际上是有意义的。您想要按结果中未包含的列进行过滤。普通的VIEW
.
旁白:我不鼓励使用像user这样的保留字作为标识符。那是一把上了膛的步枪。
归档时间: |
|
查看次数: |
4380 次 |
最近记录: |