将INSERT语句自动转换为UPDATE的简单方法?

问题描述 投票:4回答:5

我想使用mysqldump的输出来更新实时数据库中的条目。我不想先删除条目,简单的更新语句都没问题。有没有一种简单的方法将包含INSERT语句的mysqldump的输出转换为相应的UPDATE语句?

它似乎是一个基本功能,所以我确信有人创建了一个工具或想出了一种方法来快速完成它,因此人们不必为每个人编写自己的脚本而一直重新发明轮子。

编辑:我正在寻找一个通用的解决方案,而不是我必须手动枚举实际的表列。这是一个普遍的问题,所以我认为应该有一个独立于表的解决方案。

mysql mysqldump
5个回答
4
投票

Mchl的答案是有效的另一个简单的解决方案是将'INSERT'更改为'REPLACE'。两者都需要简单的搜索/替换操作(我使用sed)。但是,如果这是定期运行,那么它将是复制/使用时间戳创建仅包含修改/新记录的加载器文件的良好候选者。

mysldump也有一个--replace选项,因此sed步骤可以省略。


8
投票

您可以将mysqldump数据还原到新的临时数据库,然后使用多表UPDATE语法进行更新。

UPDATE mydb.mytable AS dest JOIN tempdb.mytable AS origin USING (prim_key)
SET dest.col1 = origin.col1,
    dest.col2 = origin.col2,
    ...

然后删除临时数据库。


4
投票

这是添加ON DUPLICATE KEY UPDATE条款的问题

http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html


1
投票

我无法相信没有人创建一个简单的工具来将一组INSERT行转换为一组UPDATE命令。所以我做了我自己的一个。您可以在this fiddle中测试它,您可以在其中输入和输出文本框。

警告!这不是故障证明,有一堆假设。例如,如果您的值中包含逗号,则可能会失败。

我还假设第一个字段是唯一键。

function substrBetween(str,before,after){
    var arr = str.split(before);
    arr.shift();
    str = arr.join(before);
    arr = str.split(after);
    str = arr.shift();
    return str;
}

var insertQuery = $('#query').val();

var lines = insertQuery.split('\n');
var header = lines[0];
var tableName = substrBetween(header,"INTO `","`");
var varNames = substrBetween(header,"(`","`)").split("`, `");

var out = "";
for (i=1; i<lines.length; i++){
  var line = lines[i];
  if (line[line.length -1] == ";"){
    line = line.slice(0, -1) + ',';
  }
  var values = substrBetween(line,"(","),").split(", ");
  out += "UPDATE `"+tableName+"` SET ";
  for (j=1; j<values.length; j++){
    out += "`"+varNames[j]+"`="+values[j]+", ";
  }
  out = out.slice(0, out.length-2);
  out += " WHERE `"+varNames[0]+"`="+values[0]+";\n";
}
return out;

示例INPUT:

INSERT INTO `devices` (`name`, `idGroup1`, `idGroup2`, `label`) VALUES
('3703-001', 16, 5, 'Meter BB #1'),
('3703-002', 12, 8, 'Meter CC #2'),
('3703-003', 12, 0, 'Meter #3'),
('3703-004', 12, 24, 'Meter building F');

相应的输出:

UPDATE `devices` SET `idGroup1`=16, `idGroup2`=5, `label`='Meter BB #1' WHERE `name`='3703-001';
UPDATE `devices` SET `idGroup1`=12, `idGroup2`=8, `label`='Meter CC #2' WHERE `name`='3703-002';
UPDATE `devices` SET `idGroup1`=12, `idGroup2`=0, `label`='Meter #3' WHERE `name`='3703-003';
UPDATE `devices` SET `idGroup1`=12, `idGroup2`=24, `label`='Meter building F' WHERE `name`='3703-004';

0
投票

我也一直在寻找一个我认为是常见问题的解决方案,但一直找不到。看起来好像是在mysqldump中,但是基于MySQL板中的这个功能请求,它不是:

https://bugs.mysql.com/bug.php?id=73190

转录如下:

[3 Jul 2014 21:23] Christopher Schultz
Description:
mysqldump currently supports two different options for dealing with PK collisions:

  --insert-ignore (uses INSERT IGNORE)
  --replace       (uses REPLACE INTO instead of INSERT INTO)

I'd like to request an additional option that uses INSERT ... ON DUPLICATE KEY UPDATE ... when used.

This will allow one database to be used as a source to update another database without the following problems:

Using INSERT IGNORE will ignore any updates to existing rows that are coming from the file being loaded "on top of" an existing database.

Using REPLACE ends up churning the primary index, failing when foreign keys point to the record being updated (REPLACED), or ON DELETE CASCADE wiping-out records in other tables as the records in the target table are "updated" (using REPLACE).

There are two significant downsides to using ON DUPLICATE KEY UPDATE, of course:

1. The dump file will get much bigger, because the bulk-loading syntax for INSERT can no longer be used.
2. The dump file will get much longer, because ON DUPLICATE KEY UPDATE requires that all values be specified twice: once in the VALUES() section and then a second time in the field=value, field=value part after "ON DUPLICATE KEY UPDATE" phrase.

Bug 11422 [http://bugs.mysql.com/bug.php?id=11422] requests the ability to simply say "ON DUPLICATE KEY UPDATE" and allow the engine to use the VALUES to update all fields in the table. Fixing bug 11422 and using the solution here would mitigate both downsides because then extended syntax could (possibly?) be used and the values would not have to be mentioned twice in the dump file.

I have found many posts online about how to do something like this and the responses always steer the person toward --insert-ignore or --replace but there are many scenarios where the above request would be preferable.

How to repeat:
(This is a feature request)
[17 Jul 2015 14:23] Georgi Kodinov
Thank you for the reasonable feature request.
© www.soinside.com 2019 - 2024. All rights reserved.