使用简单的PL / pgSQL函数的错误

时间:2016-06-02 00:12:27

标签: postgresql types plpgsql currency

我正在尝试编写我的第一个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.

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

您确定要使用数据类型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上的页面。

答案 1 :(得分:1)

您需要在输入中放置单引号:

SELECT cents('$66.66');

如果您的设置不允许此操作(仍然会抛出错误),您可以尝试投射: SELECT cents('66.66'::float8::numeric::money);

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