2017-05-26 78 views
-3

功能我有一个表人员enter image description here创建循环甲骨文

我想,当我打电话功能select functionname(443) from dual它返回序列staff_id创建功能。

例如

1. select functionname(443) from dual return 863; 
2. select functionname(443) from dual return 864; 
3. select functionname(443) from dual return 866; 
. 
. 
. 
n. select functionname(443) from dual return 6733; 

和863; 864; 866 ... 6733

+1

这不是很清楚。你有一张表,但你想要一个函数来对这张表进行查询,但是在一个双重查询中?你不能简单地查询你的表吗?这个函数的返回类型应该是什么。此外,请发布数据作为格式化文本,[不截图](http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-of-code-on-so-when-问一个问题/ 285557#285557) – Aleksej

+0

那么你想从一个你不从纯SQL获得的函数中获得什么好处?从dept_id = 443'的staff中选择staff_id? – APC

+0

当我第一次调用函数时,首先返回staff_id = 1; 当我第二次调用函数时,它首先返回staff_id = 2; 当我n次调用函数时,首先返回staff_id = n; 然后循环再次重复 – Tiko

回答

2

“时我第一次呼叫功能它返回第一staff_id = 1;当我第二次呼叫功能它返回第一staff_id = 2;当我n个时间呼叫功能它返回第一staff_id = N;且之后,循环再次重复“

程序思维通常是一种代码味道。关系数据库用于处理数据集。但是,到底什么时候,让我们享受一些午餐时间的乐趣吧:

我们需要一个包,因为包变量允许我们维护函数调用的状态。 (有这样做的其他方式,如上下文的命名空间,但一个包是容易实现的。)

create or replace package pkg_test is 
    function get_staff_id (p_dept_id number) return number; 
end pkg_test ; 
/

create or replace package body pkg_test is 
    -- variables to maintain state across function calls 
    ids_nt dbms_utility.number_array; 
    idx number := 0; 
    last_dept_id number := 0; 

    function get_staff_id (p_dept_id number) return number 
    is 
     return_value number; 
    begin 
     if idx = 0 
     or last_dept_id != p_dept_id 
     then 
      select staff_id 
      bulk collect into ids_nt 
      from staff 
      where dept_id = p_dept_id; 

      last_dept_id := p_dept_id; 
      idx := 0; 
     end if; 

     idx := idx + 1; 
     return_value := ids_nt(idx); 
     if idx = ids_nt.count() then 
      idx := 0; 
     end if; 

     return return_value; 
    end get_staff_id ; 
end pkg_test ; 
/

注意

  1. 保持这样的全局状态一般不考虑好实践。它在这里工作,但在更复杂的过程中,状态很容易被我们不期望的调用改变。
  2. 状态保持在会话级别。两个单独的会话将获得两组数据,而不是一个交错组。所以对于使用连接池的应用程序来说这不是一个好的实现。
+0

当我调用它时,一个问题,但改变dep_id,它返回null – Tiko

+0

@Tiko - 星期五午餐时间有趣的问题是它往往导致错误:)我们需要重置计数器时重新填充数组。我已经修复了代码,现在就试用它。 – APC

0

我打算做一个假设,你想要做的是调用一个函数返回所有您传递的dept_id的staff_ids。这是一个假设,因为您根本不清楚问题中的要求。

CREATE OR REPLACE TYPE staff_res_t AS OBJECT (staff_id NUMBER) 

CREATE TYPE staff_res_tab AS TABLE OF staff_res_t 

CREATE OR REPLACE FUNCTION getdept(in_dept NUMBER) 
    RETURN staff_res_tab 
    PIPELINED 
IS 
    CURSOR c_staff 
    IS 
     SELECT staff_id 
     FROM you_table 
     WHERE dept = in_dept; 

    out_rec staff_res_t := staff_res_t(NULL); 
BEGIN 
    FOR rec_staff IN c_staff 
    LOOP 
     out_rec.staff_id := rec_staff.staff_id; 
     PIPE ROW (out_rec); 
    END LOOP; 

    RETURN; 
END;  

SELECT * FROM TABLE(getdept(443))