Duplikowanie tabeli MySQL, indeksów i danych

669

Jak skopiować, sklonować lub zduplikować dane, strukturę i indeksy tabeli MySQL do nowej?

To właśnie znalazłem do tej pory.

Spowoduje to skopiowanie danych i struktury, ale nie indeksów:

create table {new_table} select * from {old_table};

Spowoduje to skopiowanie struktury i indeksów, ale nie danych:

create table {new_table} like {old_table};
xkcd150
źródło

Odpowiedzi:

1488

Aby skopiować z indeksami i wyzwalaczami, wykonaj następujące 2 zapytania:

CREATE TABLE newtable LIKE oldtable; 
INSERT INTO newtable SELECT * FROM oldtable;

Aby skopiować tylko strukturę i dane, użyj tego:

CREATE TABLE tbl_new AS SELECT * FROM tbl_old;

Pytałem o to wcześniej:

Skopiuj tabelę MySQL wraz z indeksami

Haim Evgi
źródło
10
Warto zauważyć, że klucze obce wskazujące na oldtable będą musiały zostać skopiowane do newtable (jeśli wymieniasz oldtable)
George
3
Czy to działa w przypadku dużych tabel (miliony rekordów)? .. Pytam, ponieważ nie wiem, jak to select *będzie działać w dużych tabelach.
fguillen,
3
Aby dać ogólny pomysł, operacja wstawiania zajęła 27 minut na tabeli 16 mln wierszy (z 5 indeksami) na instancji AWS db.r3.large
hello_harry
6
Warto zauważyć, że chociaż odtwarza indeksy z kopiowanej tabeli, nie przenosi żadnych ograniczeń klucza obcego.
WebSmithery
15
Uwaga: nie spowoduje to skopiowania AUTO_INCREMENTwartości.
Matt Janssen
43

Oprócz powyższego rozwiązania możesz użyć ASgo w jednym wierszu.

CREATE TABLE tbl_new AS SELECT * FROM tbl_old;
theDistantStar
źródło
32
Nie spowoduje to skopiowania indeksów i wyzwalaczy, ponieważ wynik SELECT jest (nienazwaną) tabelą tymczasową i nie „przenosi” metadanych tabeli źródłowej. Zastanów się, czy będziesz używać funkcji, nie ma to sensu.
chx
1
Chciałem wykonać kopię zapasową tabeli struktur i przenieść tylko dane, usuwając w ten sposób indeksy / ograniczenia / itp. żebym mógł je odtworzyć. Ta odpowiedź była niesamowita pod tym względem, gdy Google przysłało mnie tutaj.
Ellesedil
3
dokładnie to właśnie wspomina w pytaniu: create table {new_table} select * from {old_table};nie ma odpowiedzi i nie zawiera żadnych nowych informacji.
billynoah
14

Sposób MySQL:

CREATE TABLE recipes_new LIKE production.recipes;
INSERT recipes_new SELECT * FROM production.recipes;
Krishneil
źródło
To powinna być zaakceptowana odpowiedź. Ponieważ kopiuje to wszystkie indeksy, w tym klucz podstawowy i auto_increment
Channaveer Hakari,
10

Przejdź do phpMyAdmin i wybierz oryginalną tabelę, a następnie wybierz zakładkę „ Operacje ” w obszarze „ Kopiuj tabelę do (table.table) ”. Wybierz bazę danych, którą chcesz skopiować, i dodaj nazwę nowej tabeli.

tabela kopiowania - zrzut ekranu phyMyAdmin

spuvi86
źródło
1
@AaronJSpetner Ta odpowiedź jest nadal pomocna dla innych użytkowników, którzy przychodzą na to pytanie i są w stanie wykorzystać PHPMyAdmin do rozwiązania problemu.
zreformowany
3

Znalazłem tę samą sytuację, a moje podejście było następujące:

  1. Wykonaj SHOW CREATE TABLE <table name to clone>: da ci Create Tableskładnię tabeli, którą chcesz sklonować
  2. Uruchom CREATE TABLEzapytanie, zmieniając nazwę tabeli, aby sklonować tabelę.

Spowoduje to utworzenie dokładnej repliki tabeli, którą chcesz sklonować wraz z indeksami. Jedyne, czego potrzebujesz, to zmienić nazwy indeksów (jeśli jest to wymagane).

Jai
źródło
2

Lepszym sposobem na zduplikowanie tabeli jest użycie tylko DDLinstrukcji. W ten sposób, niezależnie od liczby rekordów w tabeli, możesz natychmiast wykonać duplikację.

Moim celem jest:

DROP TABLE IF EXISTS table_name_OLD;
CREATE TABLE table_name_NEW LIKE table_name;
RENAME TABLE table_name TO table_name_OLD;
RENAME TABLE table_name _NEW TO table_name;

Pozwala to uniknąć INSERT AS SELECTstwierdzenia, że ​​w przypadku tabeli z dużą ilością rekordów wykonanie może zająć trochę czasu.

Proponuję również utworzyć procedurę PLSQL jako następujący przykład:

DELIMITER //
CREATE PROCEDURE backup_table(tbl_name varchar(255))
BEGIN
  -- DROP TABLE IF EXISTS GLS_DEVICES_OLD;
  SET @query = concat('DROP TABLE IF EXISTS ',tbl_name,'_OLD');
  PREPARE stmt FROM @query;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;

  -- CREATE TABLE GLS_DEVICES_NEW LIKE GLS_DEVICES;
  SET @query = concat('CREATE TABLE ',tbl_name,'_NEW LIKE ',tbl_name);
  PREPARE stmt FROM @query;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;

  -- RENAME TABLE GLS_DEVICES TO GLS_DEVICES_OLD;
  SET @query = concat('RENAME TABLE ',tbl_name,' TO ',tbl_name,'_OLD');
  PREPARE stmt FROM @query;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;  

  --  RENAME TABLE GLS_DEVICES_NEW TO GLS_DEVICES;
  SET @query = concat('RENAME TABLE ',tbl_name,'_NEW TO ',tbl_name);
  PREPARE stmt FROM @query;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt; 
END//
DELIMITER ;

Miłego dnia! Alex

Alessandro
źródło
Czy ktoś tego próbował? Czy działa zgodnie z oczekiwaniami?
Radu Murzea
1

Rozwijając tę odpowiedź, można użyć procedury składowanej:

CALL duplicate_table('tableName');

Co spowoduje utworzenie zduplikowanej tabeli o nazwie tableName_20181022235959 If when when

SELECT NOW();

wyniki:

2018-10-22 23:59:59

Realizacja

DELIMITER $$
CREATE PROCEDURE duplicate_table(IN tableName VARCHAR(255))
  BEGIN
    DECLARE schemaName VARCHAR(255) DEFAULT SCHEMA();
    DECLARE today VARCHAR(14) DEFAULT REPLACE(REPLACE(REPLACE(NOW(), '-', ''), ' ', ''), ':', ''); -- update @ year 10000
    DECLARE backupTableName VARCHAR(255) DEFAULT CONCAT(tableName, '_', today);

    IF fn_table_exists(schemaName, tableName)
      THEN
        CALL statement(CONCAT('CREATE TABLE IF NOT EXISTS ', backupTableName,' LIKE ', tableName));
        CALL statement(CONCAT('INSERT INTO ', backupTableName,' SELECT * FROM ', tableName));
        CALL statement(CONCAT('CHECKSUM TABLE ', backupTableName,', ', tableName));
      ELSE
        SELECT CONCAT('ERROR: Table "', tableName, '" does not exist in the schema "', schemaName, '".') AS ErrorMessage;
      END IF;
  END $$
DELIMITER ;

DELIMITER $$
CREATE FUNCTION fn_table_exists(schemaName VARCHAR(255), tableName VARCHAR(255))
  RETURNS TINYINT(1)
  BEGIN
    DECLARE totalTablesCount INT DEFAULT (
      SELECT COUNT(*)
      FROM information_schema.TABLES
      WHERE (TABLE_SCHEMA COLLATE utf8_general_ci = schemaName COLLATE utf8_general_ci)
        AND (TABLE_NAME COLLATE utf8_general_ci = tableName COLLATE utf8_general_ci)
    );
    RETURN IF(
      totalTablesCount > 0,
      TRUE,
      FALSE
    );
  END $$
DELIMITER ;

DELIMITER $$
CREATE PROCEDURE statement(IN dynamic_statement TEXT)
  BEGIN
      SET @dynamic_statement := dynamic_statement;
      PREPARE prepared_statement FROM @dynamic_statement;
      EXECUTE prepared_statement;
      DEALLOCATE PREPARE prepared_statement;
  END $$
DELIMITER ;
Nie
źródło
1

Po wypróbowaniu powyższego rozwiązania wymyślam własną drogę.

Moje rozwiązanie jest trochę manualne i wymaga DBMS.

Najpierw wyeksportuj dane.

Po drugie, otwórz dane eksportu.

Po trzecie, zastąp starą nazwę tabeli nową nazwą tabeli.

Po czwarte, zmień całą nazwę wyzwalacza w danych (używam MySQL i pokazuje błąd, gdy nie zmieniam nazwy wyzwalacza).

Po piąte, zaimportuj zmodyfikowane dane SQL do bazy danych.

Võ Minh
źródło
0

Spróbuj tego :

`CREATE TABLE new-table (id INT(11) auto_increment primary key) SELECT old-table.name, old-table.group, old-table.floor, old-table.age from old-table;`

Wybrałem 4 kolumny ze starej tabeli i utworzyłem nową tabelę.

Crazy_DT0
źródło
-2

DLA MySQL

CREATE TABLE newtable LIKE oldtable ; 
INSERT newtable SELECT * FROM oldtable ;

DLA MSSQL Użyj MyDatabase:

Select * into newCustomersTable  from oldCustomersTable;

Ten SQL jest używany do kopiowania tabel, tutaj zawartość oldCustomersTable zostanie skopiowana newCustomersTable.
Upewnij się, że newCustomersTable nie istnieje w bazie danych.

Krishneil
źródło
4
Zgłasza błąd Błąd SQL (3172): Niezadeklarowana zmienna: „newCustomerTable”
mikewasmike
Musisz robić coś złego. Ponieważ będzie to działać w 100%. Przeczytaj zanim oddasz głos negatywny. Referencje dla Ciebie. w3schools.com/sql/sql_select_into.asp
Krishneil
1
Zauważ, że pytanie dotyczy MySQL. Niektóre składnie SQL mogą nie być obsługiwane.
mikewasmike
1
MySQL Way CREATE TABLE recipes_new LIKE production.recipes; INSERT recipes_new SELECT * FROM production.recipes;
Krishneil,
1
Zredagowałem swoje pytanie, ponieważ poprzednia odpowiedź dotyczyła tylko MSSQLL
Krishneil