You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PL/pgSQL中查询自定义数据类型数组对象返回null的问题排查

问题描述

先创建自定义数据类型compfoo:

CREATE TYPE compfoo AS (f1 int, f2 text);

接着创建表foo,包含fooid和fooname两列(对应compfoo的字段),并插入记录(1, 'aa')、(2, 'bb')、(3, 'cc')。

随后定义了如下PL/pgSQL函数:

create or replace function foo_query()
returns text
language plpgsql
as $$
    declare
      r compfoo;
      arr compfoo [];
      footemp compfoo;
      result text;
    begin
      for r in
        select * from foo where fooid = 1 OR fooid = 2
        loop
        arr := array_append(arr, r);
      end loop;
      foreach footemp in array arr
        loop
        select footemp.f1 into result where footemp.f1 = 1;
      end loop;
    return result;
    end;
$$

函数逻辑为先查询foo表将结果存入compfoo类型数组arr,再遍历数组查询元素的字段。但函数未报错却返回null,请问问题出在哪里?


问题分析与解决

问题出在遍历数组时的select ... into语句:

  • 数组中的元素顺序为(1, 'aa')、(2, 'bb'),第一次遍历到f1=1的元素时,result被赋值为'1';
  • 第二次遍历到f1=2的元素时,select footemp.f1 into result where footemp.f1 = 1因条件不匹配没有返回任何行,而PL/pgSQL中select into语句无匹配行时,会将目标变量result重置为null,最终函数返回这个被覆盖后的null。

推荐两种修正方案:

  1. 找到目标元素后直接跳出循环,避免后续操作覆盖结果:
create or replace function foo_query()
returns text
language plpgsql
as $$
    declare
      r compfoo;
      arr compfoo [];
      footemp compfoo;
      result text;
    begin
      for r in
        select * from foo where fooid = 1 OR fooid = 2
        loop
        arr := array_append(arr, r);
      end loop;
      foreach footemp in array arr
        loop
          if footemp.f1 = 1 then
            result := footemp.f1::text;
            exit; -- 找到目标后终止循环
          end if;
        end loop;
    return result;
    end;
$$
  1. 简化实现逻辑,无需数组和循环,直接查询目标值:
create or replace function foo_query()
returns text
language sql
as $$
    select fooid::text from foo where fooid = 1;
$$

内容的提问来源于stack exchange,提问作者EduardoSalazarT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 18:05:23