我正在尝试将表中的值放入数组中,并且数组定义与表的列定义不同。我试过做强制转换,但是没有用。基本上,我需要将表中的值作为数组(tab_small_str)。有人可以建议吗?
CREATE TYPE tab_small_str AS (
str CHARACTER VARYING(50)
);
create table test_emp(emp_id integer, ename character varying (10));
insert into test_emp values(1,'a1')
insert into test_emp values(2,'a2')
insert into test_emp values(3,'a3')
CREATE OR REPLACE function test_fn () RETURNS VARCHAR[] as
$$
DECLARE
v_ename tab_small_str[];
i tab_small_str;
BEGIN
SELECT ARRAY(SELECT ename::tab_small_str FROM test_emp) INTO v_ename;
RAISE INFO 'array is: %',v_ename;
RETURN v_ename;
FOREACH i IN ARRAY v_ename
LOOP
RAISE info 'value of ename is%', i;
END LOOP;
END;
$$
language plpgsql;
(function compiles fine).
select test_fn()
--gives below error
ERROR: malformed record literal: "a1"
DETAIL: Missing left parenthesis.
CONTEXT: SQL statement "SELECT ARRAY(SELECT ename::tab_small_str FROM test_emp)"
PL/pgSQL function test_fn() line 7 at SQL statement
********** Error **********
ERROR: malformed record literal: "a1"
SQL state: 22P02
Detail: Missing left parenthesis.
Context: SQL statement "SELECT ARRAY(SELECT ename::tab_small_str FROM test_emp)"
PL/pgSQL function test_fn() line 7 at SQL statement
嗨404, 我按照建议进行了修改:
CREATE OR REPLACE function test_fn () RETURNS tab_small_str[] as
$$
DECLARE
v_ename tab_small_str[];
i tab_small_str;
BEGIN
SELECT ARRAY(SELECT ROW(ename)::tab_small_str FROM test_emp) INTO v_ename;
RAISE INFO '%',v_ename;
FOREACH i IN ARRAY v_ename
LOOP
RAISE NOTICE '%', i;
END LOOP;
RETURN v_ename;
END;
$$
language plpgsql;
它返回输出为:
INFO: {(a1),(a2),(a3)}
CONTEXT: PL/pgSQL function test_fn() line 9 at RAISE
NOTICE: (a1)
CONTEXT: PL/pgSQL function test_fn() line 13 at RAISE
NOTICE: (a2)
CONTEXT: PL/pgSQL function test_fn() line 13 at RAISE
NOTICE: (a3)
CONTEXT: PL/pgSQL function test_fn() line 13 at RAISE
我的问题是为什么输出用括号括起来-为什么不仅是a1而是(a1)。您能建议一下吗?
答案 0 :(得分:2)
由于缺乏更好的描述,您的新类型不是“单字段数据类型”,您可以在其中直接将类似VARCHAR(10)
的内容转换为它;这是一个包含单个字段的ROW。所以类似'blah'::tab_small_str
之类的事情失败了,因为它试图将文本强制转换为包含字段而不是字段本身的类型。
要解决,请使用您现有的查询:
SELECT ename::tab_small_str FROM test_emp
更改为:
SELECT ROW(ename)::tab_small_str FROM test_emp
关于为什么您的结果用方括号括起来的原因:这是当将ROW或复合类型显示为单个字段(或未扩展)时的显示方式:例如,如果执行SELECT * FROM test_emp
, *
将所有字段分别作为单独的列返回;但是,如果您执行SELECT test_emp FROM test_emp
,则会返回未展开的表行,因此看起来像这样:
(1,a1)
(2,a2)
(3,a3)
和复合类型完全相同。 i tab_small_str;
-将i
视为test_emp
,其中包含可以扩展的字段。在您的代码中,您正在打印对象i
,而不是i.*
或i.str
。因此,将代码更改为:
FOREACH i IN ARRAY v_ename
LOOP
RAISE NOTICE '%', i.str;
END LOOP;