2012-08-07 63 views
0

我需要优化PL/SQL函数,目前像上建立光标:如何基于阵列

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_input number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT n_number FROM t_table WHERE n_prop_1=n_input OR n_prop_2=n_input OR n_prop_3=n_input; 
BEGIN 
    ret := t_table_of_number(); 

    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

我希望能够给数组作为参数,但是,我不不知道如何构建我的游标以获取数组。我想我可以使用IN声明,但可以帮我解决这个问题吗?

编辑:

Justin Cave提供的解决方案,它会成为:

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT n_number FROM t_table WHERE n_prop_1 IN (SELECT column_value FROM TABLE(n_inputs)) 
              OR n_prop_2 IN (SELECT column_value FROM TABLE(n_inputs)) 
              OR n_prop_3 IN (SELECT column_value FROM TABLE(n_inputs)); 
BEGIN 
    ret := t_table_of_number(); 

    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

然而,多个SELECT column_value FROM TABLE(n_inputs)减慢整个功能。我该如何改进?

+0

更好的你想'n_input'值的集合来传递?或者你在找别的东西吗? – 2012-08-07 15:44:07

+0

是的,我想通过一个n_input集合 – 2012-08-07 16:18:40

+0

什么是现有查询的查询计划?新查询的查询计划是什么? “减慢整个功能”究竟意味着什么?也就是说,如果原始函数花费了1秒来执行单个输入,那么当输入是N个元素时,修改后的函数是否需要2 * N秒才能执行? 't_table'中有多少行?哪些索引可用?你是否事先(粗略地)知道传入的数组中有多少元素? – 2012-08-07 16:27:05

回答

2

如果你想n_input值的集合来传递和返回相同的t_table_of_number集合(即你不需要知道哪些输出数组的元素与该输入数组的元素相关联)

CREATE OR REPLACE FUNCTION tkt_get_underlying(p_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c 
     IS SELECT n_number 
      FROM t_table 
      WHERE n_prop IN (SELECT column_value 
           FROM TABLE(p_inputs)); 
BEGIN 
    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

这假设将要插入到ret集合中的元素数量仍然可以同时保存在PGA内存中。根据具体情况,您可能需要将其转换为流水线表函数,以限制所需的PGA内存量。

+0

你好贾斯汀,你的解决方案可行,但我不够精确。你能否在编辑的问题上给我一些专业知识? – 2012-08-07 16:17:41

1

Oracle使用嵌套表获得基数错误,因为它不知道实际存在多少行。尝试使你的函数看起来像:

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT n_number FROM t_table WHERE n_prop_1 IN (SELECT /*+ cardinality(ni 1) */ column_value FROM TABLE(n_inputs) ni) 
              OR n_prop_2 IN (SELECT /*+ cardinality(ni 1) */ column_value FROM TABLE(n_inputs) ni) 
              OR n_prop_3 IN (SELECT /*+ cardinality(ni 1) */ column_value FROM TABLE(n_inputs) ni); 
BEGIN 
    ret := t_table_of_number(); 

    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

注意,如果你知道你在嵌套表指望有多少行,让你的基数提示准确。另外,如果在嵌套表中放置太多行,Oracle可能会以次优方式执行操作,因为您认为嵌套表中的行数少于实际使用的行数。

+0

嗨,感谢您对基数的意见,我不知道它是否真的有帮助,但它并没有伤害。我找到了一个使用JOIN的解决方案 – 2012-08-08 10:36:42

0

谢谢你的帮助,我终于找到符合我需求的优化。现在查询是这样的:

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT t.n_number FROM t_table t, (SELECT column_value /*+cardinality(t_inputs 100) */ c FROM TABLE(n_inputs)) t_inputs 
       WHERE t_inputs.c = t.n_prop_1 
       OR t_inputs.c = t.n_prop_2 
       OR t_inputs.c = t.n_prop_3; 
BEGIN 
    ret := t_table_of_number(); 
    OPEN c; 
    FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 
    RETURN ret; 
END; 

它做了一个连接比一个IN