PLSQL错误:无效数字

PLSQL错误:无效数字,sql,oracle,Sql,Oracle,我正在尝试执行此查询,它是我的过程的一部分,也是产生问题的一部分: select SUM( CASE --DT007 WHEN PRO.Sens_Mnt_Brut = 'D' THEN '-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99') WHEN PRO.Sens_Mnt_Brut = 'C' THEN '' |

我正在尝试执行此查询,它是我的过程的一部分,也是产生问题的一部分:

select SUM(
                 CASE --DT007
              WHEN PRO.Sens_Mnt_Brut = 'D'
              THEN '-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99')
              WHEN PRO.Sens_Mnt_Brut = 'C'
              THEN '' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99')
                END) OVER(PARTITION BY PRO.Num_Est_Remise) - SUM(TO_CHAR(PRO.Mnt_Comm_Tot_Ope,'99999999999,99')) OVER(PARTITION BY PRO.Num_Est_Remise))--DT015

From dlc_pr_operation pro; 
执行后,我收到以下错误:

ORA-01722: invalid number
01722. 00000 -  "invalid number"
*Cause:    
*Action:  
这是因为我在查询中添加了从char到number和逗号的转换,还是因为其他原因


提前感谢您的帮助。

您正在进行大量数字和字符串之间的显式和隐式转换,不一致性和假设让您感到困惑。但无论如何,它们都是不必要的——您根本不需要在字符串之间进行转换。您的查询可以重写为:

select SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut
  ) OVER (PARTITION BY PRO.Num_Est_Remise)
    - SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise)
From dlc_pr_operation pro; 
它只是根据
Sens_Mnt_Brut
标志决定
Mnt_Brut
是应按原样使用还是应取反,并将其乘以1或-1(视情况而定)


您的方法至少有两个问题。您使用显式格式模型将数字转换为字符串,然后隐式地将它们转换回数字以求和;这意味着(a)隐式转换依赖于NLS设置,以及(b)使用显式模型无法将正在生成的字符串转换回

让我们从一些将进入第一个分支的虚拟数据开始:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99')) from dlc_pr_operation pro;

ORA-01722: invalid number
如果你看它形成的绳子,你会看到:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select '-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99') from dlc_pr_operation pro;

'-'||TO_CHAR(PRO
----------------
-          12,35
由于所有空格,该字符串的转换失败。您可以通过稍微修改格式模型来避免这种情况:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999,99')) from dlc_pr_operation pro;

TO_NUMBER('-'||TO_CHAR(PRO.MNT_BRUT,'FM99999999999,99'))
--------------------------------------------------------
-12,35                                                  
但前提是NLS设置,特别是NLS_数字_字符正确。如果我在执行
alter session set nls\u numeric\u characters='之后运行相同的查询,“
那么这也会得到ORA-01722,因为您使用了固定的逗号。您可以显式更改会话,或者从使用固定的
切换到通用的
D
十进制分隔符:

alter session set nls_numeric_characters = '.,';

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999,99')) from dlc_pr_operation pro;

ORA-01722: invalid number

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999D99')) from dlc_pr_operation pro;

TO_NUMBER('-'||TO_CHAR(PRO.MNT_BRUT,'FM99999999999D99'))
--------------------------------------------------------
                                                -1234.56
当然,在整个查询过程中,这仍然是隐式转换回数字


使用这个答案开头的修改过的查询(如果你还记得那么远的话)和一些更多的虚拟数据给出输出:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
  union all select 'X', 123.45, 2, 4 from dual
  union all select 'Y', 456.78, 3, 4 from dual
)
select SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut
  ) OVER (PARTITION BY PRO.Num_Est_Remise)
    - SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise) as result
From dlc_pr_operation pro; 

    RESULT
----------
-1235,56  
575,23    
575,23    
由于没有转换,您的NLS设置现在无关紧要;除了最终结果由客户端使用会话的十进制分隔符自动格式化之外,因此在本例中它仍然显示逗号分隔符,数字字符设置为“
”,.
。如果我将会话改为
,“
,我会看到:

    RESULT
----------
  -1235.56
    575.23
    575.23
这是否是你真正想要的结果还不太清楚。包含其他列可能很有用,但您还需要检查是否真正需要分析函数,而不仅仅是聚合


你在评论中说:

这是一个数字(16.0),但我想在最后两个数字之前加一个逗号

这并没有真正的意义,除非你将财务金额存储为整数——本质上是便士/美分,而不是英镑/欧元/美元——但希望以更友好的方式显示它们;在这种情况下,您应该将它们除以100,而不是将它们作为字符串:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 123456, 100, 2 from dual
  union all select 'X', 12345, 200, 4 from dual
  union all select 'Y', 45678, 300, 4 from dual
)
select (SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut
  ) OVER (PARTITION BY PRO.Num_Est_Remise) / 100)
    - (SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise) / 100) as result
From dlc_pr_operation pro; 

    RESULT
----------
  -1235.56
    575.23
    575.23

。。。假设(再次)要求和的两个值都是这样存储的;如果愿意的话,您也可以减去这两个和,然后将总数除以100。

您在数字和字符串之间进行了大量显式和隐式转换,不一致和假设让您感到困惑。但无论如何,它们都是不必要的——您根本不需要在字符串之间进行转换。您的查询可以重写为:

select SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut
  ) OVER (PARTITION BY PRO.Num_Est_Remise)
    - SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise)
From dlc_pr_operation pro; 
它只是根据
Sens_Mnt_Brut
标志决定
Mnt_Brut
是应按原样使用还是应取反,并将其乘以1或-1(视情况而定)


您的方法至少有两个问题。您使用显式格式模型将数字转换为字符串,然后隐式地将它们转换回数字以求和;这意味着(a)隐式转换依赖于NLS设置,以及(b)使用显式模型无法将正在生成的字符串转换回

让我们从一些将进入第一个分支的虚拟数据开始:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99')) from dlc_pr_operation pro;

ORA-01722: invalid number
如果你看它形成的绳子,你会看到:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select '-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99') from dlc_pr_operation pro;

'-'||TO_CHAR(PRO
----------------
-          12,35
由于所有空格,该字符串的转换失败。您可以通过稍微修改格式模型来避免这种情况:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999,99')) from dlc_pr_operation pro;

TO_NUMBER('-'||TO_CHAR(PRO.MNT_BRUT,'FM99999999999,99'))
--------------------------------------------------------
-12,35                                                  
但前提是NLS设置,特别是NLS_数字_字符正确。如果我在执行
alter session set nls\u numeric\u characters='之后运行相同的查询,“
那么这也会得到ORA-01722,因为您使用了固定的逗号。您可以显式更改会话,或者从使用固定的
切换到通用的
D
十进制分隔符:

alter session set nls_numeric_characters = '.,';

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999,99')) from dlc_pr_operation pro;

ORA-01722: invalid number

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
)
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999D99')) from dlc_pr_operation pro;

TO_NUMBER('-'||TO_CHAR(PRO.MNT_BRUT,'FM99999999999D99'))
--------------------------------------------------------
                                                -1234.56
当然,在整个查询过程中,这仍然是隐式转换回数字


使用这个答案开头的修改过的查询(如果你还记得那么远的话)和一些更多的虚拟数据给出输出:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 1234.56, 1, 2 from dual
  union all select 'X', 123.45, 2, 4 from dual
  union all select 'Y', 456.78, 3, 4 from dual
)
select SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut
  ) OVER (PARTITION BY PRO.Num_Est_Remise)
    - SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise) as result
From dlc_pr_operation pro; 

    RESULT
----------
-1235,56  
575,23    
575,23    
由于没有转换,您的NLS设置现在无关紧要;除了最终结果由客户端使用会话的十进制分隔符自动格式化之外,因此在本例中它仍然显示逗号分隔符,数字字符设置为“
”,.
。如果我将会话改为
,“
,我会看到:

    RESULT
----------
  -1235.56
    575.23
    575.23
这是否是你真正想要的结果还不太清楚。包含其他列可能很有用,但您还需要检查是否真正需要分析函数,而不仅仅是聚合


你在评论中说:

这是一个数字(16.0),但我想在最后两个数字之前加一个逗号

这并没有真正的意义,除非你将财务金额存储为整数——本质上是便士/美分,而不是英镑/欧元/美元——但希望以更友好的方式显示它们;在这种情况下,您应该将它们除以100,而不是将它们作为字符串:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
  select 'D', 123456, 100, 2 from dual
  union all select 'X', 12345, 200, 4 from dual
  union all select 'Y', 45678, 300, 4 from dual
)
select (SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut
  ) OVER (PARTITION BY PRO.Num_Est_Remise) / 100)
    - (SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise) / 100) as result
From dlc_pr_operation pro; 

    RESULT
----------
  -1235.56
    575.23
    575.23
。。。假设(再次)要求和的两个值都是这样存储的;Y