在MySQL中“更新”行的正确方法

时间:2012-02-27 21:56:09

标签: php mysql

这是我的数据库结构:

ID    NAME    SOMEVAL    API_ID
1     TEST    123456     A123
2     TEST2   223232     A123
3     TEST3   918922     A999
4     TEST4   118922     A999

我正在使用调用API并从外部服务获取一些数据的函数来填充它。

第一次运行,我想插入从API返回的所有数据。之后,每次运行该函数时,我只想更新当前行并添加行,以防我从API调用中获取它们并且不在数据库中。

因此,我对更新过程的初步想法是浏览我从API和SELECT获取的每一行,看看它是否已经存在。

我只是想知道这是否是最有效的方法,或者最好是DELETE来自数据库的相关行,然后重新插入它们。

注意:我从API获得的每批行都有一个API_ID,因此当我说delete行时,我的意思是DELETE FROM table WHERE API_ID = 'A999'

5 个答案:

答案 0 :(得分:0)

如果您从服务中检索所有行,我建议您删除所有索引,截断表,然后插入所有数据并重新创建索引。

如果从服务中检索一些数据,我将删除所有索引,删除所有相关行,插入所有行,然后重新创建所有索引。

答案 1 :(得分:0)

如果您从API返回的所有数据在删除后需要完全重建行,那么请继续删除它们,然后插入。

但是,请确保您在事务中执行此操作,并且您正在使用正确支持事务的引擎,例如InnoDB,以便数据库的其他客户端不会看到表中缺少的行它们将会更新。

为了提高效率,您应该在单个查询中插入尽可能多的行。这样快得多。

BEGIN;
DELETE FROM table WHERE API_ID = 'A987';
INSERT INTO table (NAME, SOMEVAL, API_ID) VALUES
    ('TEST5', 12345, 'A987'),
    ('TEST6', 23456, 'A987'),
    ('TEST7', 34567, 'A987'),
    ...
    ('TEST123', 123321, 'A987');
COMMIT;

答案 2 :(得分:0)

在这种情况下,我通常会选择:

  • 启动交易
  • 从外部来源获取行
  • 选择本地商店以检查它是否在那里
    • 如果它在那里:更新其值,记住列表中的本地行ID
    • 如果它不存在:插入它,记住列表中的本地行ID
  • 在最后删除所有不在记住的本地行id列表中的行(如果id的数量允许,则为NOT IN子句,或者如果可能存在许多已删除的行,则为其他方式)
  • 提交交易

为什么呢?因为通常我有其他表引用的本地行,并且删除它们都会破坏引用(更不用说deletete cascade)。

答案 3 :(得分:0)

我在执行SELECT时没有看到任何问题,然后在INSERTUPDATE之间做出决定。但是,MySQL能够执行所谓的“upserts”,如果它不存在则会插入一行,否则会更新现有行。

This SO answer显示了如何做到这一点。

答案 4 :(得分:0)

我建议使用INSERT...ON DUPLICATE KEY UPDATE

如果您使用INSERT IGNORE,则实际上不会插入该行,如果它导致API_ID上出现重复的密钥。

在API_ID列上添加unique key index