1

我试图让有以下行为的查询MySQL的问题:与IF语句和TIMESTAMP

  • 如果插入新行:id = NULL或行,其中id = :id还不存在。
  • 更新现有的行,如果其中id = :id已存在的行。
  • 设置的activatedNOW()如果值:中status <> :status
    • 当前值。 (aka。如果status的值将被改变)
    • 值为:status = 'active'。 (又名的status新值将是'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'

任何人都可以解释我做错了什么?并(最好)解释如何解决它?

回答

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上更新列。

+0

嘿,我没有想到!我现在要试试:) –

+1

好的!有用!感谢Joachim! –

0

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

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

例如,如果列中的被声明为UNIQUE和包含值 1,下列两个语句具有相同的效果:

INSERT INTO表(一, b,c)VALUES(1,2,3)在重复密钥更新 c = c + 1;

UPDATE table 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 
+0

实际上,“id = LAST_INSERT_ID(id)”部分是有意的,它确保我可以检索更新行的id。 (这也在mysql文档中描述) –