如果选择部分匹配该行的列之一,则触发行的列上的更新

时间:2012-08-14 20:59:27

标签: mysql

更清楚:

thetable (id int, username varchar(30), password varchar(30), last_successful_login timestamp, last_unsuccessful_login timestamp, another_variable varchar(30))包含以下行:(1,“tgh”,“pass”,0,0,“another”)

1)用户/密码对错误,但用户名

我希望select id from thetable where username="tgh" and password="wrongpass" and another_variable="another";使用last_unsuccessful_loginusername="tgh"更新所有行的another_variable="another"列(这是唯一的,不能有两行(“ tgh“,”另一个“)对。虽然可以(”tgh“,”another2“)。)CURRENT_TIMESTAMP

因此,“选择”查询未完全匹配后,示例行将为(1, "tgh", "pass", 0, CURRENT_TIMESTAMP, "another")

为了更加明确,我试图避免在表格上仅使用username="tgh"another_variable="another"运行额外更新,即根据select的结果update thetable set last_unsuccessful_login=CURRENT_TIMESTAMP where username="tgh" and another_variable="another";

2)更正用户/通行证

此外,如果所有三个usernamepassword以及another_variable匹配,这次我想将last_successful_login设置为CURRENT_TIMESTAMP

这会使示例行`(1,“tgh”,“pass”,CURRENT_TIMESTAMP,0,“另一个”)

最有效的方法是什么?

1 个答案:

答案 0 :(得分:1)

对您的问题的简短回答是否定的,SELECT语句不可能导致或触发更新。 (这里需要注意的是SELECT语句可以调用一个可以执行UPDATE的FUNCTION(MySQL存储程序)。)

您无法绕过发布UPDATE语句;必须从某个地方发出UPDATE语句,SELECT语句不能“触发”它。

可以让一个UPDATE语句根据密码列中的当前值检查提供的密码,并设置last_successful_login和last_unsuccessful_login列,例如:

UPDATE thetable 
   SET last_successful_login = 
       IF(IFNULL(password,'')='wrongpass',CURRENT_TIMESTAMP,0)
     , last_unsuccessful_login = 
       IF(IFNULL(password,'')='wrongpass',0,CURRENT_TIMESTAMP)
 WHERE username='tgh' 
   AND another_variable='another'

因此,您可以先发出UPDATE语句;然后发出SELECT语句。

如果您想最大限度地减少数据库“往返”的数量,以增加复杂性为代价(让其他人更难弄清楚发生了什么),您可以将UPDATE语句放入存储的程序中。如果将其放入函数中,则可以设置返回值以指示登录是否成功。

SELECT udf_login('username','wrongpass','another')

因此,从您的应用程序看,您看起来正在进行登录检查,但被调用的函数可以执行更新。

CREATE FUNCTION `udf_login`
( as_username         VARCHAR(30)
, as_password         VARCHAR(30)
, as_another_variable VARCHAR(30) 
) RETURNS INT
READS SQL DATA
BEGIN
   UPDATE `thetable`
      SET `last_successful_login` = 
          IF(IFNULL(`password`,'')=IFNULL(as_password,''),CURRENT_TIMESTAMP,0)
        , `last_unsuccessful_login` = 
          IF(IFNULL(`password`,'')=IFNULL(as_password,''),0,CURRENT_TIMESTAMP)
    WHERE `username` = as_username
      AND `another_variable` = as_another_variable;

   -- then perform whatever checks you need to (e.g)
   --     SELECT IFNULL(t.password,'')=IFNULL(as_password,'') AS password_match
   --       FROM `thetable` t
   --      WHERE t.username = as_username
   --        AND t.another_variable = as_another_variable
   -- and conditionally return a 0 or 1
   RETURN 0;
END$$