2011-09-05 339 views
5

我正在寻找最佳方式来更改已填充表中列的数据类型。 Oracle仅允许使用空值更改colums中的数据类型。更改生产数据库中的列数据类型

到目前为止,我的解决方案是一个PLSQL语句,它将要修改的列的数据存储在一个集合中,更改该表,然后遍历集合,恢复转换了数据类型的原始数据。

-- Before: my_table (id NUMBER, my_value VARCHAR2(255)) 
-- After: my_table (id NUMBER, my_value NUMBER) 

DECLARE 
    TYPE record_type IS RECORD (id NUMBER, my_value VARCHAR2(255)); 
    TYPE nested_type IS TABLE OF record_type; 
    foo nested_type; 
BEGIN 
    SELECT id, my_value BULK COLLECT INTO foo FROM my_table; 
    UPDATE my_table SET my_value = NULL; 
    EXECUTE IMMEDIATE 'ALTER TABLE my_table MODIFY my_value NUMBER'; 
    FOR i IN foo.FIRST .. foo.LAST 
    LOOP 
    UPDATE my_table 
     SET = TO_NUMBER(foo(i).my_value) 
     WHERE my_table.id = foo(i).id; 
    END LOOP; 
END; 
/

我正在寻找更有经验的方式来做到这一点。

+2

简单的答案是停止数据库正在生产几个小时,而你正确地做到这一点。除非你停止向数据库写入信息,否则你绝不会保证**你已经拥有了一切正确的信息。 – Ben

+0

桌子有多大?在这段时间内桌面是否必须提供给应用程序? –

回答

6

解决方案是错误的。 alter table语句执行隐式提交。因此,该解决方案具有以下问题:

  • 你不能回滚之后改变ALTER TABLE语句,如果ALTER TABLE语句后,数据库崩溃,你将失去数据
  • 的选择和更新用户可以自行更改之间到数据

相反,你应该看看oracle在线重新定义。

+0

谢谢,史蒂夫。原来,我将有一个时间窗口来进行维护,所以我会使用@Rene的方法。 –

5

您的解决方案对我来说看起来有点危险。将值加载到集合中并随后从表中删除它们意味着这些值现在仅在内存中可用。如果出现问题,他们会失去。

正确的程序是:

  1. 添加的正确类型的列表。
  2. 将值复制到新列。
  3. 丢弃旧列。
  4. 将新列重命名为旧列名称。
+0

这是否解决了即使其他用户对数据进行更改(如@steve指出的那样)数据丢失的问题? –

+0

不,它不。但是,如果您可以将应用程序离线进行维护,它将使您保留所有数据。 – Rene

+0

我很欣赏你的想法,谢谢。 –