如何定义一个只接受三个字符的函数?

cev*_*ing 2 postgresql plpgsql functions

我试过这个:

create or replace function c3 (arg char(3))
  returns void
  language plpgsql as
$$
begin
  raise notice 'Value: %', arg;
end;
$$;
Run Code Online (Sandbox Code Playgroud)

但它接受三个以上的字符:

select c3('1234');
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 5

函数参数中的数据类型修饰符(如char(3))将被 忽略CREATE FUNCTION手册:

允许使用完整的 SQL 类型语法来声明函数的参数和返回值。然而,带括号的类型修饰符(例如,数字类型的精度字段)被 丢弃CREATE FUNCTION。因此,例如...与...CREATE FUNCTION foo (varchar(10))完全相同。CREATE FUNCTION foo (varchar)

您仍然可以通过在调用中添加显式强制转换来使用原始函数:

SELECT c3('1234'::char(3));  -- explicit cast
Run Code Online (Sandbox Code Playgroud)

但这只是给猪涂口红而已。

正确的解决方案

添加显式测试:

CREATE OR REPLACE FUNCTION c3 (arg text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   IF length(arg) > 3 THEN
      RAISE EXCEPTION 'Input too long: >>%<<', arg;
   END IF;

   RAISE NOTICE 'Value: %', arg;
END
$func$;
Run Code Online (Sandbox Code Playgroud)

或者默默地强制转换或截断输入以避免异常:

CREATE OR REPLACE FUNCTION c3 (arg text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   arg := left(arg, 3);  -- one of several ways

   RAISE NOTICE 'Value: %', arg;
END
$func$;
Run Code Online (Sandbox Code Playgroud)

并且永远不要使用旧数据类型char(N)(即使这不是这里的直接问题)。看: