如何在MySQL转储中删除这些注释?

95

我正在尝试创建一个简单的数据库结构转储。使用mysqldump会给我一个结果,如下:

/*!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 */;

DROP TABLE IF EXISTS `foo`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
无论我尝试什么方法,这些注释看起来都消除不了。
我目前正在使用:mysqldump -p -d --add-drop-table --skip-tz-utc --skip-set-charset -h 127.0.0.1 -u foo bar --result-file=dumpfile.sql 编辑: 然而,我希望保留其他注释,例如-- MySQL dump 10.13 Distrib 5.1.41, for Win32 (ia32)

不是直接回答,但我已经完全放弃使用mysqldump,转用mk-parallel-dump - 它更快(生成多个进程),根据您将要对dump输出执行的操作而定,它更加灵活,因为它有效地封装了mysqldump和“select into outfile”语法。 - zznate
2
我想知道为什么Oracle没有将这些重要的选项添加到mysqdump中? - Handsome Nerd
15个回答

190

哇!尽管看起来像评论,但这些实际上不是评论,而是条件执行标记。

以这行代码为例:

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
如果MySQL版本为4.00.14或更高版本,则MySQL服务器将运行此语句。
这种神奇的注释语法在手册的注释语法部分有所记录。
您可能不想删除这些内容。

2
另一个问题是关于MySQL中的注释是否被视为可执行SQL的(由我发布的):http://stackoverflow.com/questions/25614919/where-is-it-documented-that-some-comments-in-a-sql-script-executed-by-mysql-usi - Dan Nissenbaum
1
有些情况下删除注释是有帮助的,例如:http://bugs.mysql.com/bug.php?id=48972 当--insert-ignore由于注释而无法按预期工作时。 - varela
+1 我从未知道这一点。我以为它们只是mysql dump在导出时运行的命令。非常有启发性的答案。 - Captain Hypertext
1
假设这意味着应该有期望的兼容选项,它们指定您是否希望在旧版mysql上运行sql,如果不是,则需要将其包装在条件注释中。 - CMCDragonkai

42

我知道这是一个老问题,但至少有一个答案。我也找不到mysqldump中删除条件注释的标志,或者设置最小mysql版本以使这些注释出现的更好选项。如果您只想摧毁它们所有,您可以使用grep或sed进行操作(sed会留下空行,grep则不会):

mysqldump ... | grep -v '^\/\*![0-9]\{5\}.*\/;$'
mysqldump ... | sed -e 's/^\/\*![0-9]\{5\}.*\/;$//g'
为了回答我自己的一个希望,即根据MySQL版本有条件地删除评论,可以使用以下其中之一(删除任何小于 MySQL5 的评论):
mysqldump ... | grep -v '^\/\*![0-4][0-9]\{4\}.*\/;$'
mysqldump ... | sed -e 's/^\/\*![0-4][0-9]\{4\}.*\/;$//g'

1
对于rsnapshot备份,去掉最后一行非常有用,这样一个没有更改的数据库就会产生相同的文件:mysqldump ... | grep -v '^-- Dump completed on .*$' - rubo77
是的,但问题在于您可能会丢失 DROP DATABASE IF EXISTSIGNORING YOUR CURRENT SESSION VARIABLES。除非您知道自己在做什么:不要删除它们,特别是在环境/主机之间迁移时。因为由此产生的输出可能不如预期,原因有很多。它们是为了保护您而放置的。但是,如果您不想系安全带,那就是您的选择。 - JayRizzo
2
@rubo77 您也可以使用这个mysql转储参数:--skip-dump-date - dehart

37

尝试使用 --skip-comments 参数?

谢谢

编辑:

我明白了,试试这个。

--skip-add-drop-table --skip-add-locks --skip-disable-keys --skip-set-charset

尝试移除一些选项直到达到所需的结果,基本上这与不带--skip-comments--compact相同。

--skip-comments会移除与版本和其他相关的注释..


6
很遗憾,这会把我想要的所有评论都移除掉,保留那些我不想要的评论。 - etheros
@etheros 我同意,但我们应该详细说明。我的用例涉及源控制的结构化数据。我不想为每个表格都有非必要的闲聊。我喜欢SET NAMES调用,正如在这个答案中建议的那样,--skip-set-charset会将其删除;它仅在转储文件开头发生一次,并且可能会对数据恢复产生实质性影响。对于我的用例,我确实喜欢--skip-add-locks --skip-disable-keys。但是一些条件注释,例如/*!40101 SET character_set_client = @saved_cs_client */;/*!40101 SET character_set_client = utf8 */... 有用还是无用? - Ben Johnson
1
@BenJohnson 不,它们不是。character_set_client由于某种错误或其他原因无法在5.6中设置,所以当你使用mysqldump导出utf8mb4数据时,会得到你不想要的条件注释。 - Slava

22

2
然而,这会禁用其他我想要的注释,比如 -- MySQL dump 10.13 Distrib 5.1.41, for Win32 (ia32) - etheros

13

从技术上讲,您试图摆脱的这些行不是注释。它们会在开头暂时修改一些变量,然后在结尾将它们重置为先前的值。

在您使用 --no-data 的情况下,它们并不是非常有用(但它们也是无害的),但我认为值得提到的是,这些行确实有一定的目的,并不只是注释。


4

那些不是注释,这部分脚本的执行取决于你的mysql版本。

您可以删除“注释部分”,例如

/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */

to

SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0

让脚本更易阅读。

如果您尝试在指定“注释”中的较新版本上运行“舒适”的脚本,您将会收到一个错误。


2
我们如何“删除注释部分”?这方面有转储选项吗?我不想手动处理几个G的文件。 - mpen
实际上应该是:如果您尝试在版本比“注释”中指定的版本旧的版本中运行一个“舒适”的脚本,您将会收到一个错误。 - Daniel

2

使用--dump-date=FALSE

完全满足OP的要求。(不完全,我看到了)

来源:mysqldump选项摘要

编辑:刚过了一分钟,我意识到这就是我所寻找的,而不是OP,但还是留在这里……希望有人能用它: 这个日期行会破坏源代码控制,因为它总是会变化……


1
正是我想要的,为什么会有人踩它?我给你点个大赞。 - kungfooman

2

保留有条件执行的注释非常重要。但是如果你确信将加载转储的MySQL版本大于或等于创建它的版本,则可以使用以下方法删除“注释”部分:

sed -r  s'#/\*![0-9]{5} ?([^*]*)\*/#\1#'g

它将转换诸如以下行:

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;

to

SET SQL_MODE=@OLD_SQL_MODE ;

因为这个语句必须在任何MySQL >= 4.1.1版本上运行。

请注意,这不会移除多行条件执行注释,例如在转储触发器时。

由于无法预测未来,最好将转储与注释一起存储,并且只在需要可视化时才删除它们。

mysqldump ... > dump.sql
cat dump.sql | sed -E  s'#/\*![0-9]{5} ?([^*]*)\*/#\1#'g > dump.no-comments.sql

1
如果您正在尝试将 structure.sql 文件包含在 git/github 中,并且需要剥离自动增量,请在 rake db:structure:dump 之后使用以下代码。
# Remove beginning auto increments to prevent merge conflicts
filename = 'db/structure.sql'
File.atomic_write(filename) do |output|
  File.open(filename, 'rb').each do |input|
    output.write(input.gsub(/\s+AUTO_INCREMENT=\d+\s+/, ' '))
  end
end

1
“strip the lines with a regexp”答案为什么会被踩这么多呢?它们都是完全有效的。特别是其中一个对我的情况非常适用。给你们所有人点赞。” - plainjimbo
不过比起使用 gsub,我们该如何确保本地数据库和协作者的数据库相同呢?这样你就不必再做这些工作了。 - Trip

0

既然你使用的是Windows系统,如果没有更好的解决方案,那么你可以使用Python脚本代替:

import re, sys
sql = sys.stdin.read()
regex = re.compile(r'/\*![^\n]* \*/;\n', re.M)
print regex.sub('', sql)

命令行使用方法:

python program.py < your.sql > output.sql

它会删除所有这样的行:

/*!....... */;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接