首页 > 解决方案 > 与 postgresql 中的数组相关的错误“错误:格式错误的记录文字:”

问题描述

我正在尝试将表中的值放入数组中,并且数组定义与表的列定义不同。我试过做演员,但它不工作。基本上我需要表中的值作为数组(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)。你能建议一下吗?

标签: postgresqlplpgsql

解决方案


您的新类型不是“单字段数据类型”,因为需要更好的描述,您可以VARCHAR(10)直接将其转换为 a ;它是一个包含单个字段的 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;- 认为ias test_emp,其中包含可以扩展的字段。在您的代码中,您正在打印 object i,而不是i.*or i.str。因此,将您的代码更改为:

FOREACH i IN ARRAY v_ename
LOOP 
   RAISE NOTICE '%', i.str;
END LOOP;

推荐阅读