Duplizieren einer MySQL-Tabelle, von Indizes und Daten


668

Wie kopiere oder klone oder dupliziere ich die Daten, Strukturen und Indizes einer MySQL-Tabelle in eine neue?

Das habe ich bisher gefunden.

Dadurch werden die Daten und die Struktur kopiert, nicht jedoch die Indizes:

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

Dadurch werden die Struktur und die Indizes kopiert, nicht jedoch die Daten:

create table {new_table} like {old_table};

Antworten:


1487

Führen Sie diese beiden Abfragen aus, um mit Indizes und Triggern zu kopieren:

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

Um nur Struktur und Daten zu kopieren, verwenden Sie diese:

CREATE TABLE tbl_new AS SELECT * FROM tbl_old;

Ich habe das schon einmal gefragt:

Kopieren Sie eine MySQL-Tabelle mit Indizes


10
Es ist erwähnenswert, dass Fremdschlüssel, die auf oldtable verweisen, in newtable kopiert werden müssen (wenn Sie oldtable ersetzen)
George

3
Funktioniert dies für große Tabellen (Millionen von Datensätzen)? .. Ich frage, weil ich nicht weiß, wie dies select *in großen Tabellen funktioniert .
Fguillen

3
Um eine grobe Vorstellung zu geben, dauerte die Einfügeoperation 27 Minuten in einer Tabelle mit 16 Millionen Zeilen (mit 5 Indizes) auf einer AWS db.r3.large-Instanz
hello_harry

6
Es ist erwähnenswert, dass , während diese die Indizes aus der Tabelle neu erstellt werden kopiert, es ist nicht keinen Fremdschlüssel - Constraints trägt über.
WebSmithery

15
Hinweis: Dadurch wird der AUTO_INCREMENTWert nicht kopiert .
Matt Janssen

43

Abgesehen von der obigen Lösung können Sie ASes in einer Zeile erstellen.

CREATE TABLE tbl_new AS SELECT * FROM tbl_old;

32
Dadurch werden keine Indizes und Trigger kopiert, da das SELECT-Ergebnis eine (unbenannte) temporäre Tabelle ist und die Metadaten der Quelltabelle nicht "trägt". Überlegen Sie, ob Sie Funktionen verwenden würden, die keinen Sinn ergeben.
chx

1
Ich habe versucht, die Strukturtabelle zu sichern und nur die Daten zu verschieben, wodurch Indizes / Einschränkungen / etc. so konnte ich sie neu erstellen. Diese Antwort war in dieser Hinsicht fantastisch, da Google mich hierher geschickt hat.
Ellesedil

3
Genau das erwähnt er bereits in der Frage: create table {new_table} select * from {old_table};keine Antwort und liefert keine neuen Informationen.
Billynoah

13

MySQL-Weg:

CREATE TABLE recipes_new LIKE production.recipes;
INSERT recipes_new SELECT * FROM production.recipes;

Dies sollte die akzeptierte Antwort gewesen sein. Da dies alle Indizes einschließlich Primärschlüssel und auto_increment kopiert
Channaveer Hakari

10

Gehen Sie zu phpMyAdmin und wählen Sie Ihre ursprüngliche Tabelle aus. Wählen Sie dann die Registerkarte " Operationen " im Bereich " Tabelle in (database.table) kopieren ". Wählen Sie die Datenbank aus, in die Sie kopieren möchten, und fügen Sie einen Namen für Ihre neue Tabelle hinzu.

Tabelle kopieren - phyMyAdmin Screenshot


1
@AaronJSpetner Diese Antwort ist weiterhin hilfreich für andere Benutzer, die auf diese Frage kommen und PHPMyAdmin zur Lösung des Problems verwenden können.
Reformiert

3

Ich fand die gleiche Situation und ging wie folgt vor:

  1. Ausführen SHOW CREATE TABLE <table name to clone>: Hiermit erhalten Sie die Create TableSyntax für die Tabelle, die Sie klonen möchten
  2. Führen Sie die CREATE TABLEAbfrage aus, indem Sie den Tabellennamen ändern, um die Tabelle zu klonen.

Dadurch wird eine exakte Replik der Tabelle erstellt, die Sie zusammen mit den Indizes klonen möchten. Sie müssen dann nur noch die Indizes umbenennen (falls erforderlich).


2

Der bessere Weg, eine Tabelle zu duplizieren, besteht darin, nur eine DDLAnweisung zu verwenden. Auf diese Weise können Sie unabhängig von der Anzahl der Datensätze in der Tabelle die Duplizierung sofort durchführen.

Mein Zweck ist:

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;

Dies vermeidet die INSERT AS SELECTAussage, dass die Ausführung bei Tabellen mit vielen Datensätzen einige Zeit in Anspruch nehmen kann.

Ich schlage auch vor, eine PLSQL-Prozedur als folgendes Beispiel zu erstellen:

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 ;

Einen schönen Tag noch! Alex


1

Wenn man diese Antwort erweitert , könnte man eine gespeicherte Prozedur verwenden:

CALL duplicate_table('tableName');

Dies führt zu einer doppelten Tabelle mit dem Namen tableName_20181022235959If when when

SELECT NOW();

Ergebnisse:

2018-10-22 23:59:59

Implementierung

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 ;

1

Nachdem ich die obige Lösung ausprobiert habe, habe ich meinen eigenen Weg gefunden.

Meine Lösung ist ein wenig manuell und benötigt DBMS.

Exportieren Sie zunächst die Daten.

Zweitens öffnen Sie die Exportdaten.

Drittens ersetzen Sie den alten Tabellennamen durch den neuen Tabellennamen.

Viertens ändern Sie den gesamten Triggernamen in den Daten (ich verwende MySQL und es wird ein Fehler angezeigt, wenn ich den Triggernamen nicht ändere).

Fünftens importieren Sie Ihre bearbeiteten SQL-Daten in die Datenbank.


0

Versuche dies :

`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;`

Ich habe 4 Spalten aus der alten Tabelle ausgewählt und eine neue Tabelle erstellt.


-2

FÜR MySQL

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

FÜR MSSQL Verwendung MyDatabase:

Select * into newCustomersTable  from oldCustomersTable;

Diese SQL wird zum Kopieren von Tabellen verwendet. Hier wird der Inhalt von oldCustomersTable kopiert newCustomersTable.
Stellen Sie sicher, dass das newCustomersTable nicht in der Datenbank vorhanden ist.


4
Wirft Fehler SQL-Fehler (3172): Nicht deklarierte Variable: 'newCustomerTable'
mikewasmike

Sie müssen etwas falsch machen. Da dies zu 100% funktioniert. Lesen Sie, bevor Sie eine negative Stimme abgeben. Inhaltsreferenz für Sie. w3schools.com/sql/sql_select_into.asp
Krishneil

1
Beachten Sie, dass es sich bei der Frage um MySQL handelt. Einige SQL-Syntaxen werden möglicherweise nicht unterstützt.
Mikewasmike

1
MySQL Way CREATE TABLE rezepte_neu LIKE Production.recipes; INSERT Rezepte_neu SELECT * FROM Production.recipes;
Krishneil

1
Ich habe meine Frage bearbeitet, da die vorherige Antwort nur für MSSQLL
Krishneil
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.