提问人:Nicholas Chiang 提问时间:9/6/2021 最后编辑:Erwin BrandstetterNicholas Chiang 更新时间:9/6/2021 访问量:901
扩展现有 PostgreSQL 类型
Extend existing PostgreSQL type
问:
是否可以在 PostgreSQL 中扩展现有数据类型?从本质上讲,我想要这个 TypeScript 的等效项,但在 SQL 中:
interface Meeting {
id: number;
start: Date;
end: Date;
description: string;
}
interface ServiceHour extends Meeting {
total: number;
hours: number;
}
因为我有一个函数,它返回表中的所有列,然后返回在查询时计算的另外两列和列。下面是该函数的样子:meetings
total
hours
create or replace function user_hours(org_id text, user_id text)
returns table (like meeting_instances)
as $$
select (sum(hours) over (order by _.instance_time)) total, * from (
select
extract(epoch from ((meeting_instances.time).to - (meeting_instances.time).from)) / 60 / 60 as hours,
meeting_instances.*
from meeting_instances inner join relation_people on relation_people.meeting = meeting_instances.id
where relation_people.user = user_id
and meeting_instances.org = org_id
and meeting_instances.instance_time <= current_date
) as _;
$$
language sql stable;
现在,我收到一个类型不匹配错误,因为与包含列和两个新和列的表不同。我希望能够做的是这样的事情(显然下面的语法实际上并不存在......但我不确定是否有另一种方法可以使用类似的速记语法来做到这一点):table (like meeting_instances)
meeting_instances
hours
total
returns table (total float, hours float, meeting_instances.*)
returns table (total float, hours float) intersect (like meeting_instances)
returns table (total float, hours float) extends (like meeting_instances)
我目前的解决方法是创建一个视图,然后让该函数简单地查询该视图并返回视图的类型。
答:
对于您的核心问题:
是否可以扩展现有数据类型?
不,不可能。不在 的子句中,在 PostgreSQL 中的其他任何地方都不行,直到版本 14。RETURNS
CREATE FUNCTION
您可以返回复合类型的字段,以及任何类型的其他字段。但这有微妙的不同:
CREATE FUNCTION user_hours_plus( ...)
RETURNS TABLE (my_meeting meeting_instances, hours numeric, total numeric) ...
使用以下命令调用该函数:
SELECT * FROM user_hours_plus('a', 'b');
返回嵌套复合类型作为返回列之一,例如:
(1,"2017-01-03","2017-01-04", foo) | 123 | 345
若要分解复合类型,可以使用以下命令进行调用:
SELECT (my_meeting).*, hours, total FROM user_hours_plus('a', 'b');
但我不会去那里。
我目前的解决方法是创建一个视图,然后让该函数简单地查询该视图并返回视图的类型。
然后只需使用视图。不要在其上创建其他函数。案件已结案。
如果你真的想说:
...然后在函数的
RETURNS
子句中使用视图的行类型
然后我们回到你的问题。CREATE VIEW
以(隐式)注册扩展行类型是一个有效的选项 - 特别是因为它是 had 情况的方便语法简写。但对于初学者来说,SELECT *
RETURNS TABLE (LIKE meeting_instances)
...未记录 CREATE FUNCTION
的语法。没有人应该使用它。可能会在下一个版本之一中删除,恕不另行通知。
规范的、等效的、记录的语法是:
RETURNS SETOF meeting_instances
(与 some_table 一样)
是 CREATE TABLE
的语法记录。CREATE FUNCTION
的 RETURNS
子句目前支持相同的内容,但未记录在案,因此请勿使用它。
返回到创建 .如果除了注册该扩展行类型之外没有使用 ,请考虑改用 CREATE TYPE
。不幸的是,也不允许语法。您必须拼出复合类型的所有列(属性)。喜欢:VIEW
VIEW
CREATE TYPE
LIKE other_type
CREATE TYPE meeting_plus AS (
id numeric
, start date
, "end" date
, description text
, total numeric
, hours numeric
);
然后,您可以使用:
RETURNS SETOF meeting_plus
就像你想要的一样。
但是对于一个函数,我会改用并拼写出返回类型:RETURNS TABLE()
RETURNS TABLE (
id numeric
, start date
, "end" date
, description text
, total numeric
, hours numeric)
哦,我不会在Postgres中使用“start”和“end”作为标识符。两者都是标准 SQL 中的保留字。“end”在 Postgres 中是绝对保留的,并且必须始终用双引号引起来。
评论
CREATE TABLE ...
LIKE
RETURNS
RETURNS (LIKE tbl)
meeting_instances.time
已经是嵌套复合类型。我们不知道兔子洞有多深。