2011-07-22 106 views
1

我对ON DUPLICATE KEY UPDATE的功能有点困惑。我正在查找的内容是将检查INSERT INTO SQL命令,如果有任何行是重复的,请不要更新该行。现在,如果该行中的任何内容不是重复的(但有一些是),我想用更新后的信息替换该行。MYSQL ON DUPLICATE KEY UPDATE问题

这是可能的使用基本的MYSQL,或者我将不得不先拉出所有的数据,然后交叉检查它。我宁愿不这样做,因为我所要做的就是每天缓存大量数据。

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

回答

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; 
    } 
} 
0

您可以创建您的数据的每一列的唯一索引。如果新行的所有列都是现有行中所有列的完全相同的副本,则这将使其发生重复错误,这正是您想要的。

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

W3Schools的上唯一约束:http://www.w3schools.com/sql/sql_unique.asp

+0

你能否提供更多的见解?另外我如何捕捉错误?我将我的列添加到原始帖子。 – switz

+0

编辑: 如果你这样设置你的表,然后用INSERT IGNORE INTO运行你的INSERT语句...那么你的问题就解决了。插入IGNORE将忽略重复值(不插入),因为它们错误并继续与其他插入。 –

0

the official docs

如果你指定ON DUPLICATE KEY UPDATE,并且插入一行是 会在唯一索引或主键导致重复值, 执行旧行的更新。 例如,如果列中的被声明为UNIQUE和包含值 1,下列两个语句具有相同的效果:

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

UPDATE表SET C = C + 1其中a = 1;

+0

这是什么意思'在独特的索引'。我知道主键是第一个值,但我想检查所有的值,而不仅仅是第一个值。 – switz

+0

主键不一定是第一个值......它定义为主键。我想你应该看看['CREATE'语句](http://dev.mysql.com/doc/refman/5.0/en/create-table.html)的手册,然后你可以比较'SHOW CREATE TABLE your_table_name'到那里,看看发生了什么。 – prodigitalson

0

我之前误解了你的问题,我编辑这个职位

你必须为你正在尝试做的2米不同的东西将其分离成一个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) 

双只是一个占位符表,让你插入你所希望的任何值,并允许一个WHERE子句

UPDATE语句

UPDATE tbl_name 
SET col1 = val1 
    col2 = val2 
    col3 = val3 
WHERE key = keyval AND 
(col1 <> val1 OR col2 <> val2 OR col3 <> val3) 
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。
相关问题