4

在一个存储过程(它有一个名为 'paramDate' 的日期参数)我有一个像这样的查询

select id, name
from customer
where period_aded = to_char(paramDate,'mm/yyyy')

Oracle 会将每行的 paramDate 转换为字符串吗?

我确信甲骨文不会,但有人告诉我甲骨文会。事实上,我认为如果函数的参数是约束(在查询中没有字段或计算值),结果应该总是相同的,这就是 Oracle 应该只执行一次转换的原因。然后我意识到我有时会在几个函数中执行 DML 语句,这可能会导致结果值发生变化,即使每一行都没有变化。

这应该意味着我应该在将这些值添加到查询之前转换它们。

无论如何,也许众所周知的“已知函数”(内置)会被评估一次,甚至我的函数也会被评估。

无论如何,再...

oracle 会执行一次 to_char 还是 Oracle 会为每一行执行一次?

感谢您的回答

4

3 回答 3

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')))

对于用户定义的函数,请查看这篇文章。它提到了两种方法来确保你的函数只被调用一次:

  1. 从 Oracle 10.2 开始,您可以将函数定义为 DETERMINISTIC。

  2. 在旧版本上,您可以重新措辞以使用“标量子查询缓存”:

    SELECT COUNT(*) FROM EMPLOYEES WHERE SALARY = (SELECT getValue(1) FROM DUAL);

于 2009-07-13T01:31:21.630 回答
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;
/

千吨

于 2009-07-13T01:09:12.013 回答
1

查看关于 DETERMINISTIC 关键字的文章(这里是一个这里是另一个),引入它是为了让开发人员告诉 Oracle 该函数将为相同的输入参数返回相同的值。因此,如果您希望您的函数只被调用一次,并且您可以保证它们总是为相同的输入参数返回相同的值,您可以使用关键字 DETERMINISTIC。

关于像 等内置函数to_char,我请那些更精通 Oracle 内部的人给你指导。

于 2009-07-13T01:45:28.603 回答