我正在Oracle中编写一些存储的函数。其中一个是一个非常基本的函数,它将字符串作为参数并返回另一个字符串。这是我的功能:
CREATE OR REPLACE
FUNCTION get_mail_custcode (
custcodeParam IN customer_table.custcode%TYPE)
RETURN VARCHAR2
IS
mail_rc contact_table.email%TYPE;
BEGIN
SELECT cc.email
INTO mail_rc
FROM contact_table cc, customer_table cu
WHERE cu.customer_id = cc.customer_id
AND cu.custcode like custcodeParam ;
RETURN mail_rc ;
END;
所以它不起作用..该功能似乎运行良好但是没有任何结束执行..该功能是工作时间和时间,我在2或3分钟后手动取消操作(此查询通常即时结果)。
在反复写入查询后,我最终(并随机)将cu.custcode like custcodeParam
更改为cu.custcode = custcodeParam
并且它正在运行!!
所以我的问题是为什么?为什么我不能在存储函数中使用like
比较器?为什么这不会导致错误,但函数运行无限期。
感谢。
答案 0 :(得分:3)
游标在Oracle中的处理方式完全相同。函数中的查询将与您通过SQL * Plus手动输入的查询完全相同。
但是,您的示例中可能有所不同的是Oracle如何使用变量。以下两个查询与优化器根本不同:
SELECT * FROM tab WHERE code LIKE 'FOO%';
和
variable v_code VARCHAR2(4)
EXEC :v_code := 'FOO%';
SELECT * FROM tab WHERE code LIKE :v_code;
在第一种情况下,优化器会查看常量FOO%
,并且可以立即告诉code
上的索引非常适合通过索引RANGE SCAN快速检索行。
在第二种情况下,优化器必须考虑:V_CODE
不是常量。优化器的目的是确定将由同一查询的连续执行共享的查询计划(因为计算计划很昂贵)。
优化程序的行为取决于您的Oracle版本:
FOO%
可能是%FOO
的值(后者无法通过索引范围扫描)。%FOO
,则可能会选择全面扫描。FOO%
将使用RANGE SCAN,而%FOO
可能使用全扫描。您使用的是哪个版本的Oracle?
更新
在10g和之前,如果经常使用没有通配符的函数,你应该重写它以确认优化器的行为:
BEGIN
IF instr(custcodeParam, '%') > 0 OR instr(custcodeParam, '_') > 0 THEN
SELECT cc.email
INTO mail_rc
FROM contact_table cc, customer_table cu
WHERE cu.customer_id = cc.customer_id
AND cu.custcode LIKE custcodeParam;
ELSE
SELECT cc.email
INTO mail_rc
FROM contact_table cc, customer_table cu
WHERE cu.customer_id = cc.customer_id
AND cu.custcode = custcodeParam;
END IF;
RETURN mail_rc;
END;