在VARCHAR中使用max来获得结果> 999999?

sab*_*abi 2 sql oracle varchar numbers max

如果有人将列作为VARCHAR2(256 CHAR)并且此列中只有数字,该怎么办?我想得到最高的数字.问题是:数字是> 999999但是最大值到varchar总是给我一个最大数字999999

我试过了,to_number(max(numbers), '9999999999999')但我仍然得到了999999,那是不可能的.有任何想法吗?谢谢

Pra*_*ana 7

最好的方法是

First Solution 将数字转换为列

要么

第二个解决方案 用数字转换您查询中的数据而不是获取数据...

 select max(col1) from(
  select to_number(numbers) as col1 from table ) d
Run Code Online (Sandbox Code Playgroud)

它必须是这样的,因为如果你调用TO_NUMBER()之前MAX(),它会按字母顺序排序,然后999999是大于100000000000.请注意使用TO_NUMBER()为VARCHAR2列须支付INVALID_NUMBER异常的风险,应包含任何非数字字符的列.这就是首选提出的解决方案的首选原因.

  • +1.因为如果在TO_NUMBER之前执行MAX,它将按字母顺序排序,然后999999大于100000000000. (2认同)

Bob*_*ica 6

在Oracle中,NUMBER类型包含基本100个浮点值,其精度为38位有效数字,最大值为9999 ...(38 9)x 10 ^ 125.有两个问题 - 第一个问题是NUMBER是否可以包含从256个字符串转换的值,第二个问题是是否可以区分两个数字术语中"接近"的值.

让我们从一个256个字符的字符串开始,然后尝试将其转换为数字.显而易见的事情是:

SELECT TO_NUMBER('9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999') AS VAL
  FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

执行上面我们得到:

ORA-01426: numeric overflow
Run Code Online (Sandbox Code Playgroud)

我们期待早些时候注意到这一点.NUMBER可以处理的最大指数是125 - 这里我们尝试转换256位有效数字的值.NUMBER无法处理此问题.如果我们将位数减少到125,如下:

SELECT TO_NUMBER('99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999') AS VAL
  FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

它工作正常,我们的答案是1E125.

< blink >

哇!等待!!什么???答案是1 x 10 ^ 125 ??? 那9个人怎么样?!?!?!?

记得早些时候我曾提到Oracle NUMBER是一个浮点值,最大精度为38,最大指数为125.从TO_NUMBER 125 9的角度来看,所有串联在一起无法准确表示 - 数字太多(记住,最大精度为38(稍后会详细介绍)).所以它尽可能绝对最好 - 它转换前38位数(所有这些都是9位数)然后说"我应该如何最好地将这个数字转化为结果A"代表输入和B)尽可能接近我能得到我给的东西吗?" 在这种情况下,它查看数字39,看到它是9,并决定向上舍入.由于所有其他数字也是9位数,它会继续整齐地四舍五入,直到最后以1作为剩余的尾数位数.

*后来,回到牧场......*

好的,早些时候我提到NUMBER的精度为38位.这并不完全正确 - 它实际上可以区分精度高达40位的值,至少有时候,如果风是正确的,并且你正在走下坡路.这是一个例子:

SELECT CASE
         WHEN to_number('9999999999999999999999999999999999999999') >
              to_number('9999999999999999999999999999999999999998')
           THEN 'Greater'
           ELSE 'Not greater'
       END AS VAL
  FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

这两个值每个都有40位数(计数留给非常无聊的读者:-).如果执行上述操作,您将返回'更大',表示两个40位数值的比较成功.

现在为了一些乐趣.如果你为每个字符串添加一个额外的'9',使得41位数值,并重新执行该语句,它将返回'Not greater'.

< blink >

等待!什么??哇!这些价值观明显不同!即使是TotalFool(tm)也能看到!!

这里的问题是41位数字超过了NUMBER类型的精度,因此当TO_NUMBER发现它有一个值时,它开始丢弃右侧的数字.因此,尽管这两个非常大的数字对你我来说显然是不同的,但一旦它们被折叠,旋转,肢解和转换,它们就完全不同了.

那么,这里有什么需要呢?

1 - 对于OP的原始问题 - 除了使用NUMBER之外,您还必须提出另一种比较数字字符串的方法,因为Oracle的NUMBER类型不能保存256位数值.我建议您通过确保所有值都是256位数字来规范化字符串,根据需要在左侧添加零,然后字符串比较应该可以正常工作.

2 - 浮点数通过否定来证明(你最喜欢的神灵/神灵)的存在,因为它们显然是(你最喜欢的邪恶化身).每当你和他们一起工作时(我们都必须迟早),你应该记住,他们是邪恶邪恶的副产品,等待你最不期望的时候抨击你.

3 -有点三!(对于那些能够识别而不诉诸于颅外搜索引擎的人来说,还有额外的功劳:-)

分享和享受.