使用索引TO_NUMBER将Oracle SQL DATA_TYPE CHAR(8 BYTE)查询作为数字

时间:2013-12-19 11:43:13

标签: sql oracle oracle-sqldeveloper

我有一个oracle SQL数据库,其中有一个名为SESID的列,DATA_TYPECHAR(8 BYTE)。我们在此列上设置了索引,但是当我查看执行计划时,我们似乎没有使用索引。我将使用的简单查询是

SELECT * FROM TestTable WHERE SESID = 12345

看一下执行计划,它没有使用索引,因为它必须在TO_NUMBER列上进行SESID调用,这可以防止oracle考虑查询计划中的索引。 / p>

以下是详细说明的执行计划信息:

Predicate Information (identified by operation id):
---------------------------------------------------    
1 - filter(TO_NUMBER("SESID")=12345)

我的问题是,有没有办法更改查询,以便将数字'12345'视为CHAR数组?我的直觉告诉我这可能有用:

SELECT * FROM TestTable WHERE SESID = '12345'

但显然没有......有人知道我该怎么做吗

我正在使用.NET 4中提供的标准OracleClient连接到oracle DB并运行查询。

2 个答案:

答案 0 :(得分:0)

SELECT * FROM TestTable WHERE SESID = '12345'

SELECT * FROM TestTable WHERE SESID = TO_CHAR( 12345 )

Oracle有点奇怪,因为如果你将文字与需要隐式类型转换的列进行比较,它将始终尝试转换列而不是文字。

值得关注每个SQL语句,并在文字上添加显式转换,以确保不会被捕获。

话虽如此,拥有一个可以使用的索引和SQL语句并不能保证Oracle 将使用它 - 还需要有足够的数据。用于思考和索引的表将是有用的。

如果您想了解为什么需要大量阅读“基于成本的优化工具”

<强>除了:

如果您因为某些原因发现无法无法对文字进行转换(例如,sql是由您无法控制的库生成的)那么您可以< / em>创建一个功能索引。

即。一个基于将要发生的转换的索引。

E.g。 CREATE index test_table_index on ( TO_NUMBER( sesid ) )

只有sesid中的所有数据都是数字时才可以这样做。

这提出了这样的观点:当转换列时,它可能会转换比您想要的更多的数据,有时这是不可能的。

E.g。您在包含数字和非数字数据混合的表上执行原始SELECT。由于不存在支持select Oracle的索引,因此需要进行全表扫描。因此,它需要查看TestTable中的每条记录,并将sesid转换为数字。但它不能用于非数字值,因此即使您不希望记录是非数字的,它也会引发异常。

最终旁白:

Oracle中的对象名称不区分大小写(除非您使用“引号”表明它们应该是),因此通常的做法是使用带下划线的标识符而不是驼峰大小写,以便在Oracle输出时更容易阅读。

E.g。 test_table而不是TestTable

答案 1 :(得分:0)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE tbl ( SESID CHAR(8 BYTE) );

INSERT INTO tbl VALUES ( '1' );
INSERT INTO tbl VALUES ( '12' );
INSERT INTO tbl VALUES ( '123' );
INSERT INTO tbl VALUES ( '1234' );
INSERT INTO tbl VALUES ( '12345' );
INSERT INTO tbl VALUES ( '123456' );
INSERT INTO tbl VALUES ( '1234567' );
INSERT INTO tbl VALUES ( '12345678' );

查询1

CHAR列将使用空格字符填充字符串。您可以使用以下查询查看此内容:

SELECT SESID, LENGTH( SESID ), LENGTH( TRIM( SESID ) )
FROM   tbl

<强> Results

|    SESID | LENGTH(SESID) | LENGTH(TRIM(SESID)) |
|----------|---------------|---------------------|
| 1        |             8 |                   1 |
| 12       |             8 |                   2 |
| 123      |             8 |                   3 |
| 1234     |             8 |                   4 |
| 12345    |             8 |                   5 |
| 123456   |             8 |                   6 |
| 1234567  |             8 |                   7 |
| 12345678 |             8 |                   8 |

查询2

此查询显式将数字转换为字符串:

SELECT SESID
FROM   tbl
WHERE  SESID = TO_CHAR( 12345 )

<强> Results

但是,您要匹配的SESID12345___(其中___代表三个尾随空格)并且不等于12345(没有尾随空格)所以没有返回任何行。

查询3

相反,您可以确保在将数字转换为字符串时将其填充到正确的长度:

SELECT SESID
FROM   tbl
WHERE  SESID = RPAD( TO_CHAR( 12345 ), 8, ' ' )

<强> Results

|    SESID |
|----------|
| 12345    |

另类解决方案

将列定义从CHAR(8 BYTE)更改为VARCHAR2(8),然后您可以毫无问题地使用查询2.