1

给定以下 Oracle 函数:

CREATE or REPLACE FUNCTION foo(id NUMBER, category VARCHAR) RETURN CHAR IS

TYPE MY_ARRAY2 IS TABLE OF NUMBER;
MY_ARRAY MY_ARRAY2;

BEGIN

   SELECT my_id BULK COLLECT INTO my_array FROM my_table

   RETURN (
            CASE WHEN category = 'FOO' AND (id member of MY_ARRAY)
              THEN 'Y'
              ELSE 'N'
            END
   );
END;

查找的性质是什么:

   SELECT my_id BULK COLLECT INTO my_array FROM my_table

或者,换句话说,有什么我可以添加到这条线或其他地方来加快查找速度 - 也许是一个索引?

4

3 回答 3

3

您所能做的就是使用单个选择MAXCOUNT

AS
..
..

v_retval VARCHAR2(10);


SELECT MAX(CASE 
            WHEN category = 'FOO'
                AND id = my_id 
                THEN 'Y'
            ELSE 'N'
            END) INTO v_retval
FROM my_table;
RETURN v_retval;

这取决于字符串 "Y" > "N" 的事实。您也可以使用COUNT(CASE ..另一个案例where count > 1 THEN 'Y'

在 id (或表中引用的其他列)上添加索引将有助于加快查询速度

请注意,最好使用形式的过程参数p_idp_category避免冲突

于 2018-08-02T12:44:48.107 回答
2

BULK COLLECT只是一种用多行结果集填充 PL/SQL 集合(数组)的方法。没有它,我们只能用单行填充标量值。

在性能方面,最大的影响实际上是查询的效率,您可以按照通常的方式进行调整。否则,性能BULK COLLECT基本上是透明的 = 除非您选择很多(数千)行。这很重要,因为集合驻留在会话级内存中,因此如果您的 PGA 配置不当,非常大的集合(很多行、很多列)可能会导致分页(写入磁盘)。

如果您遇到内存问题,您可以使用BULK COLLECTLIMIT子句来获取记录的小子集并使用流水线函数实现将它们吐出。但是您确实应该首先查看填充查询的性能。

那么从数组中查找一个值是 O(n) 吗?

循环遍历集合是线性的(充其量)。使用 SQL 限制结果集通常比选择所有内容并在循环中过滤结果集更有效。SQL 在处理集合方面效率很高。换句话说,考希克的解决方案

于 2018-08-02T12:45:01.637 回答
0

这将更具可读性。当然,您可以将索引放在id表中的字段上。如果id不是主键(即可能有重复项),请使用ROWNUM = 1inWHERE子句。

FUNCTION foo(p_id NUMBER, p_category VARCHAR) RETURN CHAR IS
n NUMBER;
BEGIN
    SELECT id INTO n FROM table WHERE id = p_id AND p_category = 'FOO';
    RETURN 'Y';
EXCEPTION WHEN OTHERS THEN
    RETURN 'N';
END;
于 2018-08-02T13:40:47.713 回答