【发布时间】:2009-06-25 16:27:03
【问题描述】:
我正在尝试插入一个新行,但如果键已经存在,我只想在表中的某个其他值不同时更新该行。这可能在 mysql 查询/语句中吗?
我的表格由以下列组成:hat、mittens、name、last_update
帽子+手套构成唯一索引(比如“帽子”和“手套”的值是颜色)
假设这已经在表格中:
1. 帽子=蓝色手套=绿色名称=乔治 last_update=星期二 2. hat=red mittens=green name=bill last_update=monday在一个新键上,我想像往常一样插入。在重复键上,我只想在名称更改时进行更新,否则忽略。这样做的原因是我想保留 last_update 值(时间戳)。
hat=yellow mittens=purple name=jimmy -- 插入新行 帽子=蓝色手套=绿色名称=乔治-忽略 hat=blue mittens=green name=betty -- 更新行如果不使用单独的语句首先查找现有行、比较值然后在必要时发出更新,这是否可行?如果是这样,语法是什么?
感谢您的回复。我都试过了。事实上,只使用一个简单的 UPDATE 语句,如
update tbl set name='george' where hat='blue' and mittens='green'
导致没有行被更新。但是,使用任一
INSERT INTO tbl (hat,mittens,name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name='george';
或
INSERT INTO tbl (hat, mittens, name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name=CASE WHEN name <> VALUES(name) THEN VALUES(name) ELSE name END;
不知何故导致行被更新(并且时间戳改变)。
FWIW,这是我正在使用的表:
CREATE TABLE `tbl` (
`hat` varchar(11) default NULL,
`mittens` varchar(11) default NULL,
`name` varchar(11) default NULL,
`stamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
UNIQUE KEY `clothes` (`hat`,`mittens`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
MySQL 是 4.1.22 版(也许这很重要?) 再次感谢所有回复。
【问题讨论】:
-
我猜是你的 MySQL 版本是这里的问题。在对 4.1 分支的积极支持结束(2006 年 12 月 31 日)之后,看起来他们使用 INSERT ... ON DUPLICATE KEY UPDATE 在 5.0 分支中修复了一个错误(bugs.mysql.com/bug.php?id=28904)。我在我的机器上重新创建了你的表和测试用例,它按预期工作,我正在运行 MySQL Server 5.0.67。如果您无法更新 MySQL 安装,那么您可能会因为没有“单一查询”解决方案而陷入困境。
-
确认。两种解决方案都适用于 5.0.45(不幸的是,这只是一个开发服务器)。再次感谢!
-
您尝试了我建议的两个查询中的第二个吗?手动控制标记(last_update)列发生了什么的那个?我相信即使存在该错误也应该可以工作,因为它明确决定是否使用另一个案例语句更新列。
-
我有时间安装 4.1.22 版,以下单个语句按预期工作,除非名称更改,否则不会更新戳列:mysql> INSERT INTO tbl (hat,mittens,name) VALUES ('blue','green','george') ON DUPLICATE KEY UPDATE name = CASE WHEN name VALUES(name) THEN VALUES(name) ELSE name END, stamp = CASE WHEN name VALUES(name) THEN now() ELSE 戳 END;请参阅我的答案以获取验证行为的测试用例日志。