การทำสำเนาตารางดัชนีและข้อมูล MySQL


670

ฉันจะคัดลอกหรือโคลนหรือทำซ้ำข้อมูลโครงสร้างและดัชนีของตาราง MySQL ไปยังตารางใหม่ได้อย่างไร

นี่คือสิ่งที่ฉันได้พบ

สิ่งนี้จะคัดลอกข้อมูลและโครงสร้าง แต่ไม่ใช่ดัชนี:

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

สิ่งนี้จะคัดลอกโครงสร้างและดัชนี แต่ไม่ใช่ข้อมูล:

create table {new_table} like {old_table};

คำตอบ:


1489

ในการคัดลอกด้วยดัชนีและทริกเกอร์ให้ทำ 2 ข้อความค้นหานี้:

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

หากต้องการคัดลอกโครงสร้างและข้อมูลให้ใช้อันนี้:

CREATE TABLE tbl_new AS SELECT * FROM tbl_old;

ฉันเคยถามเรื่องนี้มาก่อน:

คัดลอกตาราง MySQL รวมถึงดัชนี


10
ที่น่าสังเกตว่าปุ่มต่างประเทศชี้ไป oldtable จะต้องถูกคัดลอกไป NewTable (ถ้าคุณกำลังแทนที่ oldtable)
จอร์จ

3
มันใช้งานได้กับตารางขนาดใหญ่ (ล้านเรคคอร์ด) หรือไม่ .. ฉันถามเพราะฉันไม่รู้ว่ามันselect *จะทำงานในตารางขนาดใหญ่ได้อย่างไร
fguillen

3
เพื่อให้แนวคิดคร่าว ๆ การแทรกใช้เวลา 27 นาทีในตาราง 16M แถว (5 ดัชนี) บน AWS db.r3. large อินสแตนซ์
hello_harry

6
เป็นที่น่าสังเกตว่าในขณะที่สิ่งนี้จะสร้างดัชนีจากตารางที่ถูกคัดลอกมันไม่ได้มีข้อ จำกัด เกี่ยวกับกุญแจต่างประเทศ
WebSmithery

15
หมายเหตุ: สิ่งนี้จะไม่คัดลอกAUTO_INCREMENTค่า
Matt Janssen

43

นอกเหนือจากวิธีการแก้ปัญหาข้างต้นคุณสามารถใช้ASเพื่อทำให้เป็นหนึ่งบรรทัด

CREATE TABLE tbl_new AS SELECT * FROM tbl_old;

32
สิ่งนี้จะไม่คัดลอกดัชนีและทริกเกอร์เนื่องจากผลลัพธ์ SELECT เป็นตารางชั่วคราว (ไม่มีชื่อ) และไม่ได้ "ดำเนินการ" เมทาดาทาของตารางต้นฉบับ พิจารณาว่าคุณกำลังใช้ฟังก์ชั่นหรือไม่
chx

1
ฉันกำลังมองหาการสำรองข้อมูลตารางโครงสร้างและย้ายข้อมูลเท่านั้นจึงลดลงดัชนี / ข้อ จำกัด / ฯลฯ ดังนั้นฉันสามารถสร้างพวกเขาใหม่ คำตอบนี้ยอดเยี่ยมมากเมื่อเห็นว่า Google ส่งฉันมาที่นี่
Ellesedil

3
ตรงนี้เป็นสิ่งที่เขากล่าวถึงแล้วในคำถาม create table {new_table} select * from {old_table};ไม่ใช่คำตอบและไม่ให้ข้อมูลใหม่
billynoah

14

วิธี MySQL:

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

นี่ควรเป็นคำตอบที่ยอมรับได้ เนื่องจากเป็นการคัดลอกดัชนีทั้งหมดรวมถึงคีย์หลักและ auto_increment
Channaveer Hakari

10

ไปที่phpMyAdminและเลือกตารางต้นฉบับของคุณจากนั้นเลือกแท็บ " การดำเนินการ " ในพื้นที่ " คัดลอกตารางไปยัง (ฐานข้อมูลตาราง) " เลือกฐานข้อมูลที่คุณต้องการคัดลอกและเพิ่มชื่อสำหรับตารางใหม่ของคุณ

คัดลอกตาราง - ภาพหน้าจอ phyMyAdmin


1
@AaronJSpetner คำตอบนี้ยังมีประโยชน์สำหรับผู้ใช้รายอื่นที่มาที่คำถามนี้และสามารถใช้ PHPMyAdmin เพื่อแก้ปัญหาได้
ใหม่

3

ฉันพบสถานการณ์เดียวกันและวิธีการที่ฉันใช้คือ:

  1. ดำเนินการSHOW CREATE TABLE <table name to clone>: นี่จะให้Create Tableไวยากรณ์สำหรับตารางที่คุณต้องการโคลน
  2. เรียกใช้CREATE TABLEแบบสอบถามโดยเปลี่ยนชื่อตารางเพื่อโคลนตาราง

สิ่งนี้จะสร้างแบบจำลองที่แน่นอนของตารางที่คุณต้องการโคลนพร้อมกับดัชนี สิ่งเดียวที่คุณต้องมีคือเปลี่ยนชื่อดัชนี (ถ้าจำเป็น)


2

วิธีที่ดีกว่าในการทำสำเนาตารางคือการใช้เท่านั้น DDLคำสั่งด้วยวิธีนี้เป็นอิสระจากจำนวนระเบียนในตารางคุณสามารถทำซ้ำได้ทันที

จุดประสงค์ของฉันคือ:

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;

นี่เป็นการหลีกเลี่ยงINSERT AS SELECTข้อความที่ว่าในกรณีของตารางที่มีระเบียนจำนวนมาก

ฉันขอแนะนำให้สร้างโพรซีเดอร์ PLSQL ตามตัวอย่างต่อไปนี้:

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 ;

ขอให้มีความสุขมาก ๆ ในวันนี้! อเล็กซ์


มีใครลองบ้างไหม มันทำงานได้ตามที่คาดไว้หรือไม่
Radu Murzea

1

การขยายคำตอบนี้สามารถใช้ขั้นตอนการจัดเก็บ:

CALL duplicate_table('tableName');

ซึ่งจะส่งผลให้ตารางซ้ำกันเรียกว่าtableName_20181022235959ถ้าเรียกว่าเมื่อใด

SELECT NOW();

ผล:

2018-10-22 23:59:59

การดำเนินงาน

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

หลังจากที่ฉันลองวิธีแก้ปัญหาข้างต้นฉันก็คิดวิธีของตัวเอง

โซลูชันของฉันเป็นคู่มือเล็กน้อยและต้องการ DBMS

ก่อนส่งออกข้อมูล

ประการที่สองเปิดข้อมูลการส่งออก

ประการที่สามแทนที่ชื่อตารางเก่าด้วยชื่อตารางใหม่

ประการที่สี่เปลี่ยนชื่อทริกเกอร์ทั้งหมดในข้อมูล (ฉันใช้ MySQL และมันแสดงข้อผิดพลาดเมื่อฉันไม่เปลี่ยนชื่อทริกเกอร์)

ประการที่ห้านำเข้าข้อมูล SQL ที่แก้ไขแล้วของคุณไปยังฐานข้อมูล


0

ลองสิ่งนี้:

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

ฉันเลือก 4 คอลัมน์จากตารางเก่าแล้วสร้างตารางใหม่


-2

สำหรับ MySQL

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

สำหรับการใช้ MSSQL MyDatabase:

Select * into newCustomersTable  from oldCustomersTable;

SQL นี้จะใช้สำหรับการคัดลอกตารางที่นี่เนื้อหาของ oldCustomersTable newCustomersTableจะถูกคัดลอกไป
ตรวจสอบให้แน่ใจว่าnewCustomersTable ไม่มีอยู่ในฐานข้อมูล


4
Thows error SQL Error (3172): ตัวแปรที่ไม่ได้ประกาศ: 'newCustomerTable'
mikewasmike

คุณต้องทำอะไรผิดพลาด เช่นนี้จะทำงานได้ 100% อ่านก่อนที่คุณจะให้คะแนนลบ การอ้างอิงเนื้อหาสำหรับคุณ w3schools.com/sql/sql_select_into.asp
Krishneil

1
โปรดทราบว่าคำถามนั้นเกี่ยวกับ MySQL อาจไม่รองรับไวยากรณ์ SQL บางรายการ
mikewasmike

1
วิธีการสร้าง MySQL สูตรตาราง _new เช่นการผลิต. INSERT recipes_new SELECT * จาก production.recipes;
Krishneil

1
ฉันได้แก้ไขคำถามของฉันเนื่องจากคำตอบก่อนหน้านี้มีไว้สำหรับ MSSQLL เท่านั้น
Krishneil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.