2012-01-30 85 views
1

我已经提出这个问题Grouping and update large database table,但我没有得到答案。关于重复密钥更新的SQL更新

我有一个表:name, date, detail, noname, date, detail一起作为PK。

不知怎的,我需要更新detail,并有可能有重复的密钥。因此我需要对no进行求和以得到重复的行。 ON DUPLICATE KEY UPDATE仅用于INSERT。那么如何解决这个问题呢?

+0

你能澄清吗?我假设有两行'name = A,date = B,detail = C,no = 23'和'name = A,date = B,detail = D,no = 45' - 并且你想让它变成所以如果你将第二行的细节更新为C,那么这两行总和为单行'name = A,date = B,detail = C,no = 68'?但是只有在'name'和'date'字段也匹配的情况下呢? – 2012-01-30 23:11:52

+0

没错。它实际上是合并这些行。 – DrXCheng 2012-01-30 23:19:40

+0

从你的其他问题,虽然我猜这不是'只是'两行...你打算改变*所有*细节领域更简单(你不需要使用LIKE)和那么所有的合并都会发生? – 2012-01-30 23:21:05

回答

0

糟糕的设计。你应该使用代理id主键,并使这些字段成为一个复合唯一索引。如果你以后想引用这个表,你会得到什么? 3个额外的字段作为另一个表中的外键和额外的大索引。你将如何更新细节领域?如果你在它是一个大表之前说过它,这意味着PK索引重建。如果可能的话禁用约束,如果它没有被引用。从源表中选择不同或分组,并使用此选择进行更新。第一

REPLACE INTO table(name,date,detail) 
    select distinct name,date,(select distinict detail from table) from 
    table 
+0

PK不会经常更新。我只想做一次性更新。 – DrXCheng 2012-01-30 23:12:31

+0

好的,你可以使用REPLACE。 http://dev.mysql.com/doc/refman/5.0/en/replace.html – 2012-01-30 23:17:31

+0

谢谢。你能举一个这个案例的简单例子吗? – DrXCheng 2012-01-30 23:23:31

1

第一件事,是多列主键可能是一个坏主意;:


更换EDIT正如你发现的那样,这使得操纵单个字段变得很困难。你应该做的是在该表中添加一个自动增量bigint列,该列将成为你的新主键,而你的三列唯一性约束可以是一个唯一的索引。它应该表现得更好......但它也可以让你做你需要的那种操作。它会让你执行修改,但仍然可以让你通过整数索引来识别原始行。

如果你这样做,只要你不介意创建一些临时表来处理,你的“一次性更新”现在可以安全地完成。事情是这样的:

创建几个具有相同的架构临时表,但没有独特三列索引 - 你可以有一个非唯一索引,因为它会帮助你了解查询去表演;

将需要处理的记录复制到第一个表中(包括唯一的整数主键);

更新您需要在临时表中更新的所有detail列;

使用INSERT ... SELECTSUMGROUP BY将这些记录合并到第二个表中;

INSERT INTO temp2 (...whatever...) SELECT ...whatever..., SUM(no) FROM temp1 GROUP BY ...whatever... 

最后,从原始表(使用整数主键)删除temp1目录表的所有记录,并插入在TEMP2表中的记录到原始表。

+1

多列主键不是一个坏主意,你为什么这么认为。 – 2012-01-31 01:08:38

+0

@ypercube我曾经喜欢在商业模式中使用任何“自然而然”独特的东西作为主键的想法;无论是字符串,还是多列的组合。它似乎比仅仅因为添加数字PK更有意义。但是当你必须做出不可避免的改变时,它就会变得脆弱,就像OP现在正在做的那样。 – 2012-01-31 01:25:03

+0

OP的问题是因为他有多个具有相同的此键值(我们假设他希望它是唯一的或主要的)的行。一个简单的“GROUP BY”将收集数据。 (将这些数据放在同一个表中,并删除多行可能会非常棘手,是的。)我看不出代理键如何帮助。 – 2012-01-31 01:29:05