首先,我了解基本知识。
select to_number('A231') from dual; --这是行不通的,但是
select to_char('123') from dual;
select to_number('123') from dual;--这也能起作用
实际上,在我的包中,我们有两个表-- A(X number)和B(Y varchar) --有很多列,但是我们只担心X和Y。X只包含数值,如123,456等,而Y包含一些string和一些number,例如'123','HR123','Hello'。我们得把这两张桌子连接起来。它的遗留应用程序使我们无法更改表和列。在此之前,下面的条件是正常工作的。
to_char(A.x)=B.y;但是由于Y上有索引,性能团队建议我们执行在dev env中运行的A.x=to_number(B.y);。
我的问题是,在任何情况下,这个查询会产生错误吗?如果它选择'123',它肯定会给123。但如果它选择'AB123',那么它就会失败。它会失败吗?即使在加入其他'AB123'时,它也能选择table吗?
发布于 2021-07-06 08:43:11
它会失败吗?
是。它必须将每一行都放在TO_NUMBER中,然后才能检查它是否符合筛选条件。因此,如果有任何一行它将失败,那么它总是会失败的。
从甲骨文12.2 (因为您标记了Oracle 12),您可以使用:
SELECT *
FROM A
INNER JOIN B
ON (A.x = TO_NUMBER(B.y DEFAULT NULL ON CONVERSION ERROR))或者,将索引放在TO_CHAR(A.x)上并使用原始查询:
SELECT *
FROM A
INNER JOIN B
ON (TO_CHAR(A.x) = B.y)还要注意:在B.y上建立索引并不意味着将使用该索引。如果您正在对TO_NUMBER(B.y)进行筛选(无论是否存在转换错误的默认值),那么您将需要在您正在使用的函数TO_NUMBER(B.Y)上建立一个基于函数的索引。您应该分析查询并检查解释计划,以查看索引的使用是否有任何改进或更改。
发布于 2021-07-06 08:42:53
永远不要转换可以包含非数字字符串VARCHAR2的to_number列。
这可能部分奏效,但最终还是会失败的。
小型示例
create table a as
select rownum X from dual connect by level <= 10;
create table b as
select to_char(rownum) Y from dual connect by level <= 10
union all
select 'Hello' from dual;这可以工作(因为您限制了行,以便转换工作;如果幸运的话,Oracle选择正确的执行计划;这是可能的,但不受保护;)
select *
from a
join b on A.x=to_number(B.y)
where B.y = '1';但这将使失败
select *
from a
join b on A.x=to_number(B.y)
ORA-01722: invalid number性能
但由于有Y指标,绩效团队建议我们做A.x=to_number(B.y);
您应该对团队进行访问,就好像不能使用列(to_number(B.y))索引上的函数一样。
相反,您的原始查询可以完美地使用以下索引:
create index b_y on b(y);
create index a_x on a(x);查询
select *
from a
join b on to_char(A.x)=B.y
where A.x = 1;执行计划
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 1 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 5 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN| A_X | 1 | 3 | 1 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN| B_Y | 1 | 2 | 0 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("A"."X"=1)
3 - access("B"."Y"=TO_CHAR("A"."X"))https://stackoverflow.com/questions/68267070
复制相似问题