2014-07-21 12 views
2

我在我的表上有一個自引用外鍵約束。因爲我改造的模式,我想現有的數據複製到一個新表(或多或少)相同的結構:將自引用數據插入副本表

CREATE TABLE test(
    id INT NOT NULL PRIMARY KEY, 
    parent INT, 
    FOREIGN KEY (parent) REFERENCES test(id) 
); 

CREATE TABLE copy(
    id INT NOT NULL PRIMARY KEY, 
    parent INT, 
    FOREIGN KEY (parent) REFERENCES copy(id) 
); 

然而,當inserting the data

INSERT INTO copy(id, parent) SELECT id, parent FROM test; 

MySQL允許我共同完整性錯誤:

Error Code: 1452. Cannot add or update a child row: 
    a foreign key constraint fails (`test`.`copy`, CONSTRAINT `copy_ibfk_1` 
    FOREIGN KEY (`parent`) REFERENCES `copy` (`id`)) 

似乎MySQL的插入每一行,而不是整個插入後檢查之後檢查約束。完全相同的例子works fine in PostgreSQL

是否有任何其他方式來插入這些數據還是我堅持這樣做在這樣的兩個步驟?

INSERT INTO copy(id) SELECT id FROM test; 
UPDATE copy 
JOIN test ON test.id = copy.id 
SET copy.parent = test.parent; 
+0

用MySQL,你只有這兩個選擇:禁止限制(如圖VMai),或在一個事務中執行插入/更新(因爲你現在做的)。 –

回答

1

您可以使用

SET FOREIGN_KEY_CHECKS=0; 
您的INSERT前

SET FOREIGN_KEY_CHECKS=1; 

後禁用外鍵約束的檢查,所以您不必擔心秩序的插頁:

請參閱foreign_key_checks的文檔

foreign_key_checks

If set to 1 (the default), foreign key constraints for InnoDB tables are checked. If set to 0, such constraints are ignored. [...] Typically you leave this setting enabled during normal operation, to enforce referential integrity. Disabling foreign key checking can be useful for reloading such tables in an order different from that required by their parent/child relationships. See Section 14.6.6, 「InnoDB and FOREIGN KEY Constraints」. [...]

Note

Setting foreign_key_checks to 1 does not trigger a scan of the existing table data. Therefore, rows added to the table while foreign_key_checks = 0 will not be verified for consistency.

CREATE TABLE test(
    id INT NOT NULL PRIMARY KEY, 
    parent INT, 
    FOREIGN KEY (parent) REFERENCES test(id) 
); 

CREATE TABLE copy(
    id INT NOT NULL PRIMARY KEY, 
    parent INT, 
    FOREIGN KEY (parent) REFERENCES copy(id) 
); 

INSERT INTO test(id, parent) VALUES(1, null); 
INSERT INTO test(id, parent) VALUES(2, 1); 
INSERT INTO test(id, parent) VALUES(3, null); 
INSERT INTO test(id, parent) VALUES(4, 2); 
UPDATE test SET parent=3 WHERE id=1; 

SET FOREIGN_KEY_CHECKS=0; 

-- Success with MySQL 
INSERT INTO copy(id, parent) SELECT id, parent FROM test; 

SET FOREIGN_KEY_CHECKS=1; 

您更新小提琴:http://sqlfiddle.com/#!2/ae623/1

+0

MySQL對'SET'命令有交易支持嗎? (我假設不)換句話說:如果事務在插入之前/之中/之後失敗會發生什麼?我寧願不放棄約束保證...... – r0estir0bbe

+0

@ r0estir0bbe我沒有看到任何問題的一次性工作。 – VMai