Jak mogę połączyć dwie tabele MySQL?

94

Jak mogę scalić dwie tabele MySQL o tej samej strukturze?

Klucze podstawowe obu tabel będą ze sobą kolidować, więc wziąłem to pod uwagę.

Steve McLeod
źródło
6
Kiedy mówisz, że PK mogą się ze sobą kolidować, czy masz na myśli to, że mogą istnieć zduplikowane wiersze i nie chcesz ich kopiować, lub że musisz przypisać nowy PK do jednego z nich, ponieważ są naprawdę różnymi wierszami pomimo posiadania ten sam PK? (kolejny powód, aby używać naturalnych kluczy głównych)
Tom H

Odpowiedzi:

124

Możesz też spróbować:

INSERT IGNORE
  INTO table_1 
SELECT *
  FROM table_2
     ;

co pozwala tym wierszom w tabeli_1 zastąpić wiersze w tabeli_2, które mają zgodny klucz podstawowy, jednocześnie wstawiając wiersze z nowymi kluczami podstawowymi.

Alternatywnie,

REPLACE
   INTO table_1
 SELECT *
   FROM table_2
      ;

zaktualizuje te wiersze już w tabeli_1 o odpowiadające im wiersze z tabeli_2, podczas wstawiania wierszy z nowymi kluczami podstawowymi.

fcw
źródło
2
W rzeczywistości ZMIENI istniejące wiersze (usuń + wstaw), a nie zaktualizuje.
Cees Timmerman
a co jeśli jest jakiś klucz obcy używany w tabeli 2 ????? Jak to zaktualizujesz?
Kshitiz
39

Zależy to od semantyki klucza podstawowego. Jeśli to tylko autoinkrementacja, użyj czegoś takiego:

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

Jeśli PK coś znaczy, musisz znaleźć sposób na określenie, który rekord powinien mieć priorytet. Możesz utworzyć zapytanie wybierające, aby najpierw znaleźć duplikaty (patrz odpowiedź według cpitis ). Następnie usuń te, których nie chcesz zachować i użyj powyższej wstawki, aby dodać pozostałe rekordy.

Milan Babuškov
źródło
22
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
źródło
1
Dzięki za dobry pomysł. Powyższe cmd powoduje jednak błąd składniowy. Ale to działa dla mnie: 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
Podobnie jak @Tapper, nie mogłem przypisać aliasu do pierwszej tabeli. Chciałbym dostać Syntax error, unexpected IDENT_QUOTED- przez MySQL Workbench jakikolwiek.
blo0p3r
Czy możesz podać przykład polecenia, które wpisałeś w ostatnim wierszu? Chciałbym, aby identyfikator wzrastał z najwyższego istniejącego identyfikatora w tabeli
Elliott B
15

Jeśli musisz to zrobić ręcznie, jednorazowo:

Najpierw połącz tabelę tymczasową z czymś takim:

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

Następnie zidentyfikuj ograniczenia klucza podstawowego za pomocą czegoś takiego jak

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

Gdzie PK to pole klucza podstawowego ...

Rozwiąż duplikaty.

Zmień nazwę tabeli.

[edytowano - usunięto nawiasy w zapytaniu UNION, które powodowały błąd w komentarzu poniżej]

Cătălin Pitiș
źródło
kiedy próbuję tego, otrzymałem ten błąd: „BŁĄD 1064 (42000): Masz błąd w składni SQL; sprawdź instrukcję, która odpowiada Twojej wersji serwera MySQL, aby znaleźć właściwą składnię w pobliżu„ UNION select * from actor) ” na linii ”, dlaczego tak jest?
jcho360
7

Nie jest to tak skomplikowane, jak się wydaje ... Po prostu pozostaw zduplikowany klucz podstawowy poza swoim zapytaniem ... to działa dla mnie!

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
źródło
0

Możesz napisać skrypt, który zaktualizuje dla Ciebie FK. Zajrzyj na tego bloga: http://multunus.com/2011/03/how-to-easily-merge-two-identical-mysql-databases/

Mają sprytny skrypt, który wykorzystuje tabele information_schema do pobierania kolumn „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
źródło