【问题标题】:How to get data from a pl/sql function if a parameter have more than one value in function with single parameters如果参数在具有单个参数的函数中具有多个值,如何从 pl/sql 函数中获取数据
【发布时间】:2019-10-11 06:59:15
【问题描述】:

我正在 pl/sql 中开发一个从函数中执行的游标获取数据集的过程。例如:

功能:

f_process_data(id_process IN NUMBER, id_product IN NUMBER)

返回:

v_result_cursor sys_refcursor;

但问题是,在搜索光标时,我需要同时发送多个 id_product。像这样的:

id_product:1240(香肠) id_product: 1260 (火腿)

¿如何在函数中发送(或获取)多个产品?

我知道循环是可能的,但是怎么做呢?

类似这样的东西(?):

v_sausage := 1240;
v_ham := 1260;

LOOP    
   IF v_count = v_sausage OR v_count = v_ham THEN 
   v_result_cursor := f_process_data(1, p_id_product);
   END IF;
   FETCH v_result_cursor
   INTO v_id, v_id_product;
   EXIT WHEN v_result_cursor%NOTFOUND;
END LOOP;

我预计 v_id 和 v_id_product 已记录在一个集合中,其中包括 id_product 1240 和 1260 的结果。

但是,如果业务规则发生变化并且不仅仅是 2 个产品,那么 100 或 1000 个产品呢?

注意:函数中的光标不可修改,id_product必须一一发送。

CURSOR cu_get_value_products IS
SELECT value FROM supplies WHERE id = p_id and id_product = p_id_product;

【问题讨论】:

  • @reymagnus 您希望如何格式化产品参数?如...你的偏好是什么?如果产品 ID,您希望参数是逗号分隔的列表吗? 1001,1002,1058,2105 作为 VARCHAR2?在首次使用产品 ID 构建该集合后,您是否想将数组/集合作为函数传递给您的 f_process_data()?您的问题有很多解决方案。
  • @Code新手函数中的光标按时间只得到一个id_product,无法更改。
  • @reymagnus 好的,那么您想要的是……为进入 f_process_data() 函数的每个 Product_ID 运行光标。如果是这种情况,您将不再返回 ref_cursor 并且需要返回其他内容。如果您无法更改光标。所以我现在的问题是,你能改变你的 f_process_data() 函数的返回类型,而不是返回你想要解析的数据的集合吗?
  • @Code Novice 该函数调用另一个函数,该函数调用另一个打开游标的函数,例如 f_open_cursor(query) 返回 sys_refcursor 并且仅在此函数内部: OPEN cursor FOR query;与我发布的示例相似,但由于保护这些代码,因此与原始示例不完全相同,对此感到抱歉-_-

标签: sql oracle function plsql parameter-passing


【解决方案1】:

由于信息有限,以下是我想出的。我仍然不知道您在问题中提到的 STATIC 光标发生了什么是在您的 f_process_data() 函数中定义的。由于我不知道该函数中的完整代码,我只是自己编写了自己的代码并将 CURSOR 声明为 SYS_REFCURSOR,因为这就是函数返回的内容。

请让我知道这是否可行,或者我是否遗漏了一些重要信息。我觉得我缺少关键信息,无法为您提供有用的解决方案。

我创建的名为 Products 的模型表包含以下列和数据。见图片。

DECLARE

  /* Store Ref Cursor returned by f_process_data() Function */
  v_result_cursor   SYS_REFCURSOR;

  /* Declare Record so we can store the data FETCHed from the Cursor */
  rec_products      products%ROWTYPE;

  /* Declare a couple Product Variables for Proof of Concept */
  v_sausage         NUMBER;
  v_ham             NUMBER;

  /* Store output */
  n_id              NUMBER;
  v_id_product      VARCHAR2(100);

  /* Declare Type of TABLE NUMBER */
  TYPE  nt_type IS TABLE OF NUMBER;

  /* Create Array/Table/Collection of type nt_type to store product ids */
  nt_product_ids    nt_type;

  /* Returns a Ref Cursor based on the product_id used as Input to this function */
  FUNCTION f_process_data(p_id_process IN NUMBER, p_id_product IN NUMBER)
  RETURN SYS_REFCURSOR
  AS
    /* Declare Ref Cursor that will be Returned */
    rc_result_cursor   SYS_REFCURSOR;    

  BEGIN 
    /* Open Ref Cursor based on Product ID parameter */
    OPEN rc_result_cursor FOR SELECT * FROM products WHERE item_id = p_id_product;

    RETURN rc_result_cursor;

  END f_process_data
  ;

BEGIN

  /* Set Product Variables to IDs */
  v_sausage       := 2002;
  v_ham           := 2009;

  /* Store product ids into a Number Table so we can Loop thru it */
  nt_product_ids  :=  nt_type (v_sausage,v_ham);

  FOR r IN nt_product_ids.FIRST .. nt_product_ids.LAST
  LOOP
    /* Get Ref Cursor using SINGLE Product ID */
    v_result_cursor := f_process_data(1, nt_product_ids(r));

    LOOP

    FETCH v_result_cursor INTO rec_products;

    n_id            :=  rec_products.item_id;
    v_id_product    :=  rec_products.item;

    EXIT WHEN v_result_cursor%NOTFOUND;

    dbms_output.put_line('Product_id: ' || n_id);
    dbms_output.put_line('Product: ' || v_id_product);  

    END LOOP; /* Cursor Loop */

    /* Close Cursor */
    CLOSE v_result_cursor;

  END LOOP; /* Product IDs Loop */

EXCEPTION WHEN OTHERS
  THEN CLOSE v_result_cursor;

END;

【讨论】:

  • 根据您的要求,我能够在不更改您的功能的情况下创建此解决方案 - FUNCTION f_process_data(p_id_process IN NUMBER, p_id_product IN NUMBER) RETURN SYS_REFCURSOR... 除了添加 p_,因为我喜欢以这种方式引用我的参数。跨度>
  • 你是对的。光标是静态的,这是我可以应用的解决方案。非常感谢。
  • 我试图实现这个并得到这个错误:ORA-01001:无效游标。它在进入第二个循环之前崩溃。
  • 一旦我可以访问数据库,我将展示我的代码。
  • @reymagnus 确保光标没有被关闭。如果您尝试从以前关闭的游标中获取,这是您将收到错误“无效游标”的一种方式。
【解决方案2】:

要一次发送多个要处理的产品,请在名为 ProductList 的数据库中创建一个用户定义的表类型。然后,您可以将产品列表作为参数发送到存储过程中。

【讨论】:

  • 但是,如果函数和光标一次只接收一个参数值,它是如何工作的?我不熟悉列表作为 pl/sql 函数中的参数,现在......
  • 不要使用函数或光标。
  • 函数或游标的使用不是可选的,因为这个对象不能被修改或删除,必须使用它们。全局存储过程调用函数f_process_data,这个函数执行一个游标,就是它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-10
  • 2019-01-16
  • 1970-01-01
  • 2019-10-24
相关资源
最近更新 更多