I’m quite new to SQL stuff and I’m trying to make a login form in php. I want the login form to do a bit of ip blocking to prevent brute force attacks. So, I have two tables – users and loginattempts. I’m trying to do a select that will return the user’s name/id if the username/password combination is correct, but regardless of its correctness I want the result of the login attempt query. Here’s a bit of code.
First, I make sure there is an entry in the loginattempt table by doing:
INSERT INTO loginattempts (ip) VALUES(:ip)
ON DUPLICATE KEY UPDATE attempt=attempt+1
Then, I want to do a select similar to:
SELECT users.username, users.id, loginattempts.attempt
FROM users, loginattempts
WHERE users.username = :username
AND users.password = :password
AND loginattempts.ip = :ip
However, this obviously won’t work if any of the conditions aren’t met. How could I achieve this in a single query?
Since the tables are not related, this is probably most easily accomplished with a subselect to get the login attempts:
It is possible to do a tricky cartesian join to pull the attempt, but since you are looking for a discrete row for both the user and ip, this will probably be fast enough. Just make sure you have an index on
loginattempts.ip.Update
If you must get a row back under any circumstance, you can the tricky left join I mentioned above. Since only one row will be returned by the ip, you can get away with a cartesian join (no
ONclause):