考虑这两个 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_1
以下查询表明和的签名本质上没有区别f_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
当我从函数返回多个列时,情况并没有好转,在这种情况下,我什至不再有“正式”返回类型。只是record
:
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_SCHEMA
或 中发现它PG_CATALOG
?