我是Oracle的新手,我有两个高频率使用的功能。我想知道它们之间哪个更好。
这一个:
FUNCTION GET_MY_MONEY (myType IN NUMBER) RETURN NUMBER AS
var_amount NUMBER;
var_result NUMBER;
BEGIN
var_result := 0;
var_amount := 0;
SELECT amount INTO var_amount FROM mytable WHERE type = myType AND sysdate >= date_from AND sysdate <= date_to;
var_result := var_amount*1000;
RETURN var_result;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END;
或者这个:
FUNCTION GET_MY_MONEY (myType IN NUMBER) RETURN NUMBER AS
var_count NUMBER;
var_amount NUMBER;
var_result NUMBER;
BEGIN
var_result := 0;
var_count := 0;
var_amount := 0;
SELECT count(*) INTO var_count FROM mytable WHERE type = myType AND sysdate >= date_from AND sysdate <= date_to;
IF (var_count > 0) THEN
SELECT amount INTO var_amount FROM mytable WHERE type = myType AND sysdate >= date_from AND sysdate <= date_to;
var_result := var_amount*1000;
RETURN var_result;
ELSE RETURN 0; END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END;
哪个性能更好?它们被调用后返回的速度更快?
提前致谢。
答案 0 :(得分:4)
一般来说,这取决于。您多久调用一次函数并传入导致查询返回0行的myType
值?
如果在99.9%的调用中,查询将返回正好1行,则第二种方法将运行查询以执行两次。虽然第二次调用可能不会导致函数的价格比第一次高两倍,因为您感兴趣的块几乎可以保证缓存,第二种方法几乎肯定会慢得多。
另一方面,如果大部分调用涉及不返回行的myType
值,则第二种方法通常不必再次执行查询。并且第一种方法将导致处理异常的开销很大一部分时间几乎肯定会比第二次查询更昂贵。
在大多数情况下,基于返回0行的概率,更有效的解决方案将是显而易见的。大多数情况下,仅当调用者非常确信它们将传入的myType
值有效时才调用该函数,因此第一种方法最终会更有效。随着导致找到0行的调用的比例增加,第二种方法变得更有效。该行的位置取决于许多因素,尤其是您的表,数据,硬件和Oracle版本。您需要运行基准测试,以确定您的特定代码的分界线是10%还是20%或90%。
答案 1 :(得分:2)
问题已被修改,但如果有多行,则SELECT amount INTO var_amount ...
将失败。(可能您想选择sum(amount)
)。
第一种方法更好,因为:
select nvl(sum(amount),0) as amount
但是,您必须为日期变量(date_from
和date_to
)指定一个值或将它们作为参数。
你可以返回一个表达式,即:RETURN var_count*1000;
答案 2 :(得分:1)
另外:
DECLARE
v_retVal NUMBER:= 0;
v_sal NUMBER:= 0;
BEGIN
SELECT nvl(sum(sal),0) as sal INTO v_sal
FROM scott.emp
WHERE deptno = 40; -- no data for deptno = 40
-- No exception needed, function will always return 0 or value --
v_retVal:= (CASE WHEN v_sal = 0 THEN 0 ELSE v_sal*1000 END);
dbms_output.put_line (v_retVal);
-- RETURN v_retVal;
END;
/