6

次の 2 つの 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 など) では、2 つのタイプの関数はまったく異なります。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

他のデータベースからのものである場合、字句署名の意図は明らかにまったく異なります。オラクルの人として、副作用があることを期待PROCEDURESしていますFUNCTIONSが、(自律型トランザクションでない限り) 副作用はなく、SQL に安全に埋め込むことができます。OUTPostgreSQL がすべての関数をテーブルとして巧みに扱うことは知っていますが、どのクエリでもパラメータをテーブル列として設計するのは良い考えではないと思います...

私の質問は:

関数を宣言する 2 つの方法に形式上の違いはありますか? ある場合、INFORMATION_SCHEMAまたは からどのように発見できPG_CATALOGますか?

4

3 に答える 3