MySql 表插入,如果不存在,否则更新
Posted
技术标签:
【中文标题】MySql 表插入,如果不存在,否则更新【英文标题】:MySql Table Insert if not exist otherwise update 【发布时间】:2011-08-27 04:02:50 【问题描述】:UPDATE AggregatedData SET datenum="734152.979166667",
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";
如果datenum
存在,它可以工作,但如果datenum
不存在,我想将此数据作为新行插入。
更新
datenum 是唯一的,但它不是主键
【问题讨论】:
“datenum”是唯一的吗?如果是,您可以使用INSERT ... ON DUPLICATE KEY UPDATE。 Insert into a mysql table or update if exists的可能重复 【参考方案1】:尝试使用this:
如果您指定
ON DUPLICATE KEY UPDATE
,并且插入的行会导致旧行的UNIQUE index or
PRIMARY KEY, MySQL performs an [
UPDATE`](http://dev.mysql.com/doc/refman/5.7/en/update.html) 中出现重复值...
ON DUPLICATE KEY UPDATE
子句可以包含多个列分配,用逗号分隔。对于
ON DUPLICATE KEY UPDATE
,如果将行作为新行插入,则每行的受影响行值为 1,如果更新现有行,则为 2,如果将现有行设置为其当前值,则为 0。如果在连接到mysqld 时将CLIENT_FOUND_ROWS
标志指定为mysql_real_connect()
,如果现有行设置为其当前值,则受影响的行值为1(而不是0)...
【讨论】:
但是我的 datenum 不是主键。 所以在我的情况下,解决方案是什么,我尝试了这个,没有任何解决方案:INSERT INTO forwind.aggregateddata (datenum,Timestamp,Min_F1_baro_20_) VALUES ('1','2','3 ') ON DUPLICATE KEY UPDATE datenum=datenum; datenum 应该是唯一的吗?如果是,则向其添加唯一索引(如果尚未添加)然后它将起作用。请参阅 dev.mysql.com/doc/refman/5.1/en/alter-table.html 了解如何投放 UNIQUE 索引 现在我将 datenum 定义为唯一的,它工作正常,谢谢 只是一个链接,也许会给一个答案。【参考方案2】:Jai 是正确的,你应该使用INSERT ... ON DUPLICATE KEY UPDATE
。
请注意,您不需要在 update 子句中包含 datenum,因为它是唯一键,因此不应更改。您确实需要包括表中的所有其他列。您可以使用VALUES()
函数确保在更新其他列时使用正确的值。
这是使用 MySQL 的正确 INSERT ... ON DUPLICATE KEY UPDATE
语法重写的更新:
INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE
Timestamp=VALUES(Timestamp)
【讨论】:
在对具有多个唯一键或主键的表使用 INSERT ... ON DUPLICATE KEY UPDATE 时要小心。取自MySQL documentation:此外,从 MySQL 5.5.24 开始,针对具有多个唯一键或主键的表的 INSERT ... ON DUPLICATE KEY UPDATE 语句也被标记为不安全。 (错误 #11765650、错误 #58637) 错误 58637 描述 bugs.mysql.com/bug.php?id=58637 可能需要使用ALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
为Timestamp
创建UNIQUE
约束
@broadband 你可以使用composite key 来避免这个错误【参考方案3】:
我遇到了一种情况,我需要根据两个字段(两个外键)更新或插入表,而我无法在这两个字段上设置 UNIQUE 约束(因此 INSERT ... ON DUPLICATE KEY UPDATE 不起作用)。这是我最终使用的:
replace into last_recogs (id, hasher_id, hash_id, last_recog)
select l.* from
(select id, hasher_id, hash_id, [new_value] from last_recogs
where hasher_id in (select id from hashers where name=[hasher_name])
and hash_id in (select id from hashes where name=[hash_name])
union
select 0, m.id, h.id, [new_value]
from hashers m cross join hashes h
where m.name=[hasher_name]
and h.name=[hash_name]) l
limit 1;
这个例子来自我的一个数据库,输入参数(两个名字和一个数字)被替换为 [hasher_name]、[hash_name] 和 [new_value]。嵌套的 SELECT...LIMIT 1 提取现有记录或新记录中的第一个(last_recogs.id 是自动增量主键)并将其用作 REPLACE INTO 的值输入。
【讨论】:
REPLACE 总是插入一个新行!它只是删除了原来的,已经存在的!以上是关于MySql 表插入,如果不存在,否则更新的主要内容,如果未能解决你的问题,请参考以下文章