1

我正在尝试进行具有以下行为的查询:

  • 如果尚不存在则插入新行:id = NULL或行。id = :id
  • id = :id如果行已存在,则更新现有行。
  • 将值设置activatedNOW()if:
    • 的当前值status <> :status。(又名。如果 的值status会改变)
    • 的值:status = 'active'status(又名will的新值'active'

为了做到这一点,我做了以下准备好的声明:

INSERT INTO test
  (`id`, `title`, `status`, `activated`)
VALUES
  (:id, :title, :status, NULL)
ON DUPLICATE KEY UPDATE
  id = LAST_INSERT_ID(id),
  status = VALUES(status),
  activated = IF(status <> VALUES(status) AND VALUES(status) = 'active', 
               NOW(), activated);

据我所知,这句话准确地描述了所需的逻辑。但是,activated无论 的值是否status更改,其值始终保持不变'active'

谁能解释我做错了什么?并且(最好)解释如何解决它?

4

2 回答 2

1

这个问题非常不像SQL,你在比较之前分配了状态;

status=VALUES(status),                                 -- assign so they're equal
activated=IF(status <> VALUES(status) AND              -- compare, always equal
      VALUES(status) = 'active', NOW(), activated);

只需颠倒分配,事情就可以正常工作。

INSERT INTO test
  (`id`, `title`, `status`, `activated`)
VALUES
  (:id, :title, :status, NULL)
ON DUPLICATE KEY UPDATE
  id=LAST_INSERT_ID(id),
  activated=IF(status <> VALUES(status) AND 
               VALUES(status) = 'active', NOW(), activated),
  status=VALUES(status);

顺便说一句,您只需要分配实际更改的列,无需设置id更新。

于 2013-05-20T20:46:04.367 回答
0

您没有在 ON DUPLICATE KEY UPDATE 子句中指定 id (或键列)。

来自:http ://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

例如,如果列 a 被声明为 UNIQUE 并且包含值 1,则以下两个语句具有相同的效果:

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

更新表 SET c=c+1 WHERE a=1;

您目前拥有的很可能是更改您插入数据库的最后一行,而不是重复的键行。阅读有关 LAST_INSERT_ID() 的文档:http: //dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

回顾您的问题,我知道我并没有真正/完全回答您的问题。我部分试图了解用例是什么。在我通过代码创建用户的情况下,如果是管理员创建用户,我只需将帐户设置为活动的(如果有,则设置激活的列)。如果是用户通过网络表单创建帐户,他们将被设置为待处理,直到他们使用电子邮件中的链接。电子邮件中的链接使用激活码,允许我执行以下操作:

update user set status='active' activated=NOW() where code=:activation_code
于 2013-05-20T20:41:01.677 回答