为什么oracle对于VARCHAR数据类型仅显示9999最大值?

时间:2019-08-09 12:43:16

标签: sql oracle

我有一个表,其中用VARCHAR将列类型设置为9 BYTE,但是在此列上应用max函数时,它仅显示最大值为9999,而没有其他值,

create table test(
ID  NUMBER,
NAME    VARCHAR2(100 BYTE),
SAL NUMBER,
RANK    VARCHAR2(9 BYTE));

Insert into test (ID,NAME,SAL,RANK  ) values (1082,'ABC',2082,'9999');
Insert into test (ID,NAME,SAL,RANK  ) values (1083,'ABC',2083,'10000');

实际数据:

id      NAME      SAL    RANK   
1082    ABC      2082   9999
1083    ABC      2083   10000

查询

select * from test where RANK   =(select max(RANK   ) from testyy);

输出:

id      NAME      SAL    RANK   
1082    ABC   2082       9999

我试图将列设为空并将列修改为INTEGER,然后它可以工作,但是我有疑问为什么它不适用于9 BYTE数据类型

update test set RANK    =null where id=1082;
update test set RANK    =null where id=1083;
alter table test modify RANK    INTEGER;

update test set RANK    ='9999' where id=1082;
update test set RANK    ='10000' where id=1083;

select * from test where RANK   =(select max(RANK) from test);

id      NAME      SAL    RANK   
------------------------------------------
1083    ABC      2083   10000

Oracle SQL开发人员没有错误消息

4 个答案:

答案 0 :(得分:6)

因为rank是表中的varchar,并且在这种情况下9999大于10000,所以9999最多。

答案 1 :(得分:3)

按字符串排序时,使用字典顺序,其中100在99之前(与'a'在bb'之前相同),而在按数字排序时,则考虑其值,因此100> 90。

例如:

lapply(.)

答案 2 :(得分:1)

当您将VARCHAR用作数据类型时,MAX函数的行为就像数据是文本一样。

在订购文本时,即使“ ALIGATOR”中的字母较多,“ ZEBRA”也位于“ ALIGATOR”之后。将相同的逻辑应用于“ 9999”和“ 10000”,则“ 9999”是两者中的较大者,因为“ 9999”的第一个VARCHAR“ 9”在“ 10000”的第一个VARCHAR“ 1”之后。

答案 3 :(得分:1)

我发布此答案是为了纠正您对表设置的基本误解

您断言此语句将创建一个具有字节数据类型的列:

CREATE TABLE X( Y VARCHAR2(100 BYTE) )

在通常理解的“字节为8位并存储0到255(或0x00到0xFF)之间的数字”的编程概念中,绝对与字节无关。

此列的数据类型为VARCHAR2,即text。不是字节。不是数字。不是数字

BYTE的存在指示oracle使用最多100个字节的存储空间来包含文本。这意味着,如果您插入每个字符需要4个字节的Unicode字符,那么在oracle告诉您您的字符串太长之前,您只能在其中获得25个字符。如果您插入ascii字符(每个字符需要1个字节),那么在oracle告诉您您的字符串太长之前,您将在那里获得100个字符

这里BYTE的补码是CHAR,您在其中告诉oracle“只要您接受长度不超过100个字符的字符串,就可以在磁盘上使用所需的空间”。这意味着oracle将在磁盘上使用100到400字节的空间来存储您的字符

-

其他答案已经涵盖了为什么字符串“ 9999”比字符串“ 10000”更大,但是我确实有一个点点滴滴可以补充为什么:

作为字符的“ 9”位于ASCII表中的位置0x39,因此在数字上为“值” 57(以10为基数的0x39十六进制表示)

'1'作为字符在ASCII表中的位置0x31,因此在数字上为“值” 49(以10为基数的0x31十六进制表示)

当oracle比较字符串(从左到右的语言)并询问“哪个字符串在字母顺序之后/更大时?”从左到右逐个字符地比较

在他的情况下,它扮演第一个角色:

Is '9' greater than '1'? 
--> What are the numeric representations of these characters? 57 and 49
--> Is 57 greater than 49? 
--> Yes. '9' is greater than '1'. 
--> STOP and declare '9999' is bigger than '10000'

它停止了,因为不再需要比较。如果两个字符串都以“ 9”开头,则它们将继续比较第一个字符,而甲骨文将继续比较第二个字符,以便确定哪个是获胜者。等等。

所以您拥有了:9999与'9999'无关-一个是数字,一个是看起来像数字的文本。这个问题与基于数字的比较,字节的最大值等无关。

这纯粹是关于字符串/文本的排序方式,这就是您需要了解的内容

永远不要将要用数学方法处理的数字存储在varchar中;它们会占用更多空间,速度会变慢,并且会导致排序,数学错误,并且每次使用时都需要进行转换