复制MySQL表,索引和数据


668

如何将MySQL表的数据,结构和索引复制或克隆或复制到新表?

这是我到目前为止发现的。

这将复制数据和结构,但不复制索引:

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

这将复制结构和索引,但不复制数据:

create table {new_table} like {old_table};

Answers:


1487

要使用索引和触发器进行复制,请执行以下两个查询:

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
大致来说,在AWS db.r3.large实例上的16M行(含5个索引)表上的插入操作花费了27分钟
hello_harry

6
值得注意的是,虽然这会从要复制的表中重新创建索引,但它不会保留任何外键约束。
WebSmithery

15
注意:这不会复制该AUTO_INCREMENT值。
马特·詹森

43

除了上述解决方案之外,您还可以将AS其制作成一行。

CREATE TABLE tbl_new AS SELECT * FROM tbl_old;

32
这将不会复制索引和触发器,因为SELECT结果是一个(未命名的)临时表,并且不会“携带”源表的元数据。考虑一下是否要使用函数,这没有任何意义。
chx 2015年

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并选择原始表,然后在“ 将表复制到(database.table) ”区域中选择“ 操作 ”选项卡。选择要复制的数据库,并为新表添加名称。

复制表-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 ;

祝你今天愉快!亚历克斯


1

扩展这个答案可以使用存储过程:

CALL duplicate_table('tableName');

这将导致一个名为tableName_20181022235959If 的重复表

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错误SQL错误(3172):未声明的变量:“ newCustomerTable”
mikewasmike

你一定做错了。因为这将工作100%。在您投反对票之前,请先阅读。内容参考给您。w3schools.com/sql/sql_select_into.asp
Krishneil

1
请注意,问题与MySQL有关。某些SQL语法可能不受支持。
mikewasmike

1
MySQL Way CREATE TABLE recipes_new LIKE production.recipes; INSERT recipes_new SELECT * FROM production.recipes;
Krishneil

1
我已经编辑了问题,因为先前的答案仅适用于MSSQLL
Krishneil
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.