`
anreddy
  • 浏览: 99220 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

在Oracle中进行大小写不敏感的查询

阅读更多
在Oracle中,命令和对象名称都是大小写不敏感的,因为Oracle在处理语句时,将所有的名称和命令全部转化为大写。

但是对于字符串中的字符,无论是比较还是排序,都是大小写敏感的。这在Oracle是默认方式,但不是唯一的方式。


下面看一个简单的例子:

SQL> CREATE TABLE T (NAME VARCHAR2(30));

表已创建。

SQL> INSERT INTO T VALUES ('A');

已创建 1 行。

SQL> INSERT INTO T VALUES ('a');

已创建 1 行。

SQL> INSERT INTO T VALUES ('B');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> CREATE INDEX IND_T_NAME ON T(NAME);

索引已创建。

看一下默认情况下的排序和查询结果:

SQL> SELECT * FROM T ORDER BY NAME;

NAME
------------------------------
A
B
a

SQL> SELECT * FROM T WHERE NAME = 'A';

NAME
------------------------------
A

这是最正常不过的结果了,下面修改会话默认的排序方式:

SQL> ALTER SESSION SET NLS_SORT = BINARY_CI;

会话已更改。

SQL> SELECT * FROM T ORDER BY NAME;

NAME
------------------------------
A
a
B

SQL> SELECT * FROM T WHERE NAME = 'A';

NAME
------------------------------
A

可以看到,通过设置排序方法为BINARY_CI,已经实现了对排序的大小写不敏感,但是查询语句中仍然是大小写敏感的,下面进一步修改比较方式:

SQL> ALTER SESSION SET NLS_COMP = LINGUISTIC;

会话已更改。

SQL> SELECT * FROM T ORDER BY NAME;

NAME
------------------------------
A
a
B

SQL> SELECT * FROM T WHERE NAME = 'A';

NAME
------------------------------
A
a

现在已经达到了大小写不敏感查询的目的了,这是由于设置比较方式是基于语义的,而不是基于二进制的,而语言方式下A和a是没有区别的。

虽然目的达到了,但是还是要说明一下,这里虽然实现了对大小写不敏感的查询,但是这个结果的实现与表面看到的现象并不完全相同。

从查询语句上看,似乎只是对NAME进行一下判断就可以了,并未对列进行任何的操作,而实际上并非如此,下面看看这种情况下的执行计划:

SQL> SET AUTOT ON EXP
SQL> SELECT * FROM T WHERE NAME = 'A';

NAME
------------------------------
A
a

执行计划
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 1 | 17 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter(NLSSORT("NAME",'nls_sort=''BINARY_CI''')=HEXTORAW('6100')
)

Note
-----
- dynamic sampling used for this statement

Oracle居然对列进行了操作,将NAME进行了NLSSORT操作,然后判断是否与目标值进行判断。不过Oracle也没有其他的好方法进行处理,对等号右边的常量进行转换固然代价较低,但是SQL的判断条件就由等于变成了IN,这种转换恐怕变化更大。而且还要找到所有其他所有可能转换为目标值的常量,这个操作要比对列进行转换复杂得多。

不过这种方法就存在一个问题,就是Oracle无法使用索引了,一方面是由于对列进行了操作,另一方面是由于Oracle的索引是按照BINARY方式编码存储的。因此这种查询会采用全表扫描的方式。

SQL> SELECT /*+ INDEX(T IND_T_NAME) */ * FROM T WHERE NAME = 'A';

NAME
------------------------------
A
a

执行计划
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 1 | 17 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter(NLSSORT("NAME",'nls_sort=''BINARY_CI''')=HEXTORAW('6100')
)

Note
-----
- dynamic sampling used for this statement

这个情况,可以考虑建立一个函数索引来解决问题:

SQL> CREATE INDEX IND_T_L_NAME ON T(NLSSORT(NAME, 'NLS_SORT=BINARY_CI'));

索引已创建。

SQL> SELECT * FROM T WHERE NAME = 'A';

NAME
------------------------------
A
a

执行计划
----------------------------------------------------------
Plan hash value: 242883967

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 17 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_T_L_NAME | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access(NLSSORT("NAME",'nls_sort=''BINARY_CI''')=HEXTORAW('6100') )

Note
-----
- dynamic sampling used for this statement

当然使用一些非大众化的功能就容易碰到bug,比如下面的例子:http://yangtingkun.itpub.net/post/468/460325
来源:
[url]http://yangtingkun.itpub.net/post/468/460324
[/url]
分享到:
评论

相关推荐

    Oracle中对像名大小写敏感性的深入解析

    然而,Oracle实际上有一套复杂的规则来处理对象名的大小写敏感性,这在某些特定情况下可能会引起混淆。下面我们将深入探讨Oracle对象名大小写敏感性的处理机制。 在Oracle中,对象名(如表名、视图名、字段名、函数...

    oracle11g密码区分大小写问题

    - **重要性**:开启密码大小写敏感性可以显著提高系统的安全性,特别是对于那些需要与其他系统进行交互的应用程序来说尤为重要。 - **灵活性**:通过调整 `sec_case_sensitive_logon` 参数的值,可以根据实际需求...

    大小写不敏感查询数据库

    大小写不敏感查询数据库oracle、java大小写不敏感替换

    解决ORALCE大小写限制及登录限制

    在Oracle数据库系统中,大小写敏感性和登录限制是两个重要的管理方面,对于系统的稳定运行和安全性至关重要。本文将深入探讨这两个问题,以及如何解决它们。 首先,让我们关注Oracle中的大小写敏感性问题。Oracle...

    ORACLE中数据字典大小写问题

    在Oracle数据库中,对于数据字典中的表名和字段名,Oracle实际上处理这些名称时默认是大小写敏感的。这意味着如果创建了一个名为`myTable`的表,并且其中包含一个名为`myField`的字段,在查询或引用这些表名和字段名...

    oracle11g密码敏感取消

    --去掉字符大小写敏感设置:禁止密码大小写敏感 show parameter sec_case_sensitive_logon alter system set sec_case_sensitive_logon=false ; --Oracle11g中Exp空表的问题:禁用插入数据时才分配空间功能 show ...

    oracle 11g 设置用户密码大小写敏感测试

    本文将详细探讨Oracle 11g版本中关于用户密码大小写敏感性的设置方法,并通过实例测试说明如何进行此项配置的验证。 在Oracle 11g中,密码的大小写敏感性是由参数`sec_case_sensitive_logon`控制的。这个参数属于...

    Oracle学习查询语句

    首先,Oracle是大小写敏感的,这意味着在编写SQL语句时,需要特别注意变量名、表名和字段名的大小写。在条件表达式中,`OR`和`AND`用于组合多个条件,而`BETWEEN`用于在指定范围内查找值,包括边界。例如,`WHERE ...

    达梦和oracle的差异说明

    - **达梦数据库**:支持字段名的大小写敏感性,即在查询结果中会按照原始SQL语句中的大小写返回列名。例如,执行`SELECT typeid, typename FROM T_PUB_PRODUCT_TYPE`这样的查询时,返回的列名为`typeid`和`typename`...

    Oracle学习笔记 PDF

    - **大小写敏感性**: - SQL语句本身不区分大小写,但在查询特定字段值时需要区分大小写。 ##### 3.2 记事本命令调用 - **编写SQL程序**: - 在编写多行SQL命令时,直到输入分号才会执行命令。 - 可以使用外部...

    SQLServer数据库导入Oracle

    因此,当尝试在Oracle中访问在SQL Server中创建的大小写混合或小写的表时,可能会遇到`ORA-00942: 表或视图不存在`的错误。解决方法是在引用表名时使用双引号,例如`"Employees"`,这告诉Oracle按照提供的精确大小写...

    SQLServer与Oracle语法差异汇总.docx

    它们在语法上有诸多差异,这些差异主要体现在存储过程、自定义函数、游标、变量、赋值、语句结束符以及大小写敏感性等方面。 首先,让我们来看看存储过程的格式。在Oracle 10g中,创建存储过程使用`CREATE OR ...

    oracle函数大全

    在实际编程中,我们需要注意区分Oracle函数的大小写敏感性,因为在PL/SQL中函数是不区分大小写的,但在SQL语句中则可能需要按照实际的大小写来编写函数名。此外,熟悉并正确使用这些函数将有助于我们编写出更高效、...

    Oracle数据库中业务数据文本导出.pdf

    此外,尽管某些操作系统不区分大小写,但在UTL_FILE包中指定的目录与初始化参数文件中的目录比较时,Oracle仍然会区分大小写。 UTL_FILE包提供了多个过程和函数,用于读写文件。基本步骤如下: 1. 声明一个文件...

    oracle基础的文档 熟悉oracle的对象

    虽然SQL本身对大小写不敏感,但数据库中的实际数据是区分大小写的。 2. SQL基本功能: - **创建或删除表**:你可以使用CREATE TABLE语句创建新的表,而DROP TABLE语句则用于删除不再需要的表。 - **插入、修改和...

    POWERDESIGNER生成oracle表名带有引号

    POWERDESIGNER 生成 Oracle 表名带有引号的问题可以通过修改表名或取消大小写敏感性来解决。 POWERDESIGNER 是一款功能强大的数据建模工具,可以帮助用户设计、生成和管理数据库结构。了解 POWERDESIGNER 和 Oracle...

    oracle数据库讲解

    在SQL语句中,当使用单引号包围字符串时,其中的文本是大小写敏感的。例如,查询名字为"Carmen"的员工的年薪时,必须确保名字的大小写与数据库中存储的一致。 通过以上知识点的学习,初学者可以对Oracle数据库的SQL...

    oracle与SQL server的语法差异总结

    7. **大小写敏感性**: 默认情况下,Oracle对字符串不区分大小写,但可以通过设置数据库参数使其区分大小写。SQL Server则默认对字符区分大小写。 8. **序列**: - Oracle使用序列对象(如 `CREATE SEQUENCE seq_...

Global site tag (gtag.js) - Google Analytics