【问题标题】:Oracle sql case sensitive indexOracle sql 区分大小写的索引
【发布时间】:2018-02-12 15:13:19
【问题描述】:

在我的项目数据库中,当前表 Products 中有一列名为“Name” 因此,此表可以包含“产品 A”和“产品 a” 两种产品都应该在简单的选择查询中被选中。

我创建索引: CREATE INDEX IDX_PRODUCT_NAME ON PRODUCTS(NAME)

然后运行 ​​SQL 查询: SELECT /*+ INDEX(PRODUCTS IDX_PRODUCT_NAME)*/ * FROM PRODUCTS WHERE NAME='Product_a'

我做错了什么?

附:我知道改变会话标志的变体: NLS_COMP=ANSI; NLS_SORT=BINARY_CI; 但对我来说,没有更改数据库设置的有趣变体,有可能吗?或者例如仅为我的查询更改此标志。

请看图

更新: William Robertson 在 cmets 中帮助了我。 CREATE INDEX IDX_PRODUCT_NAME ON PRODUCTS(UPPER(NAME))

之后运行查询: SELECT * FROM PRODUCTS WHERE **UPPER**(NAME)='PRODUCT_A' 而且这个变体很好用!

【问题讨论】:

  • 有什么问题?您是否收到错误或意外行为?
  • SELECT /*+ INDEX(PRODUCTS IDX_PRODUCT_NAME)*/ * FROM PRODUCTS WHERE NAME='Product_a' 之后我没有任何输出和计划显示索引没有被使用,但是如果我的索引只是用于名称,没有 LOWER 函数并且我运行了简单的选择,计划显示索引有被使用了
  • 查看基于函数的索引,在 products(upper(name)) 上创建索引,在谓词中使用 upper(name)。
  • 带有 UPPER 功能的索引也不起作用。检查我上面的评论,我改变了它。
  • 除非您在where 子句中指定upper(name),否则它不是区分大小写的查询。

标签: sql oracle oracle11g query-hints


【解决方案1】:

一种方法是添加一个虚拟列:

create table demo_products
( id          integer not null
, name        varchar2(20)
, name_upper  generated always as (upper(name)) );

create index demo_prod_upper_name_ix on demo_products(name_upper);

insert all
    into demo_products (id, name) values (1, 'Prod A')
    into demo_products (id, name) values (2, 'Prod a')
    into demo_products (id, name) values (3, 'Prod B')
    into demo_products (id, name) values (4, 'Prod b')
    into demo_products (id, name) values (5, 'prod A')
    into demo_products (id, name) values (6, 'Cheese')
    into demo_products (id, name) values (7, 'Bananas')
select * from dual;

commit;

select count(*) from demo_products where name_upper = 'PROD A';

  COUNT(*)
----------
         3

Plan hash value: 4158816492

---------------------------------------------------------------------------------------------
| Id  | Operation         | Name                    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                         |     1 |    12 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |                         |     1 |    12 |            |          |
|*  2 |   INDEX RANGE SCAN| DEMO_PROD_UPPER_NAME_IX |     1 |    12 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("NAME_UPPER"='PROD A')

【讨论】:

  • 你不能在 oracle 中 create index foo on demo_products( upper(name) ) 然后 select ... where upper(name) = upper('prod a') 吗? (你可以在 postgres 中使用基于函数的索引 - 不确定 oracle)
  • 是的,这是另一种可行的方法。但是,将表达式包装在虚拟列中会很方便,尤其是在它比本示例更复杂的情况下。
猜你喜欢
  • 1970-01-01
  • 2018-04-19
  • 2011-07-20
  • 2014-03-25
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2010-09-05
相关资源
最近更新 更多