2010-02-25 22 views
3

我有一個帶有兩個模式的Oracle數據庫。一個是舊的,另一個是新的。我想用新模式的新列更新舊模式。比較兩個模式並使用新模式的新列更新舊模式

我得到與以下查詢有變化的表。

select distinct table_name 
from 
(
    select table_name,column_name 
    from all_tab_cols 
    where owner = 'SCHEMA_1' 

    minus 

    select table_name,column_name 
    from all_tab_cols 
    where owner = 'SCHEMA_2' 
) 

使用此查詢我得到的表。如何使用新列更新舊架構表?我不需要數據,只需要列。

+0

小心,你的查詢將返回在'SCHEMA_1'新列,但你沒有得到中存在的'SCHEMA_2'但不是在'SCHEMA_1'列。而且你沒有發現已經改變的列。祝你好運:) – 2010-02-25 08:39:58

+0

感謝Peter Lang ..我知道我不是甲骨文的專家:)如果有人有一些想法如何做到這一點。請與我分享.... – coder247 2010-02-25 08:44:35

+0

您的新模式是否包含數據?是刪除並重新創建表的一個選項?你有幾張桌子?你只改變了列,還是有新的表格? – 2010-02-25 08:45:45

回答

3

恐怕我現在不能爲你做更多的事情,但這應該會給你一個基本的想法。

它選擇ADDDROP列語句,您可以在仔細閱讀後執行

它不處理

  • 創建/刪除的表
  • 現有的列( ALTER TABLE MODIFY
  • DEFAULT VALUES(所以你不能與數據時表應用它的
  • 數據類型/精度變化新列是NOT NULL
  • 檢查約束,外鍵約束

我嘗試了一些基本的數據類型(NUMBER,VARCHAR2,DATE),它工作。祝你好運:)


SELECT 'ALTER TABLE ' || LOWER(table_name) 
     || ' ADD ' || LOWER(column_name) || ' ' || data_type 
     || CASE WHEN data_type NOT IN ('DATE') THEN '(' || data_length || ')' END 
     || CASE WHEN nullable='Y' THEN ' NOT NULL' END 
     || ';' cmd 
    FROM all_tab_cols c2 
WHERE owner = 'SCHEMA_1' 
    AND NOT EXISTS (SELECT 1 
         FROM all_tab_cols c1 
        WHERE owner = 'SCHEMA_2' 
         AND c1.table_name = c2.table_name 
         AND c1.column_name = c2.column_name) 
UNION ALL 
SELECT 'ALTER TABLE ' || LOWER(table_name) 
     || ' DROP COLUMN ' || LOWER(column_name) || ';' 
    FROM all_tab_cols c2 
WHERE owner = 'SCHEMA_2' 
    AND NOT EXISTS (SELECT 1 
         FROM all_tab_cols c1 
        WHERE owner = 'SCHEMA_1' 
         AND c1.table_name = c2.table_name 
         AND c1.column_name = c2.column_name) 
ORDER BY cmd; 
+0

謝謝彼得.... – coder247 2010-02-25 10:45:12

3

我開始寫這一個答案,但我警告的名單變得長於答案,所以我決定放棄它。

你應該去一個模式比較工具。

有免費的版本 - 看看在服務器故障這樣一個問題:

https://serverfault.com/questions/26360/how-can-i-diff-two-oracle-10g-schemas

我的建議是下載Oracle的SQL Developer和使用的內置模式比較工具(雖然這要求您擁有變更管理包許可證)。

+1

+1:猜猜這會更痛苦:) – 2010-02-25 09:49:05

+0

是的:)我的原始答案變得有點講道。 「你應該在版本控制腳本中進行所有模式更改,並且......等等等等。」退格退格。 :) – 2010-02-25 09:57:47

+0

感謝尼克.... – coder247 2010-02-25 10:45:34

5

模式比較工具是一個好主意。數據庫模式比大多數人所稱讚的要複雜得多,並且兩個數據庫模式之間的每個差異都有可能導致錯誤。

如果您仍然熱衷於自己做,我發現的最好方法是將模式定義提取到文本,然後運行文本比較。只要所有內容按字母順序排序,就可以使用Microsoft Word中的比較文檔功能(或FC.EXE,DIFF或同等功能)來突出顯示差異。

以下SQLPlus腳本按字母順序輸出模式定義以允許進行比較。有兩個部分。第一部分列出每一列中,在格式:

table_name.column_name: data_type = data_default <nullable> 

第二部分列出索引和約束,如下所示:

PK constraint_name on table_name (pk_column_list) 
FK constraint_name on table_name (fk_column_list) 
CHECK constraint_name on table_name (constraint_definition) 

腳本用作用於提取一些Oracle模式的一個有益的參考細節。當您離開客戶站點並且沒有可用的常用工具時,或者安全策略阻止您直接從您自己的PC訪問客戶端站點數據庫時,這可能是非常好的知識。

set serveroutput on; 
set serveroutput on size 1000000; 
declare 
    rowcnt pls_integer := 0; 
    cursor c_column is 
    select table_name, column_name, data_type, 
     data_precision, data_length, data_scale, 
     data_default, nullable, 
     decode(data_scale, null, null, ',') scale_comma, 
     decode(default_length, null, null, '= ') default_equals 
     from all_tab_columns where owner = 'BCC' 
     order by table_name, column_name; 
    cursor c_constraint is 
     select c.table_name, c.constraint_name, 
     decode(c.constraint_type, 
       'P','PK', 
       'R','FK', 
       'C','CHECK', 
       c.constraint_type) constraint_type, 
     c.search_condition, 
     cc.column_1||cc.comma_2||cc.column_2||cc.comma_3||cc.column_3||cc.comma_4||cc.column_4|| 
     cc.comma_5||cc.column_5||cc.comma_6||cc.column_6||cc.comma_7||cc.column_7 r_columns 
     from all_constraints c, 
      (select owner, table_name, constraint_name, nvl(max(position),0) max_position, 
      max(decode(position, 1, column_name, null)) column_1, 
      max(decode(position, 2, decode(column_name, null, null, ','), null)) comma_2, 
      max(decode(position, 2, column_name, null)) column_2, 
      max(decode(position, 3, decode(column_name, null, null, ','), null)) comma_3, 
      max(decode(position, 3, column_name, null)) column_3, 
      max(decode(position, 4, decode(column_name, null, null, ','), null)) comma_4, 
      max(decode(position, 4, column_name, null)) column_4, 
      max(decode(position, 5, decode(column_name, null, null, ','), null)) comma_5, 
      max(decode(position, 5, column_name, null)) column_5, 
      max(decode(position, 6, decode(column_name, null, null, ','), null)) comma_6, 
      max(decode(position, 6, column_name, null)) column_6, 
      max(decode(position, 7, decode(column_name, null, null, ','), null)) comma_7, 
      max(decode(position, 7, column_name, null)) column_7 
      from all_cons_columns 
      group by owner, table_name, constraint_name) cc 
     where c.owner = 'BCC' 
     and c.generated != 'GENERATED NAME' 
     and cc.owner = c.owner 
     and cc.table_name = c.table_name 
     and cc.constraint_name = c.constraint_name 
     order by c.table_name, 
      decode(c.constraint_type, 
       'P','PK', 
       'R','FK', 
       'C','CHECK', 
       c.constraint_type) desc, 
      c.constraint_name; 
begin 
    for c_columnRow in c_column loop 
    dbms_output.put_line(substr(c_columnRow.table_name||'.'||c_columnRow.column_name||': '|| 
         c_columnRow.data_type||'('|| 
         nvl(c_columnRow.data_precision, c_columnRow.data_length)|| 
         c_columnRow.scale_comma||c_columnRow.data_scale||') '|| 
         c_columnRow.default_equals||c_columnRow.data_default|| 
         ' <'||c_columnRow.nullable||'>',1,255)); 
    rowcnt := rowcnt + 1; 
    end loop; 
    for c_constraintRow in c_constraint loop 
    dbms_output.put_line(substr(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '|| 
         c_constraintRow.table_name||' ('|| 
         c_constraintRow.search_condition|| 
         c_constraintRow.r_columns||') ',1,255)); 
    if length(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '|| 
         c_constraintRow.table_name||' ('|| 
         c_constraintRow.search_condition|| 
         c_constraintRow.r_columns||') ') > 255 then 
     dbms_output.put_line('... '||substr(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '|| 
          c_constraintRow.table_name||' ('|| 
          c_constraintRow.search_condition|| 
          c_constraintRow.r_columns||') ',256,251)); 
    end if; 
    rowcnt := rowcnt + 1; 
    end loop; 
end; 
/

不幸的是,有一些限制:

  1. 嵌入式回車和空格在data_defaults,檢查約束定義,也應當強調的差異,即使他們在架構零效果。
  2. 不包含備用密鑰,唯一索引或性能指標。這將需要腳本中的第三個SELECT語句,引用all_ind_columns和all_indexes目錄視圖。
  3. 不包括安全細節,同義詞,軟件包,觸發器等。使用與您最初提議的方法相似的方法可以最好地比較軟件包和觸發器。模式定義的其他方面可以添加到上面的腳本中。
  4. 上面的FK定義標識引用外鍵列,但不標識PK或被引用的表。只是我從來沒有做過的更多細節。

即使你不使用腳本。玩這個東西有一定的技術高興。 ;-)

馬修

+0

你是對的Matthew :) – coder247 2010-02-25 15:44:30

+0

Matthew,我不是甲骨文的專家,你能解釋一下你的代碼輸出在哪裏嗎?我成功運行它,但我不知道結果在哪裏。 – Helodia 2017-02-14 09:49:51