Comment fusionner deux tables MySQL?

92

Comment fusionner deux tables MySQL qui ont la même structure?

Les clés primaires des deux tables entreront en conflit, j'en ai donc tenu compte.

Steve McLeod
la source
6
Lorsque vous dites que les PK peuvent entrer en conflit, cela signifie qu'il peut y avoir des lignes dupliquées et que vous ne voulez pas qu'elles soient copiées, ou que vous devez attribuer un nouveau PK à l'un d'entre eux car ce sont des lignes vraiment différentes malgré même PK? (encore une autre raison d'utiliser les clés primaires naturelles)
Tom H

Réponses:

123

Vous pouvez également essayer:

INSERT IGNORE
  INTO table_1 
SELECT *
  FROM table_2
     ;

qui permet aux lignes de table_1 de remplacer celles de table_2 qui ont une clé primaire correspondante, tout en insérant toujours des lignes avec de nouvelles clés primaires.

Alternativement,

REPLACE
   INTO table_1
 SELECT *
   FROM table_2
      ;

mettra à jour ces lignes déjà dans table_1 avec la ligne correspondante de table_2, tout en insérant des lignes avec de nouvelles clés primaires.

fcw
la source
2
En fait, il remplacera les lignes existantes (supprimer + insérer), pas de mise à jour.
Cees Timmerman
et si une clé étrangère est utilisée pour la table 2 ????? Comment allez-vous mettre cela à jour?
Kshitiz le
39

Cela dépend de la sémantique de la clé primaire. S'il ne s'agit que d'auto-incrémentation, utilisez quelque chose comme:

insert into table1 (all columns except pk)
select all_columns_except_pk 
from table2;

Si PK signifie quelque chose, vous devez trouver un moyen de déterminer quel enregistrement doit avoir la priorité. Vous pouvez créer une requête de sélection pour trouver d'abord les doublons (voir réponse par cpitis ). Ensuite, éliminez ceux que vous ne souhaitez pas conserver et utilisez l'insert ci-dessus pour ajouter des enregistrements qui restent.

Milan Babuškov
la source
21
INSERT
INTO    first_table f
SELECT  *
FROM    second_table s
ON DUPLICATE KEY
UPDATE
        s.column1 = DO_WHAT_EVER_MUST_BE_DONE_ON_KEY_CLASH(f.column1)
Quassnoi
la source
1
Merci pour la bonne idée. La cmd ci-dessus me donne cependant une erreur de syntaxe. Mais cela fonctionne pour moi: INSERT INTO first_table SELECT * FROM second_table ON DUPLICATE KEY UPDATE second_table.column1 = DO_WHAT_EVER_MUST_BE_DONE_ON_KEY_CLASH (first_table.column1)
Tapper
Tout comme @Tapper, je n'ai pas pu attribuer un alias à la première table. J'obtiendrais Syntax error, unexpected IDENT_QUOTED- par MySQL Workbench de toute façon.
blo0p3r
Pourriez-vous donner un exemple de la commande que vous saisiriez sur la dernière ligne? Je voudrais que l'ID augmente à partir de l'ID existant le plus élevé du tableau
Elliott B
15

Si vous devez le faire manuellement, une fois:

Tout d'abord, fusionnez dans une table temporaire, avec quelque chose comme:

create table MERGED as select * from table 1 UNION select * from table 2

Ensuite, identifiez les contraintes de clé primaire avec quelque chose comme

SELECT COUNT(*), PK from MERGED GROUP BY PK HAVING COUNT(*) > 1

Où PK est le champ de clé primaire ...

Résolvez les doublons.

Renommez la table.

[modifié - suppression des crochets dans la requête UNION, ce qui provoquait l'erreur dans le commentaire ci-dessous]

Cătălin Pitiș
la source
quand j'essaye ceci, j'ai reçu cette erreur, "ERREUR 1064 (42000): Vous avez une erreur dans votre syntaxe SQL; vérifiez le manuel qui correspond à votre version de serveur MySQL pour la bonne syntaxe à utiliser près de 'UNION select * from actor)' à la ligne ", pourquoi est-ce?
jcho360
7

Pas aussi compliqué que cela puisse paraître ... Laissez simplement la clé primaire en double hors de votre requête ... cela fonctionne pour moi!

INSERT INTO
  Content(
    `status`,
    content_category,
    content_type,
    content_id,
    user_id,
    title,
    description,
    content_file,
    content_url,
    tags,
    create_date,
    edit_date,
    runs
  )
SELECT `status`,
  content_category,
  content_type,
  content_id,
  user_id,
  title,
  description,
  content_file,
  content_url,
  tags,
  create_date,
  edit_date,
  runs
FROM
  Content_Images
Bill Warren
la source
0

Vous pouvez écrire un script pour mettre à jour les FK pour vous .. consultez ce blog: http://multunus.com/2011/03/how-to-easily-merge-two-identical-mysql-databases/

Ils ont un script intelligent pour utiliser les tables information_schema pour obtenir les colonnes "id":

SET @db:='id_new'; 

select @max_id:=max(AUTO_INCREMENT) from information_schema.tables;

select concat('update ',table_name,' set ', column_name,' = ',column_name,'+',@max_id,' ; ') from information_schema.columns where table_schema=@db and column_name like '%id' into outfile 'update_ids.sql';

use id_new
source update_ids.sql;
TimoSolo
la source