【问题标题】:MySQL import database but ignore specific tableMySQL导入数据库但忽略特定表
【发布时间】:2013-05-20 01:51:02
【问题描述】:

我有一个包含一个数据库和大约 150 个表的大型 SQL 文件。我想使用mysqlimport 导入该数据库,但是,我希望导入过程忽略或跳过几个表。导入所有表但忽略其中一些表的正确语法是什么?谢谢。

【问题讨论】:

  • 我不知道这是否可能。您可以创建 .sql 的备份,在文本中找到它们并破坏它们吗?或者这是您将一次又一次地做的事情。您可以使用 CTRL-H 查找并用 REM stmt 替换,或者最后运行一点“从 table1 中删除;” “从 table2 中删除”排序脚本
  • 有很多需要省略的吗?它们是如何识别的?也许考虑导入整个东西,然后在你不想保留的那些上运行一个删除表。
  • 我认为可能是SQL文件中的一张表有问题,所以我的导入过程没有完成。您知道从命令行使用导入过程与从 ​​MySQL Workbench 使用导入实用程序是否不同吗?

标签: mysql mysqldump mysqlimport


【解决方案1】:

mysqlimport 不是导入 SQL 语句的正确工具。此工具旨在导入格式化的文本文件,例如 CSV。您想要做的是使用如下命令将您的 sql 转储直接提供给 mysql 客户端:

bash > mysql -D your_database < your_sql_dump.sql

mysqlmysqlimport 都不提供您需要的功能。您最好的机会是导入整个转储,然后删除您不想要的表。

如果您可以访问转储所来自的服务器,那么您可以使用mysqldump --ignore-table=database.table_you_dont_want1 --ignore-table=database.table_you_dont_want2 ... 创建一个新的转储。


Check out this answer for a workaround to skip importing some table

【讨论】:

  • 感谢您的评论。我的问题似乎是,当我在 MySQL Workbench 中使用 import 命令时,这个过程有效,但只导入了大约三分之一的表,然后挂在特定的表上。由于问题表,我无法导入所有表。
  • 尝试直接从命令行导入您的转储。你遇到同样的问题吗?至少您可能会看到一些错误消息。
【解决方案2】:

如果需要,您可以一次做一张桌子:

mysqldump -p sourceDatabase tableName > tableName.sql
mysql -p -D targetDatabase < tableName.sql

【讨论】:

    【解决方案3】:

    RandomSeed 接受的答案可能需要很长时间!导入表(只是为了稍后删除)可能会非常浪费,具体取决于大小。

    对于使用创建的文件

    mysqldump -u user -ppasswd --opt --routines DBname > DBdump.sql
    

    我目前得到一个大约 7GB 的文件,其中 6GB 是我不需要的日志表的数据;重新加载此文件需要几个小时。如果我需要重新加载(出于开发目的,或者如果需要实时恢复),我会浏览该文件:

    sed '/INSERT INTO `TABLE_TO_SKIP`/d' DBdump.sql > reduced.sql
    

    然后重新加载:

    mysql -u user -ppasswd DBname < reduced.sql
    

    这为我提供了一个完整的数据库,其中创建了“不需要的”表但为空。如果您真的根本不需要这些表,只需在加载完成后删除空表即可。

    对于多个表,您可以这样做:

    sed '/INSERT INTO `TABLE1_TO_SKIP`/d' DBdump.sql | \
    sed '/INSERT INTO `TABLE2_TO_SKIP`/d' | \
    sed '/INSERT INTO `TABLE3_TO_SKIP`/d' > reduced.sql
    

    有一个“陷阱” - 注意转储中可能包含“INSERT INTO TABLE_TO_SKIP”的过程。

    【讨论】:

    • 这真是天才,从 1 小时缩短到 30 秒。
    • 哇!太棒了,我刚刚将备份从 1GB 减少到 72MB,为我节省了很多时间,谢谢
    • 考虑sed -r 选项和正则表达式,以防您想一次性消除更多表格,例如:sed -r '/INSERT INTO `(TABLE1_TO_SKIP|TABLE2_TO_SKIP)`/d' DBdump.sql &gt; reduced.sql
    • just FLY: TABLE_TO_SKIP 区分大小写,通常是 table_to_skip :)
    • for windows 查找“sed for windows” - 现在可以在这里找到:gnuwin32.sourceforge.net/packages/sed.htm - 并在命令中使用双引号而不是单引号
    【解决方案4】:

    这是我从 mysql 转储中排除一些表的脚本 我在需要保留订单和付款数据时使用它来恢复数据库

    exclude_tables_from_dump.sh

    #!/bin/bash
    
    if [ ! -f "$1" ];
    then
        echo "Usage: $0 mysql_dump.sql"
        exit
    fi
    
    declare -a TABLES=(
    user
    order
    order_product
    order_status
    payments
    )
    
    CMD="cat $1"
    for TBL in "${TABLES[@]}";do
        CMD+="|sed 's/DROP TABLE IF EXISTS \`${TBL}\`/# DROP TABLE IF EXIST \`${TBL}\`/g'"
        CMD+="|sed 's/CREATE TABLE \`${TBL}\`/CREATE TABLE IF NOT EXISTS \`${TBL}\`/g'"
        CMD+="|sed -r '/INSERT INTO \`${TBL}\`/d'"
        CMD+="|sed '/DELIMITER\ \;\;/,/DELIMITER\ \;/d'"
    done
    
    eval $CMD
    

    它避免了表的 DROP 和 reCREATE 以及向该表中插入数据。 它还剥离了存储在 DELIMITER 之间的所有 FUNCTIONS 和 PROCEDURES ;;和分隔符;

    【讨论】:

      【解决方案5】:

      适用于使用 .sql.gz 文件的任何人;我发现以下解决方案非常有用。我们的数据库超过 25GB,我不得不删除日志表。

      gzip -cd "./mydb.sql.gz" | sed -r '/INSERT INTO `(log_table_1|log_table_2|log_table_3|log_table_4)`/d' | gzip > "./mydb2.sql.gz"
      

      感谢 Don 的回答和 Xosofox 的评论以及相关帖子: Use zcat and sed or awk to edit compressed .gz text file

      【讨论】:

      • 谢谢。这太棒了!
      【解决方案6】:

      我不会在生产中使用它,但如果我必须快速导入一些备份,其中包含许多较小的表和一个可能需要数小时才能导入的大型怪物表,我很可能会“grep -v Wanted_table_name original.sql > 减少.sql

      然后是mysql -f

      【讨论】:

      • 您可能需要注意以下情况:您的不需要的表名称为“SALES”,但您有另一个名为“BIGSALES”的表,或者可能有一个名为“another_table_SALES_fk”的外键字段。你的回答可能会导致一个痛苦的世界。另外,如果您打算走这条路,那么 fgrep 肯定会比 grep 快得多吗?
      【解决方案7】:

      有点旧,但认为它可能仍然派上用场......

      我喜欢@Don 的回答 (https://stackoverflow.com/a/26379517/1446005),但发现您必须先写入另一个文件非常烦人...
      在我的特殊情况下,这将花费太多时间和磁盘空间

      所以我写了一个小 bash 脚本:

      #!/bin/bash
      
      tables=(table1_to_skip table2_to_skip ... tableN_to_skip)
      
      
      tableString=$(printf "|%s" "${tables[@]}")
      trimmed=${tableString:1}
      grepExp="INSERT INTO \`($trimmed)\`"
      
      zcat $1 | grep -vE "$grepExp" | mysql -uroot -p
      

      这不会生成新的 sql 脚本,而是将其直接通过管道传输到数据库
      此外,它确实创建了表,只是不导入数据(这是我在使用巨大的日志表时遇到的问题)

      【讨论】:

        【解决方案8】:

        除非您在使用mysqldump --ignore-table=database.unwanted_table 转储期间忽略了这些表,否则您必须使用一些脚本或工具来过滤掉您不想从转储文件中导入的数据,然后再将其传递给mysql 客户端。

        这是一个 bash/sh 函数,它可以动态(通过管道)从 SQL 转储中排除不需要的表:

        # Accepts one argument, the list of tables to exclude (case-insensitive).
        # Eg. filt_exclude '%session% action_log %_cache'
        filt_exclude() {
            local excl_tns;
            if [ -n "$1" ]; then
                # trim & replace /[,;\s]+/ with '|' & replace '%' with '[^`]*'
                excl_tns=$(echo "$1" | sed -r 's/^[[:space:]]*//g; s/[[:space:]]*$//g; s/[[:space:]]+/|/g; s/[,;]+/|/g; s/%/[^\`]\*/g');
        
                grep -viE "(^INSERT INTO \`($excl_tns)\`)|(^DROP TABLE (IF EXISTS )?\`($excl_tns)\`)|^LOCK TABLES \`($excl_tns)\` WRITE" | \
                sed 's/^CREATE TABLE `/CREATE TABLE IF NOT EXISTS `/g'        
            else
                cat
            fi
        }
        

        假设你有一个像这样创建的转储:

        MYSQL_PWD="my-pass" mysqldump -u user --hex-blob db_name | \
        pigz -9 > dump.sql.gz
        

        并且想在导入前排除一些不需要的表:

        pigz -dckq dump.sql.gz | \
        filt_exclude '%session% action_log %_cache' | \
        MYSQL_PWD="my-pass" mysql -u user db_name
        

        或者您可以在导入数据库之前通过管道导入文件或任何其他工具。

        【讨论】:

          猜你喜欢
          • 2015-03-14
          • 1970-01-01
          • 2011-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-09
          • 2023-03-24
          • 1970-01-01
          相关资源
          最近更新 更多