MySQL从多个表中选择,但始终从一个表中获取数据

时间:2012-08-25 11:22:00

标签: mysql

我对SQL的东西很新,我正在尝试在php中创建一个登录表单。我希望登录表单执行一些ip阻止以防止暴力攻击。所以,我有两个表 - 用户和loginattempts。如果用户名/密码组合正确,我正在尝试做一个将返回用户名/ 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

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

1 个答案:

答案 0 :(得分: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