扩展现有的 PostgreSQL 类型

Nic*_*ang 5 sql postgresql create-function composite-types

是否可以扩展 PostgreSQL 中现有的数据类型?本质上,我想要这个 TypeScript 的等价物,但在 SQL 中:

interface Meeting {
  id: number;
  start: Date;
  end: Date;
  description: string;
}

interface ServiceHour extends Meeting {
  total: number;
  hours: number;
}
Run Code Online (Sandbox Code Playgroud)

因为我有一个函数,它返回表中的所有列,然后返回在查询时计算的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;
Run Code Online (Sandbox Code Playgroud)

现在,我收到类型不匹配错误,因为它与包含列两个新的和列的table (like meeting_instances)表不同。我想要做的是这样的事情(显然下面的语法实际上并不存在......但我不确定是否有另一种方法可以使用类似的简写语法来做到这一点):meeting_instanceshourstotal

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)
Run Code Online (Sandbox Code Playgroud)

我当前的解决方法是创建一个视图,然后让该函数简单地查询该视图并返回视图的类型。

Erw*_*ter 7

对于你的核心问题

是否可以扩展现有的数据类型?

,不可能。不在RETURNS的子句中CREATE FUNCTION,也不在 PostgreSQL 版本 14 之前的任何其他地方。

您可以返回复合类型的字段以及任何类型的其他字段。但这有微妙的不同:

CREATE FUNCTION user_hours_plus( ...)
  RETURNS TABLE (my_meeting meeting_instances, hours numeric, total numeric) ...
Run Code Online (Sandbox Code Playgroud)

使用以下命令调用该函数:

SELECT * FROM user_hours_plus('a', 'b');
Run Code Online (Sandbox Code Playgroud)

返回嵌套复合类型作为返回列之一,例如:

(1,"2017-01-03","2017-01-04", foo) | 123 | 345
Run Code Online (Sandbox Code Playgroud)

要分解复合类型,您可以调用:

SELECT (my_meeting).*, hours, total FROM user_hours_plus('a', 'b');
Run Code Online (Sandbox Code Playgroud)

但我不会去那里。

我当前的解决方法是创建一个视图,然后让该函数简单地查询该视图并返回视图的类型。

然后只需使用视图即可。不要在其之上创建附加函数。案件结案。

如果你真的想说:

RETURNS...然后在函数的子句中使用视图的行类型

然后我们回到你的问题。CREATE VIEW(隐式)注册扩展行类型是一个有效的选项 - 特别是因为SELECT *是 had 情况的方便语法简写。但对于初学者来说,

RETURNS TABLE (LIKE meeting_instances)
Run Code Online (Sandbox Code Playgroud)

...没有记录的语法CREATE FUNCTION没有人应该使用它。可能会在下一版本之一中被删除,恕不另行通知。
规范的、等效的、记录的语法是:

RETURNS SETOF meeting_instances
Run Code Online (Sandbox Code Playgroud)

(LIKE some_table)是记录的语法CREATE TABLERETURNS当前的子句支持CREATE FUNCTION相同的内容,但没有记录,所以不要使用它。

回到创建VIEW. VIEW如果您除了注册扩展行类型之外没有其他用处,请考虑CREATE TYPE改为使用。不幸的是,也CREATE TYPE不允许LIKE other_type语法。您必须拼写出复合类型的所有列(属性)。喜欢:

CREATE FUNCTION user_hours_plus( ...)
  RETURNS TABLE (my_meeting meeting_instances, hours numeric, total numeric) ...
Run Code Online (Sandbox Code Playgroud)

然后你可以使用:

RETURNS SETOF meeting_plus
Run Code Online (Sandbox Code Playgroud)

就像你想要的那样。

但对于只有一个函数,我会使用RETURNS TABLE()并拼写出返回类型:

RETURNS TABLE (
   id numeric
 , start date
 , "end" date
 , description text
 , total numeric
 , hours numeric)
Run Code Online (Sandbox Code Playgroud)

哦,我不会在 Postgres 中使用“开始”和“结束”作为标识符。两者都是标准 SQL 中的保留字。“end”在 Postgres 中是绝对保留的,并且必须始终用双引号引起来。