【问题标题】:Declare variable of composite type in PostgreSQL using %TYPE在 PostgreSQL 中使用 %TYPE 声明复合类型的变量
【发布时间】:2011-11-29 21:16:38
【问题描述】:

问题:如何在存储函数中声明同类型的变量作为参数?

简单的答案是使用%TYPE,这样可以:

CREATE OR REPLACE FUNCTION test_function_1(param1 text)
  RETURNS integer AS
$BODY$ 
DECLARE
    myVariable param1%TYPE;
BEGIN
    return 1;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

但问题是当param1 是复合类型时:

CREATE TYPE comp_type as
(
    field1 text
)

CREATE OR REPLACE FUNCTION test_function_2(param1 comp_type)
  RETURNS integer AS
$BODY$ 
DECLARE
    myVariable param1%TYPE;
BEGIN
    return 1;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

这不起作用:

ERROR: type comp_type does not exist [SQL State=42704]

那么当param1是复合类型时我该怎么办呢?

(注意:仅myVariable comp_type 不是一个好选择,因为我的函数稍微更复杂。)


编辑: 我在复制和粘贴时出错,真正的错误是:

ERROR: invalid type name "param1%TYPE"
  Position: 130 [SQL State=42601] 

而使用param1%ROWTYPE 的错误是:

ERROR: relation "param1" does not exist
  Where: compilation of PL/pgSQL function "test_function_2" near line 3 [SQL State=42P01] 

【问题讨论】:

    标签: postgresql stored-procedures types polymorphism plpgsql


    【解决方案1】:

    在这种情况下使用%ROWTYPE

    编辑 - 简单案例

    A.H. 和 DavidEG 的测试表明这不起作用。有趣的问题!
    您可以尝试解决方法。只要您的定义与示例类似,您就可以简单地求助于

    CREATE FUNCTION test(param1 comp_type)
      RETURNS integer AS
    $BODY$ 
    DECLARE
        myvar comp_type;
    BEGIN
        return 1;
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE;
    

    但你真正的问题可能没有那么简单?

    编辑 2 - 真正的问题

    正如预期的那样,真正的问题更复杂:多态输入类型
    解决方法该场景更难,但应该完美无缺:

    CREATE FUNCTION test(param1 anyelement, OUT a integer, OUT myvar anyelement)
      RETURNS record AS
    $BODY$
    BEGIN
        myvar := $1;  -- myvar has now the required type.
    
        --- do stuff with myvar.
    
        myvar := NULL;  -- reset if you don't want to output ..
        a := 1;
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE;
    

    呼叫:

    SELECT a FROM test('("foo")'::comp_type); -- just retrieve a, ignore myvar
    

    查看完整输出:

    SELECT * FROM test('("foo")'::comp_type);
    

    PostgreSQL 9.0+ 的注意事项

    v9.0 中有一个重要的更新。我引用release notes

    • 允许在 PL/pgSQL 函数中为输入参数赋值 (史蒂夫·普伦蒂斯)

    以前,输入参数被视为声明为 CONST,所以 该函数的代码无法更改它们的值。这个限制 已被删除以简化从其他 DBMS 移植功能 不施加等效限制。现在是一个输入参数 就像一个初始化为传入值的局部变量。

    所以,除了我的解决方法之外,您还可以直接使用输入变量。

    动态归档名称

    【讨论】:

    • 不起作用,“param1.%ROWTYPE”表示“关系 param1 不存在”。我很好奇是否有人找到答案。
    • %ROWTYPE%TYPE 出现同样的错误。顺便说一句,我正在使用 PostgreSQL 9.1。
    • @Erwin 这行得通,但在真正的问题param1anyelement 所以我不知道硬编码它的类型。
    • 我已经测试了您的第二个解决方法,它似乎工作得很好。我尝试了标准类型、复合类型、数组,没有问题。谢谢@Erwin。
    • 我不明白如何访问param1myvar 中的field1。尽管类型是anyelement,这仍然可能吗?
    猜你喜欢
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    相关资源
    最近更新 更多