Оператор EXECUTE ... USING в PL / pgSQL не работает с типом записи? - PullRequest
6 голосов
/ 20 января 2010

Я пытаюсь написать функцию в PL / PgSQL, которая должна работать с таблицей, которую она получает в качестве параметра.

Я использую операторы EXECUTE..INTO..USING в определении функции для построения динамических запросов (это единственный способ, которым я знаю), но ... Я столкнулся с проблемой с типами данных RECORD.

Давайте рассмотрим следующий (чрезвычайно упрощенный) пример.

 -- A table with some values.
 DROP TABLE IF EXISTS table1;
 CREATE TABLE table1 (
     code INT,
     descr TEXT
 );

INSERT INTO table1 VALUES ('1','a');
INSERT INTO table1 VALUES ('2','b');


-- The function code. 
DROP FUNCTION IF EXISTS foo (TEXT);
CREATE FUNCTION foo (tbl_name TEXT) RETURNS VOID AS $$
DECLARE 
    r RECORD;
    d TEXT;
BEGIN
    FOR r IN
    EXECUTE 'SELECT * FROM ' || tbl_name
    LOOP
    --SELECT r.descr INTO d; --IT WORK
    EXECUTE 'SELECT ($1)' || '.descr' INTO d USING r; --IT DOES NOT WORK
    RAISE NOTICE '%', d;
END LOOP;

END;
$$ LANGUAGE plpgsql STRICT;

-- Call foo function on table1
SELECT foo('table1');

Выводит следующую ошибку:

ОШИБКА: не удалось определить столбец "descr" в типе данных записи

хотя синтаксис, который я использовал, мне кажется действительным. Я не могу использовать статический выбор (прокомментированный в примере), потому что я хочу динамически ссылаться на имена столбцов.

Итак ... кто-то знает, что не так с приведенным выше кодом?

Ответы [ 2 ]

7 голосов
/ 21 января 2010

Это правда. Вы не можете использовать запись типа вне пространства PL / pgSQL.

Значение RECORD действительно только в plpgsql.

вы можете сделать

EXECUTE 'SELECT $1.descr' INTO d USING r::text::xx;
2 голосов
/ 25 апреля 2013

$1 должно быть внутри ||, как || $1 ||, и давать правильные пробелы, тогда оно будет работать.

BEGIN

EXECUTE ' delete from  ' ||  quote_ident($1)  || ' where condition ';

END;
...