【问题标题】:Changing precision of numeric column in Oracle更改 Oracle 中数字列的精度
【发布时间】:2012-02-10 19:49:58
【问题描述】:

目前我有一列被声明为 NUMBER。我想将列的精度更改为 NUMBER(14,2)。

所以,我运行了命令

 alter table EVAPP_FEES modify AMOUNT NUMBER(14,2)'

为此,我遇到了一个错误:

   column to be modified must be empty to decrease precision or scale

我猜它希望列是空的,而它会改变精度,我不知道为什么它说我们想在增加它的同时减少它,列中的数据不会丢失。有一个简短的解决方法吗?我不想将它复制到另一个表中然后将其删除,或者重命名列并在列之间复制,因为在传输和删除之间存在丢失数据的风险。

【问题讨论】:

    标签: sql oracle precision


    【解决方案1】:

    假设您最初没有设置精度,则假定它是最大值 (38)。您正在降低精度,因为您将其从 38 更改为 14。

    处理此问题的最简单方法是重命名列,复制数据,然后删除原始列:

    alter table EVAPP_FEES rename column AMOUNT to AMOUNT_OLD;
    
    alter table EVAPP_FEES add AMOUNT NUMBER(14,2);
    
    update EVAPP_FEES set AMOUNT = AMOUNT_OLD;
    
    alter table EVAPP_FEES drop column AMOUNT_OLD;
    

    如果您确实想保留列顺序,可以将数据移动两次:

    alter table EVAPP_FEES add AMOUNT_TEMP NUMBER(14,2);
    
    update EVAPP_FEES set AMOUNT_TEMP = AMOUNT;
    
    update EVAPP_FEES set AMOUNT = null;
    
    alter table EVAPP_FEES modify AMOUNT NUMBER(14,2);
    
    update EVAPP_FEES set AMOUNT = AMOUNT_TEMP;
    
    alter table EVAPP_FEES drop column AMOUNT_TEMP;
    

    【讨论】:

    • 这些解决方案有什么区别?
    • @BrownFurSeal:第一个解决方案将移动更改的列,使其成为表中的最后一列。第二种解决方案将保留列的原始顺序。
    • 第一种方法会破坏列(如果在某处使用列可能会导致问题)。第二种方法是非破坏性的,但要求列可以为空。如果它不可为空,则需要添加命令使其可空,然后在更改后将其恢复为不可空。
    • 如果该列是主键列,则不能使用第二种方法,因为主键列本质上是不可为空的。基本上,你完蛋了。
    • @ArunGowda:在您设置值的步骤之一中,您可以使用TRUNCCEILFLOOR 函数强制非标准舍入。 IE。 update EVAPP_FEES set AMOUNT_TEMP = TRUNC(AMOUNT, 2); 总是向下舍入。
    【解决方案2】:

    通过设置比例,您会降低精度。试试 NUMBER(16,2)。

    【讨论】:

    • 我尝试了从 1 到 38 的每个数字,但仍然得到相同的错误。
    • 对不起,我看错了帖子。当您使用 NUMBER 定义列时,它分配的最大值为 38,因此任何比例都会降低精度,并可能丢失数据。为什么您认为创建新表并从旧表复制数据可能会丢失一些数据?
    • 记录数以千计,万一update/alter语句失败,可能没有办法回滚
    • 你不能创建一个新的表定义来复制现有的表定义,除了 NUMBER(14.2) 列并执行“插入新表选择 ... 从旧表” - 当你确定成功,删除旧的并重命名新的?您可能需要删除并恢复外键,但对我来说这似乎是安全的。
    【解决方案3】:

    如果表被压缩,这将起作用:

    alter table EVAPP_FEES add AMOUNT_TEMP NUMBER(14,2);
    
    update EVAPP_FEES set AMOUNT_TEMP = AMOUNT;
    
    update EVAPP_FEES set AMOUNT = null;
    
    alter table EVAPP_FEES modify AMOUNT NUMBER(14,2);
    
    update EVAPP_FEES set AMOUNT = AMOUNT_TEMP;
    
    alter table EVAPP_FEES move nocompress;
    
    alter table EVAPP_FEES drop column AMOUNT_TEMP;
    
    alter table EVAPP_FEES compress;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多