我可能在形成文字方面做错了。假设我有一个简单的存储过程,如下所示:
CREATE OR REPLACE FUNCTION do_something(input_array composite_type[])
RETURNS SETOF text AS
$BODY$
DECLARE
temp_var composite_type;
BEGIN
FOR temp_var IN SELECT unnest(input_array) LOOP
return next temp_var.message;
END LOOP;
END
$BODY$
LANGUAGE plpgsql;
composite_type
定义为:
CREATE TYPE composite_type AS
(message text,
amount numeric(16,2));
执行如下查询:
SELECT * FROM do_something('{"(test,11)","(test2,22)"}')
生成此结果集:
(test,11.00)
(test2,22.00)
而不是:
test
test2
我的文字有问题,还是应该以不同的方式访问message
字段?感谢您的任何建议。
答案 0 :(得分:2)
如何指定输入看起来很正常,因为使用行和数组构造函数语法会观察到相同的行为:
SELECT * FROM do_something( ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[] );
和
SELECT ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[];
产生
'{"(test,11.00)","(test2,22.00)"}'
如果添加:
RAISE NOTICE '!%!',temp_var;
在循环内输出:
NOTICE: !("(test,11.00)",)!
NOTICE: !("(test2,22.00)",)!
显示您实际上正在使用“message”作为您预期的元组文本和null“amount”获取元组。
因此。为什么呢?
这有点微妙。你正在使用:
SELECT unnest(input_array)
这似乎做你想要的,对吧:
regress=> SELECT unnest( ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[] );
unnest
---------------
(test,11.00)
(test2,22.00)
(2 rows)
...但实际上,它正在返回composite_type
类型的单列。 PL / PgSQL复合类型赋值要求每个类型列一列。因此,单个col被推入'消息'并且没有第二个col。
相反,写一下:
SELECT * FROM unnest(input_array)
解压缩组合以进行分配。然后它按预期工作:
regress=> SELECT * FROM do_something( ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[] );
do_something
--------------
test
test2
(2 rows)
如果composite_type
的第一个字段属于非文本类型,则会收到一个错误信息,该信息对此有更多信息。
答案 1 :(得分:1)
Craig很好地解释了这种行为的原因 - 在FOR语句中赋值变量=值期望零嵌套。所以你应该这样做:
CREATE OR REPLACE FUNCTION do_something(input_array composite_type[])
RETURNS SETOF text AS $BODY$
DECLARE
temp_var record;
BEGIN
-- unnesting
FOR temp_var IN SELECT (unnest(input_array)).*
LOOP
RETURN NEXT temp_var.message;
END LOOP;
RETURN;
END
$BODY$ LANGUAGE plpgsql;
或 - 更好 - 更新在“列列表”
中使用SetReturnedFunctionCREATE OR REPLACE FUNCTION do_something(input_array composite_type[])
RETURNS SETOF text AS $BODY$
DECLARE
temp_var record;
BEGIN
-- SELECT FROM
FOR temp_var IN SELECT * FROM unnest(input_array)
LOOP
RETURN NEXT temp_var.message;
END LOOP;
RETURN;
END
$BODY$ LANGUAGE plpgsql;