Aqui está um caso mínimo para o meu esquema de banco de dados:
CREATE TABLE `test` (
`id` int(11) NOT NULL,
`name` varchar(22) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `test2` (
`id` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `test2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `test` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Bem, e o que temos dentro:
mysql> select * from test;
+-----+-------+
| id | name |
+-----+-------+
| 111 | AAABA |
+-----+-------+
1 row in set (0.00 sec)
mysql> select * from test2;
+-----+
| id |
+-----+
| 111 |
+-----+
1 row in set (0.00 sec)
Agora eu preciso ler de um arquivo csv externo, com chave primária duplicada, na primeira tabela:
mysql> LOAD data infile '/tmp/tar.csv' REPLACE INTO TABLE test FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"';
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`eduman`.`test2`, CONSTRAINT `test2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `test` (`id`))
E o conteúdo de /tmp/tar.csv:
%> cat /tmp/tar.csv
111,AAA
Como eu sei do MySQL, ele provavelmente faz um 'excluir' e depois 'inserir', o que causou o problema, não pode ser excluído porque a chave estrangeira existe. Então, como posso forçar uma atualização a ser executada, em vez de 'excluir e inserir'?
Aprecie qualquer uma de suas respostas.
Na internet, encontrei uma maneira viável, que suprime as verificações temporariamente, mas existe alguma resposta melhor, parece um hack sujo e não tenho certeza se isso pode ser um problema em ambiente multiusuário, por exemplo, outra tabela com restrições de chave estrangeira podem ser danificados.
SET FOREIGN_KEY_CHECKS = 0;
Blabla ...
SET FOREIGN_KEY_CHECKS = 1;
http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
O link acima explica claramente que o mysqldump também coloca set Foreign_key_checks = 0; no arquivo de despejo para que os dados possam ser restaurados sem o erro de restrição de chave estrangeira. Eu sempre usei set Foreign_key_checks = 0 para importar dados para tabelas e, em seguida, defini-lo de volta para 1.