2013-04-30 5 views
1

Я хотел бы знать, как использовать динамический запрос внутри функции. Тем не менее, я пробовал много способов, когда пытаюсь скомпилировать мою функцию, появляется сообщение SQL 42601.PostgreSQL - состояние SQL: 42601 ошибка синтаксиса

код, который я использую: сообщение

CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text) 
RETURNS TABLE (name text, rowcount integer) AS 
$$ 
BEGIN 
    WITH v_tb_person AS (return query execute sql) 
    select name, count(*) from v_tb_person where nome like '%a%' group by name 
    union 
    select name, count(*) from v_tb_person where gender = 1 group by name; 
END  
$$ LANGUAGE plpgsql; 

Ошибки я получаю:

ERROR: syntax error at or near "return" 
LINE 5:  WITH v_tb_person AS (return query execute sql) 

Я попытался с помощью:

WITH v_tb_person AS (execute sql) 

WITH v_tb_person AS (query execute) 

WITH v_tb_person AS (return query execute) 

Что не так? Как я могу решить эту проблему?

Сво вопрос, связанный с PostgreSQL equivalent of Oracle “bulk collect”

+0

Это явно синтаксис plpgsql. Что такое тег '[Oracle]' здесь? –

+0

@ErwinBrandstetter Предыдущий вопрос был о переводе PL/SQL на PL/PgSQL, поэтому, возможно, это было перенесено. Я удалил тег. –

+0

Одной вещью, которую стоит попробовать, является документация. Много усилий идет в документации PostgreSQL (и PL/PgSQL). В этом случае вам нужно начать с [Динамических операторов в PL/PgSQL] (http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN) , –

ответ

2

вашей функции будет работать следующим образом:

CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text) 
RETURNS TABLE (name text, rowcount integer) AS 
$$ 
BEGIN 

RETURN QUERY EXECUTE ' 
WITH v_tb_person AS (' || sql || $x$) 
SELECT name, count(*)::int FROM v_tb_person WHERE nome LIKE '%a%' GROUP BY name 
UNION 
SELECT name, count(*)::int FROM v_tb_person WHERE gender = 1 GROUP BY name$x$; 

END  
$$ LANGUAGE plpgsql; 

Вызов:

SELECT * FROM prc_tst_bulk($$SELECT a AS name, b AS nome, c AS gender FROM tbl$$) 
  • Вы не можете смешивать равнину и динамический SQL так, как вы пытался это сделать. Весь оператор является либо динамическим, либо простым SQL. Поэтому я создаю одно динамическое заявление, чтобы сделать эту работу. Вы можете быть заинтересованы в главе о executing dynamic commands in the manual.

  • Совокупное функция возвращает count()bigint, но ты rowcount определяется как integer, так что вам нужно явное приведение ::int, чтобы сделать эту работу

  • Я использую dollar quoting, чтобы избежать процитировать ад.

Однако, как это должно быть приманка для SQL injection атак или вы серьезно собираетесь его использовать? Для вашего очень частного и безопасного использования это может быть нормально, хотя я бы даже не доверял себе такой функцией. Если есть доступ к ненадежным пользователям, такая функция является загруженным лапкой. Это невозможно. сделайте это безопасным.

Крейг (заклятый враг инъекции SQL!) Может получить легкий ход, когда он увидит, что вы подделали из его фрагмента кода в ответ на your preceding question. :)

Сам запрос кажется довольно странным, кстати. Но это не относится к делу.

+0

Я на самом деле думаю, что это нечто меньшее, чем принятие непроверенных параметров.Если вы принимаете все необработанные SQL-заявления, вы уже знаете, что ваши входы должны поступать от полностью доверенного источника или источника с тем же самым уровнем, который выполняет функция. Теперь, если бы это была функция 'SECURITY DEFINER' тоже ... –

+0

@CraigRinger: В целом, я надеюсь, что не полностью исказил вас своим замечанием. В этом случае я должен удалить его. –

+1

Нет, все хорошо. Это все еще дает мне подергивания, которые я заверяю вас. –

Смежные вопросы