PostgreSQL中如何在数组/变量中存储多列数据并循环遍历
实现方法
你当前的写法有3个核心问题需要修正:
- 变量类型定义错误:你声明的
unsatified_documents driver_expiring_documents;是单行复合类型变量,无法存储多行查询结果,也不支持数组遍历语法,需要声明为该复合类型的数组 - 查询字段顺序和复合类型定义不匹配:自定义类型
driver_expiring_documents的字段顺序是driver_id在前、expiration_date在后,但原查询先查expiration_date再查driver_id,会导致字段值错位 - 数组非空判断写法不规范:直接和
'{}'比较在部分场景下会出现判断异常,建议用数组基数判断更可靠
完整实现代码
你可以直接在PL/pgSQL函数、存储过程或匿名块中使用如下写法:
declare -- 注意变量类型是复合类型的数组,用于存储多行结果 unsatified_documents driver_expiring_documents[]; expiring_doc driver_expiring_documents; driver_id_arg text; expiring_date date; begin -- 将查询结果聚合为数组存入变量,调整字段顺序和复合类型结构对齐 select array_agg( (driver_id, expiration_date)::driver_expiring_documents ) into unsatified_documents from ( select expiration_date, driver_id from all_requirements_driver_documents where expiration_date <= (now() + interval '1 month')::date and expiration_date > (now() - interval '7 day')::date union select expiration_date, driver_id from all_requirements_vehicle_documents where expiration_date <= (now() + interval '1 month')::date and expiration_date > (now() - interval '7 day')::date ) t; -- 判断数组非空后遍历 if cardinality(unsatified_documents) > 0 then foreach expiring_doc in array unsatified_documents loop -- 提取字段值 driver_id_arg := expiring_doc.driver_id; expiring_date := expiring_doc.expiration_date; -- 在此处编写后续业务逻辑即可 end loop; end if; end;
更简洁的替代方案
如果你不需要把结果集暂存做二次复用,完全不需要定义数组变量,直接用游标循环遍历查询结果即可,性能更好、代码更简洁:
declare driver_id_arg text; expiring_date date; begin for expiring_doc in ( select expiration_date, driver_id from all_requirements_driver_documents where expiration_date <= (now() + interval '1 month')::date and expiration_date > (now() - interval '7 day')::date union select expiration_date, driver_id from all_requirements_vehicle_documents where expiration_date <= (now() + interval '1 month')::date and expiration_date > (now() - interval '7 day')::date ) loop driver_id_arg := expiring_doc.driver_id; expiring_date := expiring_doc.expiration_date; -- 在此处编写后续业务逻辑即可 end loop; end;
关键语法说明
array_agg()会将查询返回的多行结果聚合成一个数组,每个数组元素对应一行数据,强制类型转换保证结构和自定义复合类型完全匹配cardinality()返回数组的元素总个数,值大于0即代表数组非空,兼容性比直接和空数组字面量比较更好
内容的提问来源于stack exchange,提问作者Alwaysblue
相关产品推荐
相关产品推荐

