Ошибка, связанная с массивами в postgresql «ОШИБКА: неправильный литерал записи:» - PullRequest
0 голосов
/ 05 декабря 2018

Я пытаюсь получить значения из таблицы в массив, и определение массива отличается от определения столбца таблицы.Я пытался сделать бросок, но это не работает.В основном мне нужны в виде массива (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).Можете ли вы предложить на это?

1 Ответ

0 голосов
/ 05 декабря 2018

Ваш новый тип не является «типом данных с одним полем», из-за отсутствия лучшего описания, где вы можете привести что-то вроде VARCHAR(10) непосредственно к нему;это строка, содержащая одно поле.Поэтому что-то вроде 'blah'::tab_small_str терпит неудачу, потому что он пытается привести этот текст к типу, который содержит поле, а не само поле.

Чтобы решить, используя существующий запрос:

SELECT ename::tab_small_str FROM test_emp

Измените на:

SELECT ROW(ename)::tab_small_str FROM test_emp

Почемуваши результаты заключены в квадратные скобки: именно так отображается строка или составной тип, когда отображается как одно поле (или не развернуто): например, если вы наберете 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;
...