PL/pgSQL中如何定义多列数组变量并返回查询结果
处理PostgreSQL多列数据数组的PL/pgSQL存储过程方案
我懂你这种纠结——单值数组的存储过程写得顺风顺水,一碰到多列数据的数组就卡壳了对吧?问题出在PostgreSQL的数组要求元素是同一种数据类型,而多列数据属于复合类型,不能直接用普通的数值/字符串数组来存储。下面给你两种实用的解决方案,按需选择就行:
方案1:自定义复合类型 + 复合类型数组
如果你需要多次复用这个多列数据结构,先定义一个自定义的复合类型,再用这个类型创建数组变量,步骤如下:
第一步:创建复合类型
先定义和你要存储的多列数据匹配的类型:
CREATE TYPE my_data_row AS ( id BIGINT, name VARCHAR(50), amount NUMERIC(10,2) );
第二步:编写使用复合数组的函数
用这个自定义类型声明数组变量,然后就可以像单列数组一样操作了:
CREATE OR REPLACE FUNCTION testing_multicolumn_array() RETURNS TABLE(id BIGINT, name VARCHAR(50), amount NUMERIC(10,2)) AS $body$ DECLARE l_rows my_data_row[]; -- 声明复合类型数组 BEGIN -- 把多列数据存入数组(注意要把行转成自定义类型) l_rows := ARRAY( SELECT (1, '商品A', 99.99)::my_data_row UNION ALL SELECT (2, '商品B', 159.50)::my_data_row ); -- 这里可以添加你的数据处理逻辑,比如遍历数组修改值 FOR idx IN 1..array_length(l_rows, 1) LOOP l_rows[idx].amount := l_rows[idx].amount * 0.9; -- 打9折 END LOOP; -- 返回处理后的多列数据 RETURN QUERY SELECT * FROM UNNEST(l_rows); END; $body$ LANGUAGE plpgsql;
方案2:直接使用表变量(无需额外创建类型)
如果只是在当前函数里用一次这个多列结构,直接用TABLE类型的变量会更省事,不需要预先创建自定义类型:
CREATE OR REPLACE FUNCTION testing_multicolumn_table() RETURNS TABLE(id BIGINT, name VARCHAR(50), amount NUMERIC(10,2)) AS $body$ DECLARE -- 直接声明表变量,结构和返回值一致 l_rows TABLE(id BIGINT, name VARCHAR(50), amount NUMERIC(10,2)); BEGIN -- 把数据插入表变量,就像操作普通表一样 INSERT INTO l_rows SELECT 1, '商品A', 99.99 UNION ALL SELECT 2, '商品B', 159.50; -- 处理数据,比如更新表变量中的记录 UPDATE l_rows SET amount = amount * 0.9; -- 返回数据 RETURN QUERY SELECT * FROM l_rows; END; $body$ LANGUAGE plpgsql;
额外小技巧:复用现有表的结构
如果你要处理的多列数据和已有的某个表结构完全一致,可以直接用%ROWTYPE来声明数组,省去自定义类型的步骤:
比如你有一个products表,结构是id BIGINT, name VARCHAR(50), amount NUMERIC(10,2),那函数里可以这么写:
DECLARE l_rows products%ROWTYPE[]; -- 直接复用products表的行类型
这样就可以直接把查询到的products表数据存入这个数组了。
内容的提问来源于stack exchange,提问作者kaaja




