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)减慢整个功能。我该如何改进呢?

4

3 回答 3

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 内存量。

于 2012-08-07T15:48:00.130 回答
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 可能会表现不佳,因为您让它认为嵌套表中的行数比它实际拥有的行数少。

于 2012-08-07T20:49:04.893 回答
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;

它的 JOIN 比 IN 更好

于 2012-08-08T10:35:57.137 回答