2011-10-09 47 views
15

我使用MySQL GUI通过选择某些表并将从备份转储生成的INSERT语句运行到空表(新模式)中,将某些站点迁移到新版本的CMS。有在不新一个存在的旧表数列,所以脚本这样的错误停止:在“字段列表”有没有办法忽略INSERT上不存在的列?

1个未知列“USER_ID”:

脚本行

樱桃挑选所需的列导出,或编辑转储文件将是太繁琐和耗时。要解决这个问题,我会在生成错误时创建未使用的列,通过运行查询导入数据,然后在完成该表时删除未使用的列。我看过INSERT IGNORE,但这似乎是忽略重复键(不是我要找的)。

有什么办法可以在忽略目标表中不存在的列的同时执行INSERT?我正在寻找“无痛”的东西,就像现有的一些SQL功能一样。

为了澄清,我正在处理一堆备份文件,并将数据导入本地数据库进行测试,然后再将其移至活动服务器。该种方案的例子中,我希望:

-- Don't try to insert data from columns that don't exist in "new_table" 
INSERT INTO `new_table` {IGNORE UNKNOWN COLUMNS} (`id`, `col1`, `col2`) VALUES 
    (1, '', ''), 
    (2, '', ''); 

如果这样的事情是不存在的,我很乐意接受,作为一个答案,并继续使用我目前的解决方法。

+1

如果字段列表提到不存在的列,它可能包含偶然匹配的列。无论你知道什么,它可能是表名是错误的,使你无意中在无效的表中插入无效的数据。这是一个非常糟糕的主意。如果插入错误,让它失败。 – GolezTrol

+0

如果使用不当或“意外”,有很多危险的查询是危险的,我不明白为什么这会是任何异常。 –

+0

当然,但查询中不存在的列表示直接错误,并且会失败。 INSERT也不例外。 SELECT查询也会失败。 – GolezTrol

回答

5

你目前的技术似乎够实用。只是一个小小的改变。

与其等待错误然后逐个创建列,您可以导出模式,做一个比较并找出所有表中所有缺失的列。

这样做会少一些工作。

您的gui将能够导出刚才的模式或mysqldump上的以下开关将有助于找出所有缺少的列。

mysqldump --no-data -uuser -ppassword --database dbname1 > dbdump1.sql 
mysqldump --no-data -uuser -ppassword --database dbname2 > dbdump2.sql 

通过对dbdump1.sql和dbdump2.sql进行区分可以使您在两个数据库中都有所区别。

+0

好的补充,在从一个数据库模式迁移到另一个数据库模式时非常有用。 +50。 – Kaivosukeltaja

3

你可以写一个存储功能类似:

sf_getcolumns(table_name varchar(100)) 

返回字符串指含有的申请表是这样的: 'field_1,field_2,field_3,......'

然后创建一个存储过程

sp_migrite (IN src_db varchar(50), IN target_db varchar(50)) 
运行trugh表和每个表获取申请表,然后

创建像

字符串
cmd = 'insert into ' || <target_db><table_name> '(' || <fileds_list> || ') SELECT' || <fileds_list> || ' FROM ' <src_db><table_name> 

然后执行字符串中的每个表

+1

我不得不承认,我不确定这意味着什么 - 但它看起来比它的价值更麻烦?我想我希望能找到一个关键字,或者我可以添加到现有的'INSERT'脚本中,以便忽略未知列,因为我已经有了自己的解决方法。我会看看如果我能理解这一点,并给它一个镜头,谢谢。我正在使用现有的备份文件,所以不太确定这是我所追求的。 –

+0

我看到这有一个投票,所以我认为这不是一个坏的解决方案(即使我有限的SQL技能不能理解它)。我是否应该从这个答案中假设我所特别寻找的*不存在? –

+2

@WesleyMurch - 是的。这真是一个** TERRIBLE **的想法,让你的引擎处理场失准。它表明你不知道你在插入什么,这是一个主要问题。 – JNK

0

dbForge Studio for MySQL会给你一个机会,compare and synchronize数据的两个数据库之间。

默认情况下,仅对名称相同的对象执行数据比较;您可以使用自动映射或手动映射数据库对象。 dbForge Studio允许您自定义表和列的映射,以便您可以比较具有不同名称,所有者和结构的对象的数据。您也可以映射不同类型的列,但这可能会导致数据截断,舍入以及某些类型同步期间的错误。

0

发现你的问题有趣。

我知道有一种方法可以从MySQL中的表中选择列名;它是show columns from tablename。我忘记了所有的MySQL表数据都保存在一个特殊的数据库中,名为“information_schema”。

这是逻辑的解决方案,但它不工作:

mysql> insert into NEW_TABLE (select column_name from information_schema.columns where table_name='NEW_TABLE') values ... 

我会继续关注,虽然。如果可以从select column_name查询中获取以逗号分隔的值,则可能正在进行业务。

编辑:

可以使用select ... from ... into命令生成一个行CSV,如下所示:

mysql> select column_name from information_schema.columns where table_name='NEW_TABLE' into outfile 'my_file' fields terminated by '' lines terminated by ', ' 

我不知道如何得到这个输出到MySQL CLI标准输出,但。

1

有什么办法来执行INSERT,而忽略目标表中不存在的列?我正在寻找“无痛”的东西,就像现有的一些SQL功能一样。

不,没有“无痛”的方式来这样做。

相反,您必须显式处理那些最终表中不存在的列。例如,您必须将它们从输入流中移除,在事实之后放弃它们,玩弄肮脏的技巧(engine=BLACKHOLE +触发器,以仅插入您想要的真实目标架构的内容),无论如何。

现在,这不一定需要是手册 - 有工具(如Devart noted)以及查询db目录以确定列名称的方法。但是,它不像简单地注释INSERT语句那么简单。

也许CMS供应商可以提供合理的迁移脚本?

+0

感谢您的直接回答,不幸的是我是CMS供应商:)我有一个最新版本的迁移系统,但试图从一个更旧的版本快速启动更新。 –

0

我仔细阅读所有这些帖子,因为我有同样的挑战。请检查我的解决方案:

我在c#中做了它,但您可以使用任何语言。

检查列名的插入语句。如果你的实际表中缺少任何东西,请将它们添加为TEXT列,因为TEXT可以吃任何东西。

当完成插入该表时,删除添加的列。

完成。

相关问题