Функция динамического запроса Postgres
Мне нужно создать функцию, которая будет запускать запрос и возвращать результаты с именем таблицы, а имя столбца - это исправление, данное функции. В настоящее время у меня есть это:
CREATE OR REPLACE FUNCTION qa_scf(tname character varying, cname character varying)
RETURNS SETOF INT AS
$BODY$
BEGIN
RETURN QUERY SELECT * FROM tname WHERE cname !='AK' AND cname!='CK';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
Это дает мне ошибку "Relation" tname "des not exist" при запуске. Я новичок в создании функций для Postgres, поэтому любая помощь приветствуется. Я чувствую, что возвращение int неверно, но я не знаю, что еще нужно сделать, чтобы он возвращал все столбцы для возвращаемых строк. Спасибо!
Ответы
Ответ 1
Вы не можете использовать переменную вместо идентификатора. Вам нужно сделать это с помощью динамических запросов. Он будет выглядеть примерно так:
EXECUTE 'SELECT * FROM ' || quote_ident(tname)
|| ' WHERE ' || quote_ident(cname) || ' NOT IN (''AK'',''CK'');'
INTO result_var;
Если вы используете PostgreSQL 9.1 или выше, вы можете использовать функцию format(), которая упрощает построение этой строки.
Ответ 2
Имена таблиц и столбцов не могут быть указаны как параметры или переменные без динамического построения строки для выполнения в качестве динамического оператора. Postgres имеет отличную вводную документацию о выполнении динамических утверждений. Важно правильно указывать идентификаторы и литералы с помощью quote_ident()
или quote_literal()
. Функция format() помогает очистить динамическую конструкцию sql-оператора. Поскольку вы объявляете функцию для возврата SETOF INTEGER
, вы должны выбрать нужное целое поле, а не *
.
CREATE OR REPLACE FUNCTION qa_scf(tname text, cname text)
RETURNS SETOF INTEGER AS
$BODY$
BEGIN
RETURN QUERY EXECUTE format(
'SELECT the_integer_field FROM %I WHERE %I NOT IN (%L, %L)',
tname, cname, 'AK', 'CK'
);
END;
$BODY$
LANGUAGE plpgsql;