Есть ли способ выполнить запрос внутри значения строки (например, eval) в PostgreSQL?
Я хочу сделать вот так:
SELECT (EVAL 'SELECT 1') + 1;
Есть ли способ сделать это (EVAL
) в PostgreSQL?
Ответы
Ответ 1
Если утверждения, которые вы пытаетесь "eval", всегда возвращают один и тот же тип данных, вы можете написать функцию eval(), которая использует EXECUTE, упомянутую Grzegorz.
create or replace function eval(expression text) returns integer
as
$body$
declare
result integer;
begin
execute expression into result;
return result;
end;
$body$
language plpgsql
Тогда вы могли бы сделать что-то вроде
SELECT eval('select 41') + 1;
Но этот подход не будет работать, если ваши динамические операторы возвращают что-то другое для каждого выражения, которое вы хотите оценить.
Также имейте в виду, что это создает огромный риск для безопасности за счет запуска произвольных операторов. Если это проблема, зависит от вашей среды. Если это используется только в интерактивных сеансах SQL, это не проблема.
Ответ 2
ПРИМЕЧАНИЯ
Синтаксис языка PLpgSQL имеет много способов сказать:
Y := f(X);
Предложение EXECUTE
предназначено только для "динамического исполнения" (меньше производительности),
EXECUTE 'f(X)' INTO Y;
Используйте Y := f(X);
или SELECT
для выполнения статических объявлений,
SELECT f(X) INTO Y;
Используйте PERFORM statment при отбрасывании результатов или работе с возвратами void:
PERFORM f(X);
Ответ 3
Я бы пошел с текстом типа данных, так как он более гибкий, используя при этом следующие операторы литья, такие как ::int
:
create or replace function eval( sql text ) returns text as $$
declare
as_txt text;
begin
if sql is null then return null ; end if ;
execute sql into as_txt ;
return as_txt ;
end;
$$ language plpgsql
-- select eval('select 1')::int*2 -- => 2
-- select eval($$ select 'a'||1||'b' $$) -- => a1b
-- select eval( null ) -- => null
Я также добавил эту и другую eval( sql, keys_arr, vals_arr )
функцию, поддерживающую некоторые пользовательские подстановки значений ключа, , например. для удобных :param1
подстановок в postgres-utils
Ответ 4
Я не уверен, подходит ли он вам, но PostgreSQL имеет EXECUTE
.
Ответ 5
Хорошая идея. Вы можете изменить для выполнения прямых выражений:
create or replace function eval(expression text) returns integer
as
$body$
declare
result integer;
begin
execute 'SELECT ' || expression into result;
return result;
end;
$body$
language plpgsql;
Для запуска просто введите это:
SELECT eval('2*2');