【问题标题】:Calling a stored procedure within a stored procedure在存储过程中调用存储过程
【发布时间】:2013-11-23 23:09:31
【问题描述】:

我正在尝试在 postgres 9.3 上使用 sql 在函数中调用函数。

这个问题与another post by me有关。

我写了下面的函数。到目前为止,我还没有合并任何类型的保存输出 (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。但是,当用 'mtd1','sp1' 替换 print_out() 中的 arg1、arg2 时,正确的输出会打印到 test.csv(如下所示)

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

如何让retrieve_info() 的arg1、arg2 在print_out() 中正确调用arg1、arg2?

我完全被困住了。不胜感激,谢谢

【问题讨论】:

标签: sql postgresql export-to-csv nested-function


【解决方案1】:

xy 是故意引用的吗?

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

您没有将print_outxy 参数发送到retrieve_info - 而是发送字符串'x''y'。假设您没有 method='x' AND species='y' 的记录,难怪您没有得到任何结果。

试试这个:

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

【讨论】:

  • 感谢您的评论。是的,你说的没错。我愚蠢地留下引号(现已删除)。我已经测试过了,但是在调用函数ERROR: column "x" does not exist SQL state: 42703 Context: SQL function "print_out" statement 1后得到这个错误信息
  • 不应该是@x和@y,因为它们是在变量中传递的吗?
  • @Erwin Brandstetter:既然你以前帮过我,也许你也可以试试看?你有什么想法吗?在函数中添加 COPY 语句和/或在函数中调用函数?非常感谢您的帮助,谢谢
  • @Matt:感谢您的评论。尝试 @x,@y, $x,$y 和 $1, $2 在 retrieve_info() 中引用 x, y 但没有成功...
  • 我有'未定义'参数 x, y 试图使用参考 $1, $2 使其成为可能
【解决方案2】:

COPY 有点奇怪,因为它在某种程度上将其 query 参数视为字符串,即使它没有写为字符串。结果是query:

SELECT * FROM retrieve_info($1, $2)

不在函数的上下文中执行,而是在 COPY 本身的上下文中执行。即使你说:

copy (select * from t) ...

它更像是你写的:

copy 'select * from t' ...

所以到执行查询时,函数参数不再具有任何意义,COPY 的 query 参数可能看起来像其他语言中的闭包,但实际上并非如此,它更像传递给 eval 的字符串。

您可以使用常用的 Kludge of Last Resort 来解决这种奇怪现象:dynamic SQL。如果您编写函数以使用字符串整理和执行,您应该会得到更好的结果:

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;

【讨论】:

  • 感谢您的回答和解释。上面的代码在with csv 处失败。将其更改为 ....csv'''';(我认为我在某处看到过)似乎有效,但调用它我收到消息 ERROR: function print_test(unknown, unknown) does not exist SQL state: 42883 Hint: No function matches the given name and argument types. You might need to add explicit type casts. Character: 15
  • 我在任何地方都看不到任何print_test。它对我有用,就像我的回答一样,您是否在某处弄乱了嵌套引号?
  • 是的,很抱歉。它们在实际代码中的调用方式略有不同。我认为它看起来正确(?),请看看这个print screen
  • 您在“to”之后缺少双引号:') to '/Users 应该是 ') to ''/Users
  • @jO。您可能对 format() 感兴趣,以简化字符串连接,同时自动引用值和标识符。我发布了几个相关的答案以及更多详细信息。 Like this onethis one
猜你喜欢
  • 2012-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多