2013-11-11 3 views
3

Я пытаюсь вызвать функцию внутри функции, используя sql в postgres 9.3.Вызов хранимой процедуры в хранимой процедуре

Этот вопрос относится к another post by me.

Я написал ниже функцию. До сих пор мне не удалось включить какой-либо оператор save-output (COPY), поэтому я пытаюсь обойти это, создав функцию отложенной функции.

CREATE FUNCTION retrieve_info(TEXT, TEXT) RETURNS SETOF 
retrieve_info_tbl AS $$ 
SELECT tblA.id, tblA.method, tblA.species, tblA.location 
FROM tblA 
WHERE method=$1 AND species=$2 
GROUP BY id, method, species 
ORDER BY location 
$$ LANGUAGE 'sql'; 

Вышеуказанная функция работает.

Попытка создать вложенную функцию.

CREATE FUNCTION print_out(TEXT, TEXT) RETURNS void AS $$ 
COPY (SELECT * FROM retrieve_info($1, $2)) TO 'myfilepath/test.csv'  
WITH CSV HEADER; 
$$ LANGUAGE 'sql'; 

Вызов вложенных функций.

SELECT * FROM print_out('mtd1','sp1'); 

ВЫВОД

выше дает это ERROR: column "$1" does not exist SQL state: 42P02 Context: SQL function "print_out" statement 1. Однако, когда подставляя arg1, arg2 в print_out() с 'mtd1', '' sp1 правильный вывод распечатывается на test.csv (как показано ниже)

id | method | ind | location 
---------------------------- 
1a | mtd1 | sp3 | locA 
1d | mtd1 | sp3 | locB 

Как бы я получить arg1, arg2 из retrieve_info() для правильного вызова arg1, arg2 в print_out()?

Я полностью застрял. Поблагодарили бы любые указатели, спасибо

+0

тесно связаны: http://stackoverflow.com/questions/16019508/copy-with-dynamic-file-name/16021835# 16021835 и http://stackoverflow.com/questions/16991383/postgres-copy-from-variable-with-csv-data/16991854#16991854 –

ответ

4

COPY немного странно, как это своего рода относится к своему query аргумент в виде строки, даже если она не записана в виде строки. Результатом является то, что query:

SELECT * FROM retrieve_info($1, $2) 

не выполняется в контексте функции, она выполняется в контексте самого COPY. Даже если вы говорите:

copy (select * from t) ... 

лечится более, как если бы Вы писали:

copy 'select * from t' ... 

так к тому времени, запрос выполняется, параметры функции больше не имеют никакого значения, то query аргумент COPY может выглядеть так, как будто она будет вести себя как закрытие на других языках, но это не так, она больше напоминает строку, которая передается в eval.

Вы можете обойти эту странность, используя обычный Kludge of Last Resort: dynamic SQL. Вы должны получить лучшие результаты, если написать функцию, чтобы использовать строку пререканий и EXECUTE:

create or replace function print_out(text, text) returns void as $$ 
begin 
    execute 'copy (' 
     || 'select * from retrieve_info' 
     ||  '(' || quote_literal($1) || ',' || quote_literal($2) || ')' 
     || ') to ''myfilepath/test.csv'' with csv header;'; 
end; 
$$ language plpgsql; 
+0

Спасибо за ваш ответ и объяснение. Вышеупомянутый код не работает с 'c' csv. Изменение его на просто ... '.csv '' '';' (думаю, что я где-то это видел), похоже, работает, но называя его, я получаю сообщение «ERROR: function print_test (неизвестно, неизвестно) не существует Состояние SQL: 42883 Подсказка: никакая функция не соответствует данным имени и типам аргументов. Возможно, вам придется добавлять явные типы. Характер: 15' –

+0

Я не вижу ни одного 'print_test' в любом месте. Это сработало для меня, как и в моем ответе, где-то вы испортили вложенные цитаты? –

+0

Да, извините. Они называются немного разными в реальном коде. Я думаю, что это выглядит правильно (?), Пожалуйста, посмотрите на этот [экран печати] (http://i1326.photobucket.com/albums/u642/Awful-Dodger/ScreenShot2013-11-14at75409PM_zps5a693e66.png) –

0

Есть x и y цитируется умышленно?

COPY (SELECT * FROM retrieve_info('x','y')) TO 'myfilepath/test.csv' 

Вы не посылать x и y аргументы в print_out к retrieve_info - скорее, вы отправляете строки 'x' и 'y'. Предполагая, что у вас нет записей с method='x' AND species='y', неудивительно, что вы не получите никаких результатов.

Попробуйте вместо этого:

COPY (SELECT * FROM retrieve_info(x,y)) TO 'myfilepath/test.csv' 
+0

Спасибо за комментарий. Да, ты прав. Глупо мне оставлять цитаты (теперь удалены). Я уже тестировал без, но получаю это сообщение об ошибке после вызова функции 'ERROR: столбец« x »не существует Состояние SQL: 42703 Контекст: SQL-функция« print_out »statement 1' –

+0

не должна be @x и @y, поскольку они передаются в переменных? – Matt

+0

@Erwin Brandstetter: Так как вы смогли мне помочь раньше, возможно, вы тоже можете это сделать? Вы знаете, как, например, добавить инструкцию COPY внутри функции и/или вызвать функцию внутри функции? Поблагодарите любую помощь по этому поводу, спасибо –

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