【发布时间】:2018-01-13 08:19:52
【问题描述】:
我知道 Oracle(我正在研究 Oracle11gR2)如果可以的话,可以隐式地将数据类型相互转换。例如,如果我尝试将数字插入 varchar 区域,它会隐式地将数字转换为 varchar,反之亦然,如果 varchar 是有效数字,它将被转换为数字。
Oracle 也对连接进行这种隐式转换。如果我将数字列连接到 varchar 列,它将隐式将 varchar 转换为数字并完成查询。但如果 varchar 列中有任何无效数字,它会抛出 ORA-01722 : Invalid Number 您可以通过运行以下代码来查看此设置:
create table test_1(
id varchar2(20),
val number);
create table test_2(
id number,
name varchar2(20)
);
insert into test_1 values ('abc', 10);
insert into test_1 values ('1', 11);
insert into test_2 values (1,'abc');
insert into test_2 values (2,'def');
-- Throw error
select
*
from
test_1, test_2
where
test_1.id = test_2.id
-- work
select
test_1.id, val, name
from
test_1, test_2
where
test_1.id = test_2.id
and test_1.id = '1'
您还可以在以下位置查看和运行示例:http://sqlfiddle.com/#!4/fdce3/9/0
现在我的问题,是否有任何选项或配置参数可以强制 Oracle 将此隐式转换为 varchar 而不是数字?或者确切地看到无效数字的错误来源(哪个列或哪个连接)?
我知道我可以明确地进行转换以避免错误。如下所示,但我不希望将其作为解决方案。
select
*
from
test_1, test_2
where
test_1.id = to_char(test_2.id)
您也可以访问http://sqlfiddle.com/#!4/fdce3/10 以查看上面的代码是否正常工作。
谢谢
【问题讨论】:
-
我看不出这个问题有什么意义。即使您可以欺骗 Oracle 以您想要的方式进行隐式转换,它仍然会进行转换,因此从性能的角度来看,我不希望有任何差异。另外,不要使用隐式连接语法;它已经过时并且使您的查询难以阅读。
-
正确的解决方案是:当你想存储数字时不要使用 VARCHAR2 数据类型!
-
@WernfriedDomscheit - 阿门!
-
@TimBiegeleisen - 这个问题有一个明显的观点:在执行时失败的查询会引发错误,但它没有说明它在哪个表的哪一列上失败。如果查询比较复杂,涉及很多表,很多列,可以用
TO_CHAR()改变所有的条件,但是需要很长时间,需要大量的测试。 OP 想查找哪个表和列有无效数据,而不是更改查询。 -
感谢 cmets! TimBiegeleisen “不要使用隐式连接”不幸的是,我们使用的 ETL 工具会自动创建这些连接,我无法控制它。我的问题不在于性能,而在于崩溃的代码,因为源系统将一些非数字值放入 ID 列。我知道,如果我们需要存储数字,那么列类型不应像 Wernfried Domscheit 所说的那样是 VARCHAR,但我无法控制源系统的数据模型。