sql - 扩展现有的 PostgreSQL 类型

标签 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;
}
因为我有一个函数可以返回 meetings 中的所有列表然后另外两个 totalhours在查询时计算的列。下面是这个函数的样子:
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 的表不同栏目 两个新hourstotal列。我想要做的是这样的事情(显然下面的语法实际上并不存在......但我不确定是否有另一种方法可以使用类似的速记语法来做到这一点):
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)
我当前的解决方法是创建一个 View ,然后让该函数简单地查询该 View 并返回该 View 的类型。

最佳答案

致您的 核心问题 :

Is it possible to extend an existing datatype?


, 不可能。不在 RETURNS CREATE FUNCTION的条款, 不是 PostgreSQL 版本 14 之前的任何其他地方。
您可以返回复合类型的字段,以及任何类型的附加字段。但这有微妙的不同:
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');
但我不会去那里。

My current workaround is to create a view and then have that function simply query that view and return the view's type.


然后只需使用 View 。不要在它之上创建附加功能。案件结案。
你实际上是想说:

... then use the row type of the view in the RETURNS clause of the function


然后我们回到你的问题。 CREATE VIEW (隐式)注册扩展行类型是一个有效的选项 - 特别是因为 SELECT *是在 had 的情况下的一种方便的语法简写。但对于初学者来说,
RETURNS TABLE (LIKE meeting_instances)
... 不是 CREATE FUNCTION 的文档语法. 任何人都不应该使用它。 可能会在下一版本之一中删除,恕不另行通知。
规范的、等效的、记录在案的语法是:
RETURNS SETOF meeting_instances
(LIKE some_table)记录了 CREATE TABLE 的语法. RETURNS CREATE FUNCTION的条款目前支持相同,但没有记录,所以不要使用它。
回到您创建 VIEW 的解决方法.如果你没有用VIEW ,除了注册扩展行类型,考虑 CREATE TYPE 反而。不幸的是,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 中使用“开始”和“结束”作为标识符。两者都是reserved words在标准 SQL 中。 “end”在 Postgres 中是绝对保留的,必须始终用双引号引起来。

关于sql - 扩展现有的 PostgreSQL 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69067171/

相关文章:

mysql - CREATE FUNCTION 在本地工作,在服务器上失败 - 相同版本的 MySQL

PHP 的 create_function() 与仅使用 eval()

MySQL 创建带有值的函数语句并返回数据类型decimal

php - 在查询内进行另一个查询时仅显示一行

sql - oracle中的区间函数

Postgresql 9.5 安装 - 配置所有者(postgres :105) and data owner (ubuntu:1000) do not match, 和配置所有者不是 root

ruby-on-rails - 关系表中的模型问题

sql - 在 Postgres 中使用表值参数调用函数

sql - PostgreSQL 将 varchar 列表示为 bool 值

arrays - 创建另一个表和在 postgres 中使用数组有什么区别