【问题标题】:how to call postgresql stored procs from inside another stored proc and include return values in queries如何从另一个存储过程中调用 postgresql 存储过程并在查询中包含返回值
【发布时间】:2013-07-09 23:04:29
【问题描述】:

我有一个 postgresql 函数/存储过程,它执行以下操作: 1. 调用另一个函数并将值保存到变量中。 2. 使用我从第一步获得的值作为参数执行另一个 sql 语句。

我的问题是查询没有返回任何数据。也不返回任何错误。 我只是 postgresql 的新手,所以我不知道调试的最佳方法......但我在第 1 步之后添加了一个 RAISE NOTICE 命令,如下所示:

SELECT INTO active_id get_widget_id(widget_desc);
RAISE NOTICE 'Active ID is:(%)', active_id;

在 pgadmin3 屏幕的“消息”部分,我看到带有数据的调试消息:

注意:活动 ID 为:(2)

我想知道括号是否对我造成了问题。
这是我在第 2 步中尝试运行的 sql:

        SELECT d.id, d.contact_id, d.priority, cp.contact
        FROM widget_details d, contact_profile cp, contact_type ct
        WHERE d.rule_id=active_id
        AND d.active_yn = 't'
        AND cp.id=d.contact_id
        AND cp.contact_type_id=ct.id
        AND ct.name = 'email'
        Order by d.priority ASC

您会注意到,在我的 where 子句中,我引用了变量“active_id”。 我知道这个查询应该至少返回一行,因为当我运行一个直接的 sql 选择(而不是使用这个函数)并将值 2 替换为变量“active_id”时,我得到了我正在寻找的数据。

任何建议将不胜感激。

谢谢。

编辑 1:

这是完整的函数定义:

CREATE TYPE custom_return_type AS (
    widgetnum integer,
    contactid integer,
    priority integer,
    contactdetails character varying
);

CREATE OR REPLACE FUNCTION test(widget_desc integer)
  RETURNS SETOF custom_return_type AS
$BODY$
DECLARE 
     active_id integer; 
     rec custom_return_type ;

BEGIN
SELECT INTO active_id get_widget_id(widget_desc);
    RAISE NOTICE 'Active ID is:(%)', active_id;

FOR rec IN 
    SELECT d.id, d.contact_id, d.priority, cp.contact
        FROM widget_details d, contact_profile cp, contact_type ct
        WHERE d.rule_id=active_id
        AND d.active_yn = 't'
        AND cp.id=d.contact_id
        AND cp.contact_type_id=ct.id
        AND ct.name = 'email'
        Order by d.priority ASC
    LOOP
     RETURN NEXT rec;
END LOOP;   

 END
 $BODY$

【问题讨论】:

  • 你可能需要展示整个函数——或者至少是它的一个子集——以获得任何真正的帮助。您的函数是否定义为“RETURNS setof RECORD”或类似的东西?
  • bma,看看我的“EDIT 1”。谢谢。
  • 你是如何执行函数的?喜欢“select * from test(2)”?
  • 快速提示:您可以通过将函数定义为 RETURNS TABLE (....cols....) 来避免创建自定义类型。方便多了。
  • 那个函数永远不可能运行。您没有在任何地方定义widget_desc,而且您似乎也没有使用fmfm_number 参数。这真的是您遇到问题的确切、未经编辑的代码吗?还是您在发布之前对其进行了编辑而不重新测试?

标签: postgresql stored-procedures


【解决方案1】:

这太复杂了几个级别(编辑:事实证明Erwin already explained to you last time you posted the same thing)。首先使用RETURNS TABLERETURN QUERY

CREATE OR REPLACE FUNCTION test(fmfm_number integer)
RETURNS TABLE ( 
    widgetnum integer,
    contactid integer,
    priority integer,
    contactdetails character varying
) AS
$BODY$
BEGIN
    RETURN QUERY SELECT d.id, d.contact_id, d.priority, cp.contact
        FROM widget_details d, contact_profile cp, contact_type ct
        WHERE d.rule_id = get_widget_id(widget_desc)
        AND d.active_yn = 't'
        AND cp.id=d.contact_id
        AND cp.contact_type_id=ct.id
        AND ct.name = 'email'
        Order by d.priority ASC;
 END
 $BODY$ LANGUAGE plpgsql;

此时它可能很简单,可以变成一个微不足道的SQL 函数甚至是一个视图。很难确定,因为这个函数写的意义不大:

  • 您永远不会在任何地方使用参数fmfm_number;和
  • widget_desc 从未定义过

所以这个函数永远无法运行。显然,您没有向我们展示真正的源代码,而是某种与您真正遇到问题的代码不匹配的“简化”代码。

【讨论】:

  • 克雷格,你是对的。这不是真正的交易。我试图将代码简化为基础......但我会在这里尝试一些建议并回复。
  • craig,这个问题其实和上一个不一样。我使用了类似的代码,但概念不同。在这个例子中,我试图在另一个存储过程中调用一个存储过程。前面的例子只是关于如何返回自定义数据。说了这么多(只是为了澄清我的想法……)我已经实施了你和欧文提出的所有建议。问题是我认为我无法避免使用 plpgsql,因为我确实需要在直接 sql 之外执行其他逻辑。我更新了示例代码,使其更有意义。
  • @markli 嗯,我认为您需要展示一个包含架构和数据 (sqlfiddle.com) 的完整示例,因为这个 看起来 就像现在一样好书面。还有更多的事情发生,如果没有看到完整的行为示例,我不可能说出什么。
【解决方案2】:

两者之间有区别:
选择...
[http://www.postgresql.org/docs/current/interactive/sql-selectinto.html]

SELECT select_expressions INTO [STRICT] 目标 FROM ...;
[http://www.postgresql.org/docs/current/interactive/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW]

我想你想要:
SELECT get_widget_id(widget_desc) INTO active_id;

【讨论】:

  • 这给出了相同的结果。消息窗口中的相同消息,“数据输出”窗口中没有结果
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-17
  • 1970-01-01
相关资源
最近更新 更多