在存储过程(其日期参数名为'paramDate')中,我有一个像这样的查询
select id, name
from customer
where period_aded = to_char(paramDate,'mm/yyyy')
Oracle会将paramDate转换为每行的字符串吗?
我确信Oracle不会,但我被告知Oracle会。 事实上,我认为如果函数的参数是约束(在查询中没有获得fierld或计算值),结果应该总是相同的,这就是Oracle应该只执行一次此转换的原因。 然后我意识到我有时会在几个函数中执行DML语句,这可能会导致结果值发生变化,即使每行都没有变化。
这应该意味着我应该在将这些值添加到查询之前对其进行转换。
无论如何,也许好的“已知函数”(内置)会被评估一次,甚至我的函数也会被评估。
无论如何,再次......
oracle会执行一次to_char还是Oracle会为每一行执行该操作?
感谢您的回答
答案 0 :(得分:8)
我认为通常不会这样,因为它会阻止使用索引。
至少对于内置函数,Oracle应该能够确定它只能评估一次。 (对于用户定义的函数,请参见下文)。
以下是使用索引的情况(并且不对每一行评估函数):
SQL> select id from tbl_table where id > to_char(sysdate, 'YYYY');
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 35 | 140 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| SYS_C004274 | 35 | 140 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("ID">TO_NUMBER(TO_CHAR(SYSDATE@!,'YYYY')))
对于用户定义的功能,请查看此article。它提到了两种确保方法 您的函数只被调用一次:
从Oracle 10.2开始,您可以将函数定义为DETERMINISTIC。
在旧版本中,您可以重新使用它来使用“标量子查询缓存”:
SELECT COUNT(*) 来自员工 WHERE SALARY =(SELECT getValue(1)FROM DUAL);
答案 1 :(得分:1)
对to_char的担忧并没有给我敲响声。但是,在你的pl / sql中, 你可能有
create or replace procedure ........
some_variable varchar2(128);
begin
some_variable := to_char(paramDate,'mm/yyyy');
-- and your query could read
select id, name from customer where period_aded = some_variable;
.
.
.
end;
/
的Kt
答案 2 :(得分:1)
查看关于DETERMINISTIC关键字(here is one,here is another)的文章,介绍它是为了让开发人员告诉Oracle该函数将为相同的输入参数返回相同的值。因此,如果您希望只调用一次函数,并且可以保证它们将始终为相同的输入参数返回相同的值,您可以使用关键字DETERMINISTIC。
关于像to_char
这样的内置函数,我会让那些精通Oracle内部的人给你指路。