50

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

4

8 回答 8

148

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”的过程。

于 2014-10-15T09:53:08.563 回答
12

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

bash > mysql -D your_database < your_sql_dump.sql

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

如果您有权访问转储所来自的服务器,那么您可以使用mysqldump --ignore-table=database.table_you_dont_want1 --ignore-table=database.table_you_dont_want2 ....


查看此答案以获取跳过导入某些表的解决方法

于 2013-05-24T12:53:16.790 回答
12

对于任何使用 .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 editcompressed .gz text file

于 2018-08-23T08:06:33.613 回答
2

除非您在转储期间忽略了表,否则您必须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

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

于 2019-07-11T11:34:11.620 回答
2

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

我喜欢@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 脚本,而是将其直接通过管道传输到数据库
,它确实创建了表,只是不导入数据(这是我在使用巨大的日志表时遇到的问题)

于 2018-10-26T12:23:40.057 回答
1

如果需要,您可以一次执行一张表:

mysqldump -p sourceDatabase tableName > tableName.sql
mysql -p -D targetDatabase < tableName.sql
于 2013-07-26T02:13:45.380 回答
1

这是我从 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 ;; 和分隔符;

于 2018-05-30T14:11:09.143 回答
0

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

然后 mysql -f < reduce.sql

于 2018-09-08T03:48:46.510 回答