自定义 Postgres 功能不起作用

bca*_*lla 5 postgresql functions

我编写了这个函数,它应该遍历文本数组并将每个元素(这是一个类型转换的整数)转换为十六进制,附加到文本变量,然后返回十六进制。然而,我什么也得不到。

有没有人看到该函数有任何问题会导致它不返回任何内容?

CREATE OR REPLACE FUNCTION array_convert_to_hex(text[])
RETURNS text
AS
$$
DECLARE
   arrInts ALIAS FOR $1;
   retVal text;
BEGIN
   FOR I IN array_lower(arrInts, 1)..array_upper(arrInts, 1) LOOP
    retVal := retVal || lpad(cast(to_hex(arrInts[I]::integer) as varchar), 2, '0');
   END LOOP;
RETURN retVal;
END;
$$
LANGUAGE plpgsql
   STABLE
RETURNS NULL ON NULL INPUT;
Run Code Online (Sandbox Code Playgroud)

Cra*_*ger 7

当然,彼得对这个问题的看法是正确的。然而,这整个函数是不必要的缓慢和复杂 - 重复的字符串连接对性能来说是可怕的,无论如何,最好避免 PL/PgSQL 循环。

您可以使用普通 SQL 函数执行相同的工作generate_subscripts

CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $$
SELECT 
  string_agg(
    lpad(to_hex($1[x]),2,'0'),
    ''
    order by x
  ) 
FROM generate_subscripts($1,1) x;
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

上面的版本需要一个整数数组,但你可以接受带有重载的文本数组:

CREATE OR REPLACE FUNCTION intarr_to_hex_string(text[]) RETURNS text AS $$
SELECT intarr_to_hex_string($1::integer[])
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

请注意,没有进行完整性检查以确保十六进制字符串为两位或更少。您真的应该在使用 CASE 语句执行 PL/PgSQL 函数的地方添加一个检查,如果输入错误,则会引发错误。这是一个完整的例子:

CREATE OR REPLACE FUNCTION raise_exception(text)
  RETURNS void LANGUAGE plpgsql AS
$BODY$ 
BEGIN 
   RAISE EXCEPTION '%', $1; 
END; 
$BODY$;

CREATE OR REPLACE FUNCTION intarr_to_hex_string(integer[]) RETURNS text AS $$
SELECT 
  string_agg(lpad(
    CASE WHEN $1[x] < 256 THEN
      to_hex($1[x])
    ELSE
      raise_exception('Argument to intarr_to_hex_string contained value '||coalesce($1[x]::text,'NULL')||', expected all values in i[] to be 0 <= i < 256. Full argument was '||quote_literal($1)||'.')::text
    END,
    2, '0'),
  ''
  order by x) 
FROM generate_subscripts($1,1) x;
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)


Pet*_*aut 6

因为 retVal 开始时为 null,而 null || 某些东西保持为空。您应该将 retVal 初始化为 ''。