我对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
但是,如果不满足任何条件,这显然是行不通的。我怎么能在一个查询中实现这个目标?
答案 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