【问题标题】:How to skip row when importing bad MySQL dump导入错误的 MySQL 转储时如何跳过行
【发布时间】:2011-11-29 03:38:18
【问题描述】:

鉴于错误的mysqldump 会导致导入错误:

namtar backups # mysql -p < 2010-12-01.sql
Enter password: 
ERROR 1062 (23000) at line 8020: Duplicate entry 'l�he?' for key 'wrd_txt'

有没有简单的方法告诉导入跳过给定的行并继续?

(是的,我知道我可以手动编辑文件或解析输出,但不是很方便)

【问题讨论】:

  • 我也遇到了这个问题,我创建了一个新数据库,然后将 .sql 文件中的数据导入到我新创建的数据库中。它对我有用。
  • 在我的例子中,触发器在导入时导致重复输入错误。

标签: mysql bash backup mysqldump mysql-error-1062


【解决方案1】:

如果您可以再次进行转储,您可以在转储时将--insert-ignore 添加到命令行。

或者你可以尝试使用带有--forcemysqlimport命令,即使遇到MySQL错误也会继续。

【讨论】:

  • 我无法再次创建导出...以及如何使用 mysqlimport 再次从 mysqldump --all-databases 输出?
  • 我刚刚尝试将 --force 与 mysql 一起使用,当错误发生时,它会导致插入停止。 mysqlimport 不适用于 --all-databases 转储,所以这也是不可能的。最简单的方法是编辑文件,而不是删除可能很乏味的违规行,而是将“INSERT”命令转换为“INSERT IGNORE”命令。一个简单的查找/替换就足够了。我意识到这不是一个理想的解决方案,但它比在发现它们时必须手动挖掘文件替换有问题的插入要好。
【解决方案2】:

mysql -f -p &lt; 2010-12-01.sql

-f(强制)是这里的操作选项,对我有用。

【讨论】:

  • 就我而言,我在 mysql 集群 5.5.29-7.2.10 中恢复了 .sql 文件,-f 也可以。它列出了所有的 ERROR 行,这也可以忽略错误,例如:ERROR 1528 (HY000) at line 22: Failed to create LOGFILE GROUP,并重用已经创建的 LOGFILE。
【解决方案3】:

只是想你是否删除了转储顶部的 MySQL 指令? (当我在删除我已经使用 sed 命令插入的所有记录/表后重新启动恢复时,我无意中这样做了)。这些指令告诉 MySQL,除其他外,不要进行唯一测试、外键测试等)

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

【讨论】:

    【解决方案4】:

    根据 jmlsteele 的回答和评论中的建议,以下是如何将插入内容即时转换为 INSERT IGNORE

    如果您从 sql 文件导入:

    sed -e "s/^INSERT INTO/INSERT IGNORE INTO/" < 2010-12-01.sql | mysql -p
    

    如果您从 gz 文件导入,只需将 gunzip 的输出通过管道传输到 sed,而不是使用文件输入:

    gunzip < 2010-12-01.sql.gz | sed -e "s/^INSERT INTO/INSERT IGNORE INTO/" | mysql -p
    

    【讨论】:

    • 这不会也替换文本字段中的“INSERT INTO”文本吗?
    • @Almad - 它只会更改第一个 INSERT INTO,并且不会更改同一行上的任何其他内容。据我所知,任何时候你在文本字段中有“INSERT INTO”,它都会遵循一个 INSERT INTO 语句——但是,我改变了答案以确保它只在它的开头被替换换行。
    • 每行转储可以有多个 INSERT 语句(甚至数千或更多):在这种情况下,解决方案不会影响第一个语句之后的其他语句。也许使用更复杂的正则表达式可以实现结果,只替换 INSERT INTO 而不是文本字段。
    【解决方案5】:

    其他选项当然是可行的选项,但另一种解决方案是简单地编辑从mysqldump 获得的.sql 文件。

    变化:

    INSERT INTO table_name ...
    

    INSERT IGNORE INTO table_name ...
    

    【讨论】:

    • @Almad 您链接的解决方案允许您进行我在导入时从命令行提出的相同更改,并且不修改 .sql 文件。我的建议是在导入之前实际打开文件,编辑其内容并保存文件。虽然相似,但我不认为这些是重复的答案。
    【解决方案6】:

    很棒的提示。我做了一些不同但结果相同的操作。

    perl -pi -e 's/INSERT INTO/INSERT IGNORE INTO/g' filename.sql
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-28
      • 2019-07-30
      • 1970-01-01
      • 2017-05-27
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      相关资源
      最近更新 更多