1

我对 SQL 的东西很陌生,我正在尝试在 php 中制作一个登录表单。我希望登录表单做一些 ip 阻止以防止暴力攻击。所以,我有两个表 - 用户和登录尝试。我正在尝试进行选择,如果用户名/密码组合正确,则将返回用户的名称/ID,但无论其正确性如何,我都想要登录尝试查询的结果。这是一些代码。

首先,我通过执行以下操作确保 loginattempt 表中有一个条目:

INSERT INTO loginattempts (ip) VALUES(:ip)
            ON DUPLICATE KEY UPDATE attempt=attempt+1

然后,我想做一个类似于:

SELECT users.username, users.id, loginattempts.attempt
             FROM users, loginattempts
             WHERE users.username = :username
             AND users.password = :password
             AND loginattempts.ip = :ip

但是,如果不满足任何条件,这显然是行不通的。我怎样才能在单个查询中实现这一点?

4

1 回答 1

2

由于这些表不相关,这可能最容易通过子选择来完成以获取登录尝试:

SELECT
  users.username,
  users.id,
  /* COALESCE() to return 0 if no attempt yet logged */
  COALESCE((SELECT attempt FROM loginattempts WHERE ip = :ip),0) AS attempt
FROM uusers
WHERE 
  username = :username
  AND password = :password

可以做一个棘手的笛卡尔连接来尝试,但由于您正在为用户和 ip 寻找一个离散的行,这可能会足够快。只需确保您在loginattempts.ip.

更新

如果您在任何情况下都必须返回一行,您可以使用我上面提到的棘手的左连接。由于 ip 只会返回一行,因此您可以使用笛卡尔连接(无ON子句):

SELECT
  username,
  userid,
  attempt
FROM
  /* Should always return exactly one row */
  (SELECT COALESCE((SELECT attempt FROM loginattempts WHERE ip = :ip),0) AS attempt)
  /* left joins against users with no ON condition, so if user doesn't match NULLs will return */
  LEFT JOIN users
WHERE 
  username = :username
  AND password = :password
于 2012-08-25T11:31:38.630 回答