MySQL 테이블, 인덱스 및 데이터 복제


669

MySQL 테이블의 데이터, 구조 및 인덱스를 새로운 테이블로 복사 또는 복제 또는 복제하려면 어떻게해야합니까?

이것이 내가 지금까지 찾은 것입니다.

이것은 데이터와 구조를 복사하지만 인덱스는 복사하지 않습니다.

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

이것은 구조와 색인을 복사하지만 데이터는 복사하지 않습니다.

create table {new_table} like {old_table};

답변:


1488

인덱스와 트리거로 복사하려면 다음 두 쿼리를 수행하십시오.

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을 교체하는 경우)
George

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

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으로 이동 하여 원본 테이블을 선택한 다음 "(테이블 을 datadata.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 ;

좋은 하루 보내세요! 알렉스


누구든지 이것을 시도 했습니까? 예상대로 작동합니까?
Radu Murzea는

1

이 답변을 확장 하면 저장 프로 시저를 사용할 수 있습니다.

CALL duplicate_table('tableName');

어떤 tableName_20181022235959경우 호출하면 If라는 중복 테이블이 생성 됩니다.

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
슬로우하는 오류 SQL 오류 (3172) : 선언되지 않은 변수 : 'newCustomerTable'
mikewasmike

당신은 뭔가 잘못하고 있어야합니다. 이것은 100 % 작동합니다. 부정적인 투표를하기 전에 읽으십시오. 당신을위한 콘텐츠 참조. w3schools.com/sql/sql_select_into.asp
Krishneil

1
질문은 MySQL에 관한 것입니다. 일부 SQL 구문이 지원되지 않을 수 있습니다.
mikewasmike

1
MySQL 방식 CREATE TABLE recipes_new LIKE production.recipes; INSERT recipes_new SELECT * FROM production.recipes;
Krishneil 2016

1
이전 답변이 MSSQLL에 대한 것이므로 질문을 편집했습니다.
Krishneil
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.