MYSQL ON DUPLICATE KEY UPDATE问题

时间:2011-07-22 05:50:46

标签: php mysql sql

我对ON DUPLICATE KEY UPDATE的作用有点困惑。我正在寻找的东西将检查INSERT INTO SQL命令,如果任何行是重复的,则不更新该行。现在,如果该行中的任何内容不重复(但有些内容),我想用更新的信息替换该行。

这是否可以使用基本的MYSQL,或者我将首先必须提取所有数据,然后交叉检查它。我宁愿不这样做,因为我所要做的就是每天缓存一次相当数量的数据。

"INSERT INTO years (date,year,venue,city,state,country,showid) VALUES (?,?,?,?,?,?,?)"

5 个答案:

答案 0 :(得分:3)

ON DUPLICATE KEY UPDATE只是在重复键的情况下执行您提供给它的SET语句。它不会比较单个列值,只会更新不同的列值。只要您具有定义为UNIQUE KEYPRIMARY KEY的正确列,它听起来就像您想要做的那样。

但是,我通常做的是运行插入,然后捕获错误并在需要时执行不同的操作。如果存在重复,这会产生2个查询的缺点,但在我看来,它更易于维护。

示例:

$db = new PDO($dsn, $user, $pass);
$stmt = $db->prepare('INSERT INTO some_tbl (col1,col2,col3) VALUES (?,?,?)');
$values = array('Col 1 value','Col 2 Value', 'Col 3 Value');
try {
  $db->execute($values);
} catch (PDOException $e) {
  if($e->getCode() == 23000){
    // dupe key do some other action whether update or otherwise
  } else {
    // rethrow non dupe errors
    throw $e;
  }
}

答案 1 :(得分:1)

正如一些人已经建议的那样,您需要做的第一件事就是定义什么是重复行。这是通过设置UNIQUE索引来完成的。例如,如果您认为表中没有重复的场地,则应在场地上设置UNIQUE索引。如果它是场地和日期的组合(基本上是说 - 你不能在同一个日期在同一个地方有两个事件),那么你将定义一个复合的UNIQUE索引,它看起来像UNIQUE(场地,日期)。

当你有这样的设置。您可以开始使用ON DUPLICATE KEY UPDATE:如果您输入的数据将与现有的复合唯一键匹配 - 您将只更新相关列。如果没有 - 您将添加一个新的。该语句的语法是:

INSERT INTO table (col1, col2, col3) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE SET col3 = VALUE(col3);

如果没有像之前那样的唯一键,这将插入一个新行(假设唯一键是UNIQUE(col1,col2) - 所以之前没有col1和col2对)。如果表中存在一对col1和col2,它将用您提供的值替换col3值。

现在,谈到您的示例,看起来您需要在所有列上使用复合UNIQUE索引。我不是专家,但对我而言,这看起来不是最好的做法:)

因此,我建议稍微重新考虑一下你的表结构:

  • 有一个场地桌,栏目类似“州,城市,场地,场地_id”。这个表可以有一个独特的索引(州,地点,城市)。
  • 有一个“主”表,其中包含“show_id,artist_id,venue_id,time ..”等列。然后该表将具有复合UNIQUE索引(show_id,venue_id)。
  • 有一个艺术家表,其中的列类似于“artist_id,artist_name等*”。
  • 所有三个表在相应的ID上都有PRIMARY键(基本上是UNIQUE和INDEX键):show_id,venue_id,artist_id。

答案 2 :(得分:0)

您可以在数据的每一列上创建UNIQUE INDEX。如果新行的所有列都与现有行中的所有列完全相同,那么这将使得它会抛出重复的错误,这就是你想要的。

ALTER TABLE TABLE ADD UNIQUE uniqueconstraintname(col1,col2,...);

W3Schools on Unique Constraints:http://www.w3schools.com/sql/sql_unique.asp

答案 3 :(得分:0)

来自the official docs

  

如果指定ON DUPLICATE KEY UPDATE,则插入一行   会导致UNIQUE索引或PRIMARY KEY中的重复值   执行旧行的更新。   例如,如果列a声明为UNIQUE并包含该值   1,以下两个陈述具有相同的效果:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;
  

UPDATE表SET c = c + 1 WHERE a = 1;

答案 4 :(得分:0)

之前我误解了你的问题,我编辑了这篇文章

当你尝试做两件不同的事情时,你必须将它分成INSERT语句和UPDATE语句。并且要使UPDATE语句起作用,您至少需要一个键,然后检查该行以查看是否有任何值。

您可以检查行的存在,只有在它不存在时才插入。

INSERT声明

INSERT INTO tbl_name (key, col1, col2, col3) 
SELECT keyval, val1, val2, val3 
FROM dual
WHERE NOT EXISTS
(SELECT key, col1, col2, col3 
FROM tbl_name 
WHERE key = keyval AND col1 = val1 AND col2 = val2 AND col3 = val2)

dual只是一个占位符表,允许您插入所需的值并允许WHERE子句

更新声明

UPDATE tbl_name
SET col1 = val1
    col2 = val2
    col3 = val3
WHERE key = keyval AND 
(col1 <> val1 OR col2 <> val2 OR col3 <> val3)