【问题标题】:Errors with an easy PL/pgSQL Function简单的 PL/pgSQL 函数的错误
【发布时间】:2016-06-02 00:12:26
【问题描述】:

我正在尝试编写我的第一个 PL/pgSQL 函数。目前,它只是应该返回传递给它的值中的字符数。

CREATE OR REPLACE FUNCTION public.cents(money)
 RETURNS int
 LANGUAGE plpgsql
 LEAKPROOF
AS $function$
DECLARE
    new_price money;
    size int;
BEGIN
    size := char_length(money);
    RETURN size;
END;
$function$;

当我尝试使用 $66.66 进行测试时,我收到一个错误:

select cents($66.66);
ERROR:  syntax error at or near ".66"
LINE 1: select cents($66.66);
                        ^

如果我使用$66,我会得到一个不同的错误:

select cents($66);
ERROR:  there is no parameter $66
LINE 1: select cents($66);
                     ^

仅使用整数 66 给了我第三个错误:

select cents(66);
       ^

HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

我在这里做错了什么?

【问题讨论】:

    标签: postgresql types plpgsql currency


    【解决方案1】:

    您确定要使用数据类型money 吗?考虑:

    如果您需要money 类型,请务必了解此类型的区域设置的作用。 Read the manual.

    你不能输入没有单引号的文字(比如数字常量)——除非你强制转换它们,否则效率会很低。但这不是唯一的错误。你的函数会像这样工作:

    CREATE OR REPLACE FUNCTION public.cents(_my_money_parameter money)
      RETURNS int AS
    $func$
    BEGIN
       RETURN char_length(_my_money_parameter::text);
    END
    $func$  LANGUAGE plpgsql LEAKPROOF;
    

    呼叫:

    SELECT public.cents(money '66.66');
    SELECT public.cents('66.66'::money);
    SELECT public.cents(66.66::money);
    

    第一个调用变体是最有效的,但它取决于区域设置。我的示例中的 dot 在某些语言环境中被解释为千位分隔符并被忽略(而不是小数点)。

    注意事项

    • 您将money 视为函数体中的参数名称,但它只是数据类型。如果要使用参数名称,则必须像演示的那样声明它们。或者引用有位置引用的参数:$1$2等。

    • char_length() 需要一个字符数据类型,你不能将它用于数据类型money 而不进行强制转换。只是length() 是等效的。

    • 如果包含美元符号,则字符串文字需要单引号:'$66.66' - 格式必须与您的语言环境设置相匹配才能适用于 money
      如果你只提供数字常量66,由于函数类型解析的规则,Postgres 将找不到带有money 参数的函数。详情:

    首先阅读手册中的章节Constants
    继续CREATE FUNCTION 上的页面。

    【讨论】:

      【解决方案2】:

      您需要在输入周围加上单引号:

      SELECT cents('$66.66');
      

      如果您的设置不允许这样做(仍然抛出错误),您可以尝试强制转换: SELECT cents('66.66'::float8::numeric::money);

      请务必参考文档,因为它们提供了很好的概述: https://www.postgresql.org/docs/current/static/datatype-money.html

      【讨论】:

      • 您从手册中复制了演员表:::float8::numeric::money 但在这种情况下这是无稽之谈。它旨在转换数字 values 并且对于文字输入没有意义。除此之外,答案错过了问题中的大部分问题,并且忽略了使用输入 '$66.66' 警告可能的警告。不过,您指向手册的链接很有帮助,因此我将删除反对票。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多