Sql 在Oracle中使用类似于数值的字符串值

Sql 在Oracle中使用类似于数值的字符串值,sql,oracle,query-performance,Sql,Oracle,Query Performance,我的oracle查询中有一个条件: AND a.ACCARDACNT > '0880080200000006' and a.ACCARDACNT < '0880080200001000' 和a.ACCARDACNT>'0880080200000006'和a.ACCARDACNT880802000006和a.accardacnt_num880802000006和a.accardacnt_num“0880080200000006”和 a、 ACCARDACNT“088008020000

我的oracle查询中有一个条件:

AND a.ACCARDACNT > '0880080200000006' and a.ACCARDACNT < '0880080200001000'
和a.ACCARDACNT>'0880080200000006'和a.ACCARDACNT<'0880080200001000'
表中ACCARDACNT列的类型是
varchar
并已索引,但在这种情况下,我希望将其用作数字。当我执行这个查询时,执行计划显示CBO可以使用索引并逐个索引扫描表。 这是真的吗


我想使用和比较它们作为数字,也可以使用索引。有什么解决方案吗?

您当前的查询应该能够使用索引。但问题是,您正在对文本进行压缩,但希望它按数字排序。一般来说,这可能不是因为文本在SQL中按字典顺序排序(即按字典顺序)。因此,要获得正确的排序行为,您必须将
ACCARDACNT
转换为一个数字:

AND CAST(LTRIM(a.ACCARDACNT, '0') AS FLOAT) BETWEEN 880080200000007 AND 880080200000999

您当前的查询应该能够使用索引。但问题是,您正在对文本进行压缩,但希望它按数字排序。一般来说,这可能不是因为文本在SQL中按字典顺序排序(即按字典顺序)。因此,要获得正确的排序行为,您必须将
ACCARDACNT
转换为一个数字:

AND CAST(LTRIM(a.ACCARDACNT, '0') AS FLOAT) BETWEEN 880080200000007 AND 880080200000999

我认为不能同时使用数字比较和索引

执行计划显示CBO可以使用索引

这里可能使用完全索引扫描,因此它只是一个表扫描,但列数较少


可能的方法是将数字转换为带前导零的固定长度字符串,然后在比较中使用1。在这种情况下,将使用索引。

认为不能同时使用数字比较和索引

执行计划显示CBO可以使用索引

这里可能使用完全索引扫描,因此它只是一个表扫描,但列数较少


可能的方法是将数字转换为带前导零的固定长度字符串,然后在比较中使用1。在这种情况下,将使用索引。

如果保证所有
ACCARDACNT
都是数字,则只需使用

and to_number(a.accardacnt) > 880080200000006 and a.accardacnt < 880080200001000;

或包含
到\u编号(accardacnt)
的复合索引。由于字符串查询的执行计划显示了要使用的索引,因此数字比较和函数索引也应该如此。(请记住,DBMS可以自由使用提供的索引,也可以不使用。我们只是提供索引,但DBMS最清楚在查询中使用它们是否有意义。)

如果保证所有
ACCARDACNT
都是数字,那么只需使用

and to_number(a.accardacnt) > 880080200000006 and a.accardacnt < 880080200001000;

或包含
到\u编号(accardacnt)
的复合索引。由于字符串查询的执行计划显示了要使用的索引,因此数字比较和函数索引也应该如此。(请记住,DBMS可以自由使用提供的索引,也可以不使用。我们只是提供它们,但DBMS最清楚在查询中使用它们是否有意义。)

另一个选项仍然是计算列:

alter table mytable add accardacnt_num as (to_number(accardacnt));
并提供一个或多个包含此列的索引:

create index idx_accardacnt_num on mytable(accardacnt_num);
然后现有代码继续工作,但新查询可以从数字列中受益:

and a.accardacnt_num > 880080200000006 and a.accardacnt_num < 880080200001000;
和a.accardacnt_num>880802000006和a.accardacnt_num<8808020000000;

另一个选项仍然是计算列:

alter table mytable add accardacnt_num as (to_number(accardacnt));
并提供一个或多个包含此列的索引:

create index idx_accardacnt_num on mytable(accardacnt_num);
然后现有代码继续工作,但新查询可以从数字列中受益:

and a.accardacnt_num > 880080200000006 and a.accardacnt_num < 880080200001000;
和a.accardacnt_num>880802000006和a.accardacnt_num<8808020000000;

我认为以下逻辑符合您的实际需要:

a.ACCARDACNT > '0880080200000006' and
a.ACCARDACNT < '0880080200001000' and
length(ACCARDACNT) = 16
a.ACCARDACNT>“0880080200000006”和
a、 ACCARDACNT<'0880080200001000'和
长度(ACCARDACNT)=16
此外,如果有合适的索引,可以在列上使用索引


如果您希望15个字符的帐号
'8800820000060'
符合您的条件,则此选项不正确。我的猜测是,您不希望这样。

我认为以下逻辑符合您的实际需要:

a.ACCARDACNT > '0880080200000006' and
a.ACCARDACNT < '0880080200001000' and
length(ACCARDACNT) = 16
a.ACCARDACNT>“0880080200000006”和
a、 ACCARDACNT<'0880080200001000'和
长度(ACCARDACNT)=16
此外,如果有合适的索引,可以在列上使用索引


如果您希望15个字符的帐号
'8800820000060'
符合您的条件,则此选项不正确。我的猜测是您不希望这样。

您必须在列上创建函数索引:
accardacnt

create index idx_fn_accardant on table_name( to_number(accardacnt) );
在查询的where子句中将其转换为数字:

where to_number(ACCARDACNT) > 0880080200000006 and to_number(ACCARDACNT) < 0880080200001000
where to_number(ACCARDACNT)>088008020000006和to_number(ACCARDACNT)<0880080200001000

您必须在列上创建函数索引:
accardacnt

create index idx_fn_accardant on table_name( to_number(accardacnt) );
在查询的where子句中将其转换为数字:

where to_number(ACCARDACNT) > 0880080200000006 and to_number(ACCARDACNT) < 0880080200001000
where to_number(ACCARDACNT)>088008020000006和to_number(ACCARDACNT)<0880080200001000

我认为可以使用索引,但请记住,您所做的比较是针对文本,而不是数字。您的排序可能并不总是按照您所期望的方式进行。我想将它们作为数字和索引来使用和比较。有什么解决方案吗?如果执行计划显示Oracle使用索引,那么它将(几乎总是)使用索引-那么您的问题是什么?可能重复。使用TO_NUMBER函数。您的解决方案可能是:那么,ACCARDACNT中的所有值都是数字吗?我认为可以使用索引,但请记住,您所做的比较是针对文本的,而不是数字。您的排序可能并不总是按照您所期望的方式进行。我想将它们作为数字和索引来使用和比较。有什么解决方案吗?如果执行计划显示Oracle使用索引,那么它将(几乎总是)使用索引-那么您的问题是什么?可能重复。使用TO_NUMBER函数。您的解决方案可能在这里:那么,ACCARDACNT num中的所有值