我有一个oracle SQL数据库,其中有一个名为SESID
的列,DATA_TYPE
为CHAR(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并运行查询。
答案 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)
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 强>:
但是,您要匹配的SESID
是12345___
(其中___
代表三个尾随空格)并且不等于12345
(没有尾随空格)所以没有返回任何行。
查询3 :
相反,您可以确保在将数字转换为字符串时将其填充到正确的长度:
SELECT SESID
FROM tbl
WHERE SESID = RPAD( TO_CHAR( 12345 ), 8, ' ' )
<强> Results 强>:
| SESID |
|----------|
| 12345 |
另类解决方案
将列定义从CHAR(8 BYTE)
更改为VARCHAR2(8)
,然后您可以毫无问题地使用查询2.