динамический запрос sql в postgres

Я пытался использовать Dynamic SQL для выполнения некоторых запросов в postgres.

Пример:

EXECUTE format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition)))

Мне нужно запросить таблицу, имеющую форму result_% s_table, в которой мне нужно заменить правильное имя таблицы (идентификатор) из другой таблицы.

Я получаю сообщение об ошибке ERROR: prepared statement "format" does not exist

Ссылка: подстановка строки с результатом запроса postgresql


person psteelk    schedule 08.10.2012    source источник


Ответы (5)


EXECUTE ... USING работает только в PL / PgSQL, то есть внутри функций или _ 2_ блоков, написанных на языке PL / PgSQL. Это не работает в простом SQL; EXECUTE в простом SQL полностью отличается от выполнения подготовленных операторов. Вы не можете использовать динамический SQL непосредственно в диалекте SQL PostgreSQL.

Сравнивать:

См. Второй последний параграф в моем предыдущем ответе.


В дополнение к тому, что вы не работаете, кроме PL / PgSQL, ваш оператор SQL неверен, он не будет делать то, что вы ожидаете. Если (select id from ids where condition = some_condition) возвращает, скажем, 42, оператор завершится ошибкой, если id является целым числом. Если его преобразовать в текст, вы получите:

EXECUTE format('SELECT * from result_%s_table', quote_ident('42'));
EXECUTE format('SELECT * from result_%s_table', '"42"');
EXECUTE 'SELECT * from result_"42"_table';

Это неверно. Вы действительно хотите result_42_table или "result_42_table". Вам нужно было бы написать что-то вроде:

EXECUTE format('SELECT * from %s', quote_ident('result_'||(select id from ids where condition = some_condition)||'_table'))

... если вы должны использовать quote_ident.

person Craig Ringer    schedule 08.10.2012
comment
В дополнение, блок DO всегда возвращает void и не принимает никаких параметров, поэтому я думаю, что OP ограничен функцией. - person Clodoaldo Neto; 08.10.2012
comment
@Clodoaldo Хороший момент - они могут выполнять SELECT, но это не принесет им никакой пользы, если они не сделают что-то действительно окольное, например SELECT ... INTO временную таблицу. - person Craig Ringer; 08.10.2012
comment
@CraigRinger Привет, я знаю, что немного опоздал на вечеринку, но не могли бы вы предложить какой-нибудь хороший учебник по динамическому sql в postgreSQL? Я не могу найти ни одного. Я хочу создать универсальный динамический запрос. Если хотите, проверьте этот вопрос. Спасибо - person slevin; 12.01.2018
comment
Вы не можете использовать динамический SQL непосредственно в диалекте SQL PostgreSQL. На самом деле вы можете, по крайней мере, с помощью query_to_xml. См. stackoverflow.com/a/38684225/3935325 - person villasv; 10.04.2019
comment
Есть ли какое-либо расширение для postgres для программного создания динамических параметров sql с заданными параметрами? - person Behnam Esmaili; 14.05.2020

CREATE OR REPLACE FUNCTION public.exec(
text)
RETURNS SETOF RECORD
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN 
    RETURN QUERY EXECUTE $1 ; 
END 
$BODY$;

использование:

select * from exec('select now()') as t(dt timestamptz)
person Inshua    schedule 13.10.2017
comment
Это просто и очень удобно для повседневной работы ... Покажите, как использовать динамический запрос в качестве обычного запроса! - person Peter Krauss; 29.11.2018
comment
Чудесно! безопасно только чтение запускать динамический SQL. . выберите * из run_select («обновить набор i = 5;») как t (account_id int); ОШИБКА: невозможно открыть запрос UPDATE как курсор; - person Charlie 木匠; 23.07.2021

Попробуйте использовать

RETURN QUERY EXECUTE '<SQL Command>'

Это вернет данные в виде таблицы. Вы должны использовать это в сохраненной функции PostgreSQL.

Я уже создал полную демонстрацию настраиваемого фильтра и настраиваемой сортировки с использованием динамического запроса PostgreSQL. Посетите этот URL: http://www.dbrnd.com/2015/05/postgresql-dynamic-sql/

person Anvesh    schedule 22.08.2015

Все это выглядит сложнее, чем вопрос ОП. Другое форматирование должно помочь ... но это может быть абсолютно так, что я не понимаю.

Судя по тому, как я прочитал вопрос OP, я думаю, что другие в аналогичной ситуации могут извлечь выгоду из того, как я его получил.

Я использую Postgre для Redshift, и я столкнулся с этой проблемой и нашел решение.

Я пытался создать динамический запрос, вставив свою дату.

date = dt.date(2018, 10, 30)

query = ''' select * from table where date >= ''' + str(my_date) + ''' order by date '''

Но запрос полностью игнорирует условие при его вводе таким образом.

Однако, если вы используете знак процента (%), вы можете правильно вставить дату.

Один из правильных способов написать приведенное выше утверждение:

query = ''' select * from table where date >= ''' + ''' '%s' ''' % my_date + ''' order by date '''

Так что, может быть, это полезно, а может быть, нет. Надеюсь, это поможет хоть одному человеку в моей ситуации!

С наилучшими пожеланиями.

person spen.smith    schedule 31.10.2018

EXECUTE будет работать только в среде pl / pqsql.

вместо EXECUTE попробуйте с SELECT

 SELECT format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition))

вывод будет динамическим запросом.

person solaimuruganv    schedule 08.10.2012
comment
Текст динамического запроса, конечно, но он не будет выполнять запрос. Смотрите предыдущий связанный пост. - person Craig Ringer; 08.10.2012
comment
да, я прошел через подробное динамическое выполнение qry, здесь только то, что я упомянул, EXECUTE будет работать только в среде pl / pqsql, и когда я опубликовал свой ответ, я действительно не заметил вашего ответа. - person solaimuruganv; 08.10.2012
comment
Не беспокойся. Он просто не отвечает на вопрос, как выполнить динамический SQL. - person Craig Ringer; 08.10.2012
comment
тогда приведенный выше оператор должен быть в блоке pl / pqsql, который я упомянул в самой первой строке. - person solaimuruganv; 08.10.2012
comment
Я подумывал о голосовании против, потому что, как было сказано, это не выполняет блок. НО нетрудно взять результат запроса и снова передать его как другой вызов запроса, динамический контент является доверенным. Таким образом, это решает проблему и теоретически позволяет избежать инъекций. - person John White; 27.04.2019