【问题标题】:Oracle: SQL Error: ORA-01722: invalid number when copying NUMBER to VARCHAR2Oracle:SQL 错误:ORA-01722:将 NUMBER 复制到 VARCHAR2 时数字无效
【发布时间】:2016-09-29 18:17:39
【问题描述】:

我有一个 Oracle 数据库,我需要将其中一个表中的 NUMBER(38,0) 列更改为 VARCHAR2 列。在this post 的建议下,我正在做以下事情:

  1. 添加一个 VARCHAR2 类型的临时列
  2. 将原始 NUMBER 列中的数据复制到 temp 列中
  3. 删除原来的 NUMBER 列
  4. 将临时列重命名为原始列名

但是,步骤 2 会导致主题错误,即使副本是从 NUMBER 到 VARCHAR2

作为安全措施,我在要更改的表的副本上运行下面的代码,该表是我使用创建的:

create table TPA_SPEC_COPY as select * from TPA_SPEC;
COMMIT WORK;

这是我尝试执行上述步骤的 SQL 代码:

ALTER TABLE TPA_SPEC_COPY
ADD (PA_SPEC_VALUE_NUM_TEMP  VARCHAR2(40 CHAR));

UPDATE TPA_SPEC_COPY set PA_SPEC_VALUE_NUM_TEMP = TO_CHAR(PA_SPEC_VALUE_NUM);  -- This is Line 4 where I get the error

ALTER TABLE TPA_SPEC_COPY DROP COLUMN PA_SPEC_VALUE_NUM_TEMP;

ALTER TABLE TPA_SPEC_COPY 
RENAME COLUMN PA_SPEC_VALUE_NUM_TEMP TO PA_SPEC_VALUE_NUM;

这是我在 SQL Developer 中收到的错误:

Error starting at line : 4 in command -
UPDATE TPA_SPEC_COPY set PA_SPEC_VALUE_NUM_TEMP = TO_CHAR(PA_SPEC_VALUE_NUM)
Error report -
SQL Error: ORA-01722: invalid number
01722. 00000 -  "invalid number"
*Cause:    The specified number was invalid.
*Action:   Specify a valid number.

编辑:添加表结构(使用DESCRIBE TPA_SPEC_COPY

DESCRIBE TPA_SPEC_COPY
Name                     Null     Type               
------------------------ -------- ------------------ 
PA_ID                    NOT NULL NUMBER(10)         
PA_VERSION_NUM           NOT NULL NUMBER(10)         
PA_SPEC_VERSION_NUM      NOT NULL NUMBER(10)         
SPEC_TYPE_CD             NOT NULL CHAR(10 CHAR)      
PA_SPEC_VALUE_NUM                 NUMBER(38)         
UOM_CD                            CHAR(10 CHAR)      
PA_SPEC_FORMULA_TXT               VARCHAR2(100 CHAR) 
PA_SPEC_COMMENT_TXT               VARCHAR2(250 CHAR) 
DISPLAY_FORMAT_NM                 VARCHAR2(30 CHAR)  
ROW_PROG_UPDT_ID         NOT NULL CHAR(12 CHAR)      
ROW_STATUS_CD            NOT NULL CHAR(1 CHAR)       
ROW_UPDATE_TIME          NOT NULL TIMESTAMP(9)       
ROW_LASTUPD_USERID       NOT NULL VARCHAR2(80 CHAR)  
ROW_CREATE_TIME          NOT NULL TIMESTAMP(9)       
ROW_CREATE_USERID        NOT NULL VARCHAR2(80 CHAR)  
VARIABLE_ID                       VARCHAR2(100 CHAR) 
SPEC_FORMULA_NM                   VARCHAR2(80 CHAR)  
SPEC_FORMULA_VERSION_NUM          NUMBER(10)         
DR_SENSITIVITY_NUM                NUMBER(38)         
PA_SPEC_RISKTODR_CD               CHAR(4 CHAR)       
PA_SPEC_VALUE_NUM_TEMP            VARCHAR2(40 CHAR)  

我在一个用假数字创建的小测试表上运行了相同的脚本,它运行成功。也许这表明这是一个数据问题?无论如何,我不知道我还能如何对付他。任何建议将不胜感激。

【问题讨论】:

  • 空值? to_char(nvl(PA_SPEC_VALUE_NUM,0))
  • 我认为 NUMBER(38,0) 不能包含空格...除非数据库以某种方式损坏
  • @Nicarus - 这就是 SQL Developer 显示 ORA-01722 错误的方式,它没有显示错误的值。如果它这样做会很好,但它没有。而@Gar 你可以将null 传递给to_char(),你只需要返回null。
  • 拥有corrupt numeric data 是我s possible,但我原以为CTAS 会首先失败。
  • 您可以使用幻数,但它们有自己的问题。或者一个单独的列作为标志可能 - 对于 NA,applicable 可能是 Y/N;或用于非数字值的字符串列,并且一次只允许设置一列。不过,请继续将数字存储为数字,以便以后省事。

标签: oracle sqldatatypes


【解决方案1】:

我只能怀疑某种数据损坏,我建议这个 plsql 代码尝试找到它,在更新后添加一个提交将有助于至少移动好的值。

我知道这不是最好的方法,它是要使用一次的代码。

begin
  for i in (select pa_id,PA_SPEC_VALUE_NUM from TPA_SPEC_COPY)
loop
   begin
    update TPA_SPEC_COPY set PA_SPEC_VALUE_NUM_TEMP=to_char(PA_SPEC_VALUE_NUM)

     where pa_id=i.pa_id;
   exception when others
    then 
       dbms_output.put_line('Problem with ' || i.pa_id);
 end;
end loop;
end;

【讨论】:

  • 很抱歉,我花了很长时间才接受您的回答。感谢这个脚本!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-14
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
  • 2020-09-21
  • 2021-01-22
相关资源
最近更新 更多