2011-09-05 221 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

我很欣賞你的想法,謝謝。 –