2011-11-01 155 views
0

我試圖使用SQL腳本來恢復數據庫SQL腳本來恢復數據庫,但事情外鍵約束的方式從外鍵約束

我正在一個MySQL數據庫,並把它交給PostgreSQL的獲得。 由於MySQL創建表語法結束了很大的不同,我帶了另一個PostgreSQL數據庫具有相同的模式,但不同的數據,並從中恢復模式。 換句話說,我現在有一個數據庫,其中包含表格,約束,序列以及所有那些內部沒有數據的數據庫。

因此,現在是恢復數據的時候了。 我使用phpMyAdmin(僅數據)作爲SQL腳本備份MySQL數據庫(由於某種原因,pgAdmin似乎不接受zip或gzip文件)並運行SQL腳本。 現在,這就是問題開始發生的地方,從MySQL到PostgreSQL是很自然的,所以語法錯誤一定會發生。

但是,也有其他非語法有關的問題,像這樣的:

ERROR: insert or update on table "_account" violates foreign key constraint "fk_1_account" 
DETAIL: Key (accountid)=(2) is not present in table "_entity". 

所以,是的,基本上,一個外國約束存在,查詢嘗試將數據插入到_account表,但尚未將相應的數據插入_entity表中。 我該如何解決這個問題?有沒有辦法讓pgAdmin3/PostgreSQL禁用所有的約束,插入數據,然後重新啓用約束?

我遇到語法有關的錯誤,是這樣的一個:

INSERT INTO _accounttype_seq (id) VALUES (11); 

PostgreSQL的相當於該聲明(如果我是正確的)是

ALTER SEQUENCE _accounttype_seq INCREMENT BY 11; 

但是,這是一個有點痛運行整個腳本並更改所有200多個序列插入語句。所以,我在這裏很懶,但是有沒有更簡單的方法來處理序列呢?

或者,你們對不同的工具有什麼建議可以使這更簡單嗎?

感謝您的時間,祝您有美好的一天。

+0

mysql有一個'foreign_key_checks'設置,您可以爲導入目的禁用 - 不禁用它們就不可能導入任何帶有循環引用的表,或者以非常特定的順序列出表。 PG應該有類似的東西。 –

+0

這些可能有所幫助: 1. http://stackoverflow.com/questions/2679854/postgresql-disabling-constraints,2. http://www.postgresql.org/docs/8.2/static/sql-set-constraints。 html – Abhay

回答

2

不要試圖繞過外鍵約束。這是確保數據不好的方法。

首先看看約束條件,並確保按正確的順序插入表格。如果_entity是「_account」的父項,那麼它應該先填充。

接下來,您需要讓腳本將任何失敗的記錄移動到異常表中,然後您可以查看它們並查看數據完整性問題以及如果您需要永久丟棄記錄或試圖找出丟失的父值應該是什麼,如果它是關鍵數據,如客戶不再存在的訂單(可能在任何系統中沒有正確的fks開始與),並且您必須保留記錄,並且不能確定父項值應該是什麼,您可以在客戶表中創建一個「未知」記錄並將所有不良訂單分配給該客戶ID。

即使無聊,手動更改修改序列也不會花費很長時間。在這種類型的轉換中,您需要手動處理其他事情。

我會嘗試爲PostgreSQL找到一個數據導入工具 - 我住在SQL服務器世界中,我將使用SSIS,但是您需要相當於PostgreSQL世界的SSIS。

+0

哈哈謝謝,是的,最後,我只是移動桌子,所以他們按順序填充。 – zermy

+0

看看這個http://kettle.pentaho.com/上的免費工具。 – Kuberchaun

2

實際上,外鍵並沒有在MySQL中實際執行(可能是因爲使用MyISAM),或者生成的SQL只是按錯誤的順序執行。

如果它是「唯一」的順序錯誤,我看到了兩個可能的解決方案:

  1. 編輯生成的腳本,要麼將所有FK定義的腳本
  2. 編輯每個FK的定義結束約束並將它們全部設置爲initially deferred。然後將腳本作爲一個單獨的事務運行,僅在最後提交。

編輯(因爲這是過多地放在一個評論)

使用SET CONSTRAINTS ALL DEFERRED如果約束已經與選項DEFERRABLE創建才起作用。

要在單個事務中運行所有事務,您必須確保已關閉自動提交。然後只需運行INSERT,最後發出COMMIT。 A ;只會在您自動提交時纔會提交。

如果您希望獨立於自動提交設置,請使用[BEGIN][1]開始您的腳本,並確保最後只有一個COMMIT。

BEGIN DEFERRABLE 
    INSERT INTO table_one ... ; 
    INSERT INTO table_two ... ; 
    ..... 
COMMIT; 
+0

約束定義不是我正在運行的查詢的一部分。表和約束已經創建。 按照Abhay的建議,我試着在開頭添加這行代碼來運行查詢:SET CONSTRAINTS ALL DEFERRED;但它不起作用,我認爲這是因爲有很多提交。我是否正確地假設每次用';'結束查詢,然後查詢都被提交?如果是的話,我怎麼才能最終承諾? 感謝您的回覆。 – zermy

+0

非常感謝您的幫助,但不幸的是,我不認爲約束是使用可延遲選項創建的,所以,我只是繼續前進,並圍繞插入順序移動。 – zermy