如何在 postgreSQL 中处理复合类型的变化

Posted

技术标签:

【中文标题】如何在 postgreSQL 中处理复合类型的变化【英文标题】:How to handle changes in composite type in postgreSQL 【发布时间】:2017-02-26 21:47:35 【问题描述】:

我即将学习 postgresql,但遇到了某种问题。我想通过存储过程(函数)建立从网站到数据库的大部分连接。到目前为止,我有大约 20 个函数,其中 5 个函数返回与列完全相同的表,即:

create or replace function my_Function( t text )
returns setof table(uid uuid,testText text, randomInt int ...)
...

因为 table(uid uuid,testText text, randomInt int ...) 重复了 5 次,我发现我可以使用复合类型从我的函数返回相同类型的数据,所以如果我需要返回一个额外的列我可以更改我的复合类型,瞧,所有 5 个函数都应该返回相同的列。

不幸的是,这不是如何工作的,一旦我向复合类型添加了一个新列,所有使用我的复合类型的函数都因 saem 错误而中断:

Final statement returns too few columns

这是有道理的,因为我没有选择额外的列来适应复合类型。

有什么方法可以判断哪些函数使用复合类型作为返回类型? 有没有办法强制复合类型为新创建的列填充空白(如果没有,那么我也可以使用 table(...) 返回类型,因为它不能解决我试图避免的冗余问题)?

【问题讨论】:

【参考方案1】:

示例设置:

create type my_type as (id int, name text);

create or replace function my_function_1()
returns setof my_type language plpgsql as $$
declare
    rec my_type;
begin
    rec.id := 1;
    rec.name := 'name';
    return next rec;
end $$;

create or replace function my_function_2()
returns setof my_type language plpgsql as $$
begin
    return query select 1::int, 'name'::text;
end $$;

有什么方法可以判断哪些函数使用复合类型作为返回类型?

是的:

select nspname as schema_name, proname as function_name
from pg_proc p
join pg_namespace n on n.oid = pronamespace
join pg_type t on t.oid = prorettype
where typname = 'my_type';

 schema_name | function_name 
-------------+---------------
 public      | my_function_1
 public      | my_function_2
(2 rows)

有没有办法强制复合类型为新创建的列填充空白?

没有。在向类型添加新属性后,您可以尝试重新创建(不修改)函数:

alter type my_type add attribute new_col int;
create or replace function my_function_1() ...
create or replace function my_function_2() ...

但只有返回下一个类型变量的函数才能正常工作(my_function_1() 可以工作,my_function_2() 不行)。

【讨论】:

嗯,这听起来很压抑。修改这么难,我就不去了。【参考方案2】:

使用 Postgres 复合类型有什么好处?这似乎是一个痛苦的世界。我可以探索这将如何与QueryFirst 一起工作吗?您的程序将在您的应用程序中的 .sql 文件中,与您的应用程序一起进行版本控制,源代码受控。对于共享返回类型的 5 个过程,您将创建一个 C# 接口。在 5 个 Results.cs 文件的每一个中,在结果部分类上,继承接口。因此,这 5 个 proc 可以单独发展,根据需要添加列。如果您修改了 proc 使其不再满足接口:编译错误。一个更宽容、更能容忍变化的场景。

免责声明:我写的是 QueryFirst

【讨论】:

以上是关于如何在 postgreSQL 中处理复合类型的变化的主要内容,如果未能解决你的问题,请参考以下文章

重构 PostgreSQL SProcs

复合数组类型作为 PostgreSQL 中的 OUTPUT 参数

Postgresql:复合类型并选择进入

PostgreSQL中复合类型列子列的外键约束

在 Postgresql 中创建一个不返回复合值的函数

如何使用 jOOQ 更新 PostgreSQL 上复合列的单个子字段?