【问题标题】:How to return a set of results from one Oracle subprogram to another?如何将一组结果从一个 Oracle 子程序返回到另一个?
【发布时间】:2017-09-01 16:54:40
【问题描述】:

这是我尝试做的简化版本,但假设我想选择其经理在给定部门的所有员工。我可以有如下 SQL 查询:

SELECT employees.id
  FROM employees
 WHERE employees.manager IN (SELECT managers.id
                               FROM managers
                              WHERE managers.dept = 12)
;

但是假设我想将管理器子查询抽象为 PL/SQL 子程序。我该怎么做?
我使用过的存储过程(主要由其他开发人员编写)往往具有由 PHP 调用代码映射到 PHP 数组的参数。我真的没有任何从另一个调用一个存储过程的经验。

我想做的是有这样的东西:

SELECT employees.id
  FROM employees
 WHERE employees.manager IN my_stored_procedure(12)
;

然后my_stored_procedure 将为输入参数输出一组经理 ID(在本例中为 12)。

【问题讨论】:

  • 是过程还是函数(我认为是函数)

标签: sql oracle stored-procedures plsql


【解决方案1】:

不可能完全按照您发布的方式进行,但如果经理的选择不简单,您可以通过视图将其抽象或使用返回表格的函数,如下所示:

SELECT employees.id
  FROM employees
 WHERE employees.manager IN (SELECT * from TABLE(get_managers_from_dept(12)));

在这个链接中有一个这种方法的例子: Function or Procedure for an IN clause

【讨论】:

    【解决方案2】:

    要从另一个存储过程调用一个存储过程,您只需要从主过程调用它,如下所述。这个 Main Proc 可以由 PHP 代码调用/启动。

    PROCEDURE some_sp
           AS
           BEGIN
              some_other_sp('parm1');
           END;
    

    【讨论】:

    • 是的,但我不确定的是从第一个调用的 proc 的结构。 IE。如何为调用过程输出一组结果
    【解决方案3】:

    虽然不那么直接,但您可以通过使用动态 sql 来完成它。这是您的存储过程的结构。它返回给定部门的 manager_id 的逗号分隔列表。

    CREATE OR REPLACE FUNCTION my_stored_procedure(
        p_dept NUMBER)
      RETURN VARCHAR2
    IS
      v_manager_list VARCHAR2(1000);
    BEGIN
      SELECT m.id INTO v_manager_list FROM managers m WHERE m.dept = p_dept;
      RETURN '('||v_manager_list||')';
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
      RETURN '(NULL)';
    END;
    /
    

    现在不能用这个直接查询为...IN my_stored_procedure(12), 相反,您必须使用动态提取到集合中。

    SET SERVEROUTPUT ON;
    DECLARE
    TYPE v_emp_type
    IS
      TABLE OF employees.id%TYPE;
      v_emp v_emp_type;
    BEGIN
      EXECUTE IMMEDIATE 'SELECT employees.id 
    FROM employees 
    WHERE employees.id IN '|| my_stored_procedure(100) BULK COLLECT INTO v_emp ;
      FOR i IN v_emp.FIRST..v_emp.LAST
      LOOP
        DBMS_OUTPUT.PUT_LINE(v_emp(i));
      END LOOP;
    END;
    /
    

    【讨论】:

    • 这个解决方案似乎有点老套。我正在寻找一个可扩展的解决方案。您的 v_manager_list VARCHAR2 有长度限制,通常感觉有点复杂。我试图让事情保持简单和优雅。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    • 2017-11-17
    • 1970-01-01
    • 2021-06-25
    相关资源
    最近更新 更多