【问题标题】:How to duplicate a schema in mysql database如何在mysql数据库中复制模式
【发布时间】:2021-01-16 15:28:06
【问题描述】:

目标

在mysql数据库中复制一个模式,不转储sql文件并执行它们。

如果有一种方法可以通过几个命令完成此任务,那就太好了。

背景

有一些方法可以转储数据库并通过执行转储程序生成的 sql 来导入它。

但我想做的是执行copy schema abc to abc_bk之类的命令,然后完成。

因为我必须通过 phpmyadmin 来完成,并且转储所有字段并重新导入它们太费时了。

【问题讨论】:

    标签: mysql duplicates schema


    【解决方案1】:

    有一个说法:

    CREATE TABLE <name> LIKE <othername>;
    

    但您必须一次处理一张桌子。没有一条语句可以对架构中的所有表执行此操作。

    您可以从 INFORMATION_SCHEMA.TABLES 中获取表列表:

    SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = <old-schema>;
    

    然后对于该查询返回的每个表,运行以下语句:

    CREATE TABLE <new-schema>.<table-name> LIKE <old-schema>.<table-name>;
    

    您必须编写一些代码来执行循环来执行此操作。


    你的评论:

    如果你也想复制数据,可以使用INSERT ... SELECT

    INSERT INTO <new-schema>.<table-name> 
     SELECT * FROM <old-schema>.<table-name>;
    

    这需要一段时间,与表中需要更新的行数和索引数成正比(即写入每行的成本乘以索引数)。

    请注意,当 INSERT...SELECT 运行时,它会锁定它从旧表中读取的行。如果您需要在此过程中继续写入旧表,我建议您使用pt-archiverpt-table-sync 进行复制。

    【讨论】:

    • 谢谢你先回答。但我发现这只会复制表结构而不是数据。
    • 没错。当您说复制模式时,我认为这是指元数据,而不是数据。有关复制数据的提示,请参阅上述更新。
    • 谢谢,您推荐的工具看起来很棒。稍后再试。
    【解决方案2】:

    就我而言,我想在现有数据库的基础上创建一个全新的数据库,用于我的集成测试。它基本上是上面比尔卡尔文答案的充实版本。

    请注意,我的解决方案不会复制数据。如果您需要该功能,添加到脚本中应该不会太难。

    您可以参考GitHub Gist here

    这里是 MySQL 代码供快速参考:

    -- this procedure needs to be run somewhere, so just select a database
    USE `existing_db`;
    
    DELIMITER $$
    
    DROP PROCEDURE IF EXISTS `exec`$$
    DROP PROCEDURE IF EXISTS `copy_schema`$$
    
    -- simple procedure to allow statement strings to be built and executed easily
    -- using `concat`
    CREATE PROCEDURE exec(stmt_text TEXT)
    BEGIN
      SET @sql_text = stmt_text;
      PREPARE stmt FROM @sql_text;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;
    END $$
    
    -- Copies the database `from_db` into a new database, `to_db`.
    -- Be careful: This procedure DROPs `to_db` before copying data
    CREATE PROCEDURE copy_schema(from_db VARCHAR(64), to_db VARCHAR(64))
    BEGIN
      -- declare variables to be used throughout the procedure
      DECLARE curr_table_name VARCHAR(64) DEFAULT NULL;
      DECLARE done TINYINT DEFAULT FALSE;
      -- This is a cursor that will point to every row in
      -- INFORMATION_SCHEMA.TABLES
      -- Each row corresponds to a table in `from_db`, so this will effectively
      -- give us a foreach loop through the table names
      DECLARE table_cursor
        CURSOR FOR
        SELECT TABLE_NAME
          FROM INFORMATION_SCHEMA.TABLES
            WHERE TABLE_SCHEMA = from_db;
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
      -- initialize `to_db` before attempting to copy data into it
      CALL exec(concat('DROP DATABASE IF EXISTS ', to_db));
      CALL exec(concat('CREATE DATABASE ', to_db));
    
      OPEN table_cursor;
    
      -- Loop through all table names
      table_loop:
      LOOP
        FETCH NEXT FROM table_cursor INTO curr_table_name;
        -- Break if no more results
        IF done THEN
          LEAVE table_loop;
        ELSE
          -- Call `CREATE TABLE` for each table, copying the schema from `from_db`
          CALL exec(concat('CREATE TABLE ', to_db, '.', curr_table_name, ' LIKE ', from_db, '.', curr_table_name));
        END IF;
      END LOOP;
    
      CLOSE table_cursor;
    END $$
    
    DELIMITER ;
    
    -- EXAMPLE USAGE:
    CALL copy_schema('existing_db', 'existing_db_copy');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-21
      • 2011-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多