0

为了更清楚:

表格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) 错误的用户/通行证对,但有一行与用户名

我想用ANDselect id from thetable where username="tgh" and password="wrongpass" and another_variable="another";更新last_unsuccessful_login所有行的列(这是唯一的,不能有两行(“tgh”,“another”)对。但是可以有(“tgh”,“another2”)。 ) 到.username="tgh"another_variable="another"CURRENT_TIMESTAMP

因此,示例行将是(1, "tgh", "pass", 0, CURRENT_TIMESTAMP, "another")不完全匹配的“选择”查询之后。

更清楚地说,我试图避免只在表上运行额外的更新username="tgh"another_variable="another"update thetable set last_unsuccessful_login=CURRENT_TIMESTAMP where username="tgh" and another_variable="another";,根据选择的结果。

2) 正确的用户/通行证对

另外,如果所有三个usernameandpasswordanother_variable匹配,这次我想将 设置last_successful_loginCURRENT_TIMESTAMP

这将使示例行 `(1, "tgh", "pass", CURRENT_TIMESTAMP, 0, "another")

最有效的方法是什么?

4

1 回答 1

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')

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

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$$
于 2012-08-20T21:57:03.673 回答