【问题标题】:how to change a column's attribute without affecting the values already present?如何在不影响已经存在的值的情况下更改列的属性?
【发布时间】:2010-10-31 07:28:11
【问题描述】:

简而言之 - 在 oracle db 中,我想创建一个列 varchar2(16),它现在是 varchar2(8),而不影响值 presnet。我已经尝试过了,它会做一些奇怪的事情。

我尝试的查询是 - alter table SOME_TABLE modify (SOME_COL varchar2(16)); 但是表中已经存在的值(有些不是全部)得到 当我运行上述查询时,它们附加了“\0”。

那么,做我想做的事的正确方法是什么?

【问题讨论】:

    标签: sql database oracle alter-table


    【解决方案1】:

    你正在执行的命令是正确的。

    您确定您看到的其他字符不存在吗?

    【讨论】:

    • 是的,我确定.. 在查询运行前后我有多个数据库实例。
    • 关于正在修改的值的任何具体信息?您可以在更改值的前后发布 select dump(columnname, 16) from table where ... 的结果吗?
    • 我同意这个命令是正确的。之后如何查看数据?也许空字符是您的 GUI 的产物。
    • 哈哈.. 更奇怪的是,即使上面的 sql 现在也失败了.. 我收到一条错误消息,说“你的 sql 中的错误,也许你应该先尝试执行”。我以前从未见过这个:| @kevin:在我发布转储之前给我一些时间。
    • @Bill:我知道数据已损坏,因为应用程序现在正在中断:(并且调试时的变量检查显示数据的变化。
    【解决方案2】:

    如果没有其他方法适合您,您可以随时执行以下操作:

    1. 使用新名称添加新列
    2. 使用 UPDATE 将旧列中的值复制到新列中
    3. 删除旧列
    4. 将新列重命名为旧列

    这是漫长而繁琐且蛮力的,但如果你不能以任何其他方式完成它,它会起作用......

    【讨论】:

    • 这就是我最终要做的。但我不高兴也不自豪。 :(
    • @Wikidkaka:我很抱歉,有时简单的蛮力是有效的。如果你没关系,请接受我的回答:)
    【解决方案3】:

    表中的原始数据正在被更改是非常值得怀疑的。由于您的某些 cmets 暗示您正在使用 SQLPlus 以外的工具和应用程序来查看和处理数据,因此我认为您需要查看它们是否以某种方式错误处理了数据。

    这是一个示例,我试图重现您在直接 SQLPlus 中所做的事情。没有空字节附加到现有数据:

    SQL> create table foo (bar varchar2(8));
    
    Table created.
    
    SQL> insert into foo        
      2  select lpad(to_char(level),level)
      3    from dual 
      4    connect by level <=8;
    
    8 rows created.
    
    SQL> commit;
    
    Commit complete.
    
    SQL> select bar,dump(bar) from foo;
    
    BAR
    --------
    DUMP(BAR)
    --------------------------------------------------------------------------------
    1
    Typ=1 Len=1: 49
    
     2
    Typ=1 Len=2: 32,50
    
      3
    Typ=1 Len=3: 32,32,51
    
       4
    Typ=1 Len=4: 32,32,32,52
    
        5
    Typ=1 Len=5: 32,32,32,32,53
    
         6
    Typ=1 Len=6: 32,32,32,32,32,54
    
          7
    Typ=1 Len=7: 32,32,32,32,32,32,55
    
           8
    Typ=1 Len=8: 32,32,32,32,32,32,32,56
    
    
    8 rows selected.
    
    SQL> alter table foo modify (bar varchar2(16));
    
    Table altered.
    
    SQL> select bar,dump(bar) from foo;
    
    BAR
    ----------------
    DUMP(BAR)
    --------------------------------------------------------------------------------
    1
    Typ=1 Len=1: 49
    
     2
    Typ=1 Len=2: 32,50
    
      3
    Typ=1 Len=3: 32,32,51
    
       4
    Typ=1 Len=4: 32,32,32,52
    
        5
    Typ=1 Len=5: 32,32,32,32,53
    
         6
    Typ=1 Len=6: 32,32,32,32,32,54
    
          7
    Typ=1 Len=7: 32,32,32,32,32,32,55
    
           8
    Typ=1 Len=8: 32,32,32,32,32,32,32,56
    

    【讨论】:

    • 我没有直接访问数据库的权限,我运行的查询是通过浏览器内的 perl 接口进行的。但我真的不认为那里有什么问题。
    【解决方案4】:

    大部分同意戴夫·科斯塔的观点。 可能有一个缓存仍然认为数据是旧的“8”大小。 当你说“一些不是全部”的值得到额外的 \0 时,一致的因素是什么? 它们的长度是否相同(例如七个或八个字符),或者它们可能是在 ALTER 列完成时或在某些服务器重新启动之前插入的?

    没有解决方案,但几天前提出了类似的问题here。不妨试着比较一下笔记。

    【讨论】:

    • 实际上存在一致性因素。所有小于 8 字节的旧值都附加了 '\0',而其他旧值则没有。很奇怪吧? :-|
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多