sql - 带有 OUT 参数的 PostgreSQL 函数和带有 TABLE 结果的 PostgreSQL 函数之间有任何形式上的区别吗?

标签 sql postgresql stored-procedures user-defined-functions out-parameters

考虑这两个 PostgreSQL 函数:

CREATE OR REPLACE FUNCTION f_1 (v1 INTEGER, v2 OUT INTEGER)
AS $$
BEGIN
    v2 := v1;
END
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION f_2 (v1 INTEGER)
RETURNS TABLE(v2 INTEGER)
AS $$
BEGIN
    v2 := v1;
END
$$ LANGUAGE plpgsql;

在任何“普通”过程式 SQL 语言(例如 Transact-SQL)中,这两种类型的函数都大不相同。 f_1 实际上是一个过程,而 f_2 是一个表值函数。在 SQL Server 中,后者从 INFORMATION_SCHEMA.ROUTINES 返回,如下所示:

SELECT r.routine_schema, r.routine_name
FROM   information_schema.routines r
WHERE  r.routine_type = 'FUNCTION'
AND    r.data_type = 'TABLE'

然而,在 PostgreSQL 中,这不起作用。以下查询显示 f_1f_2 的签名之间基本上没有区别:

SELECT r.routine_name, r.data_type, p.parameter_name, p.data_type
FROM   information_schema.routines r
JOIN   information_schema.parameters p
USING (specific_catalog, specific_schema, specific_name);

以上结果:

routine_name | data_type | parameter_name | data_type
-------------+-----------+----------------+----------
f_1          | integer   | v1             | integer
f_1          | integer   | v2             | integer
f_2          | integer   | v1             | integer
f_2          | integer   | v2             | integer

当我从函数返回多个列时,事情并没有变得更好,在这种情况下,我什至不再有“正式”返回类型。只需记录:

CREATE OR REPLACE FUNCTION f_3 (v1 INTEGER, v2 OUT INTEGER, v3 OUT INTEGER)
AS $$
BEGIN
    v2 := v1;
END
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION f_4 (v1 INTEGER)
RETURNS TABLE(v2 INTEGER, v3 INTEGER)
AS $$
BEGIN
    v2 := v1;
END
$$ LANGUAGE plpgsql;

...我会得到:

routine_name | data_type | parameter_name | data_type
-------------+-----------+----------------+----------
f_3          | record    | v1             | integer
f_3          | record    | v2             | integer
f_3          | record    | v3             | integer
f_4          | record    | v1             | integer
f_4          | record    | v2             | integer
f_4          | record    | v3             | integer

如果来自其他数据库,显然词法签名的意图是完全不同的。作为 Oracle 人员,我希望 PROCEDURES 有副作用,而 FUNCTIONS 没有任何副作用(除非在自治事务中)并且可以安全地嵌入在 SQL 中。我知道 PostgreSQL 巧妙地将所有函数都视为表,但我认为将 OUT 参数设计为任何查询中的表列并不是一个好主意...

我的问题是:

这两种声明函数的方式在形式上有什么区别吗?如果存在,我如何从 INFORMATION_SCHEMAPG_CATALOG 中发现它?

最佳答案

\df public.f_* 这样做

select
    n.nspname as "Schema",
    p.proname as "Name",
    pg_catalog.pg_get_function_result(p.oid) as "Result data type",
    pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
    case
        when p.proisagg then 'agg'
        when p.proiswindow then 'window'
        when p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype then 'trigger'
        else 'normal'
    end as "Type"
from
    pg_catalog.pg_proc p
    left join
    pg_catalog.pg_namespace n on n.oid = p.pronamespace
where
    p.proname ~ '^(f_.*)$'
    and n.nspname ~ '^(public)$'
order by 1, 2, 4;

返回这个

                                          List of functions
 Schema | Name |       Result data type        |            Argument data types             |  Type  
--------+------+-------------------------------+--------------------------------------------+--------
 public | f_1  | integer                       | v1 integer, OUT v2 integer                 | normal
 public | f_2  | TABLE(v2 integer)             | v1 integer                                 | normal
 public | f_3  | record                        | v1 integer, OUT v2 integer, OUT v3 integer | normal
 public | f_4  | TABLE(v2 integer, v3 integer) | v1 integer                                 | normal
(4 rows)

要删除函数,必须传递其输入(ININOUT)参数数据类型。然后我猜测函数名称及其输入参数数据类型确实构成了它的签名。要更改返回的数据类型,必须先删除它并重新创建。

关于sql - 带有 OUT 参数的 PostgreSQL 函数和带有 TABLE 结果的 PostgreSQL 函数之间有任何形式上的区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24512606/

相关文章:

python - 使用 Django 获取对象的孙子

mysql - 有没有办法执行根据单元格内容进行更新的 SQL 更新语句

windows - 如何使用 Windows 完成 psql?

postgresql - 创建 Postgres 规则或触发器以在插入时自动将列转换为小写或大写

Django 时间戳不一致

sql-server - 多表复杂实体的乐观并发

c# - 将 int 数组传递给存储过程的表值参数 - 转换失败

mysql - 如果在重复键更新时插入

java - SQL False 命令、Java 代码和 SQL?希望可以有人帮帮我

sql - 向 SQL Server 用户授予执行权限以仅运行特定作业