Check two tables in one query - php

I have the following function:
function login_check($email, $password)
{
$email = mysql_real_escape_string($email);
$password = md5($password);
$login_query = mysql_query("SELECT COUNT(`id`) as `count`, `id` FROM `table_name` WHERE `email`='$email' AND `password`='$password'");
return (mysql_result($login_query, 0) == 1) ? mysql_result($login_query, 0, 'id') : mysql_error();
}
I want it to check if the user login is correct in two different tables not only one since I've made another table for users who have authenticated their twitter account with my site.

You'd be better off with a single table that has an "authenticated with Twitter" flag but you can check both with something like this:
select exists(
select 1 from table_name where email = '$email' and password = '$password'
union
select 1 from twitter_table where email = '$email' and password = '$password'
)
MySQL will give you a one (AKA true) if at least one of the tables has what you're looking for and a zero (AKA false) if neither has a match.
Using the select exists(select 1...) trick will also be faster than counting as the database only needs to find one match or check the indexes to know that there are no matches before it returns from the query.

You could create an union view of both tables:
CREATE VIEW combined_accounts AS
(SELECT id, twitter_mail AS mail, password FROM twitter_accounts)
UNION
(SELECT id, mail, password FROM my_accounts);

Related

MySQL WHERE if one is there but other is not in database

I am trying to get results from MySQL. but it only works if both have a valve.
Like if both WHERE is in the database it works, but if only one is in the database and the other is not it fails, this is what I have now for the code
$check_ip = $_GET['ip'];
$check_username = $_GET['username'];
$query = "SELECT *, COUNT(ip), COUNT(username) FROM bl WHERE ip = '$check_ip' AND username = '$check_username'";
$resultID = mysql_query($query, $linkID) or die("Data not found.");
Now if both IP and username are in the database it get the results, which is great, I am also wanting result if ip is there but username is not and the other way around.
It says they both not there
What is happening is when ip and username is there is says they both there.
But if ip is not and username is, it says they both not there.
I need a reply from both, so if ip is there and username is not, I need the ip data
Why are you not using OR Operator
"SELECT *, COUNT(ip), COUNT(username) FROM bl WHERE ip = '$check_ip' OR username = '$check_username'"
use UNION
SELECT *, COUNT(ip), COUNT(username) FROM bl WHERE ip = '$check_ip'
UNION
SELECT *, COUNT(ip), COUNT(username) FROM bl WHERE username = '$check_username'"
Change the AND to OR so that MySQL counts rows if one (or both) of the two conditions is true.
As your query contains the 'AND' condition which means if both the values exists then only it will return a value. you can change the 'AND' condition to 'OR' for the desired result.
Just change the AND for an OR, please read this, it would help in the future: https://dev.mysql.com/doc/refman/5.0/en/selecting-rows.html

prevent duplicate usernames adding a sequence number after username

I'm trying to Implement the facebook registration. It works and i'm getting back all the data I need. Now I want to assign a username to the user like this:
$username = ''.$first_name.'.'.$lastname.'';
The problem is that I don't know if a user with the same name and last name will register to the website and i would like to check if the username is taken and add a sequence number to the basic $username (facebook does the same), like this:
name.lastname
name.lastname.1
name.lastname.2
etc
I tried with:
$temp_username = ''.$first_name.''.$last_name.'';
$check_username = mysql_query("SELECT username FROM users WHERE username = '$temp_username'");
$num_rows = mysql_num_rows($check_username);
if ($num_rows == 0){
$username = strtolower($temp_username);
} else {
$username = strtolower(''.$temp_username.'.'.$num_rows.'');
}
but of course it doesn't work because there is always just one user with that username.
EDIT*** this is how I fix it (thanks to zander):
$temp_username = ''.$first_name.''.$last_name.'';
$num_rows = mysql_num_rows(mysql_query("SELECT username FROM users WHERE username = '$temp_username' OR username LIKE '$temp_username%' "));
$username = strtolower(''.$temp_username.'.'.$num_rows.'');
$num_rows = mysql_num_rows(mysql_query("SELECT username FROM users WHERE username = '$temp_username' OR username LIKE '$temp_username.%' ")); will return the number of rows you actually expect. Then, use $username = strtolower(''.$temp_username.'.'.$num_rows.''); to get it done. No need of loops.
The following SELECT determines the user with the highest number if there are any
select max(reverse(SUBSTRING(reverse(username), 1, LOCATE('.', reverse(username))-1))) trail
from users
where username like 'John.Smith.%';
SQL Fiddle Demo
Add it to PHP like this
...
if ($num_rows == 0){
    $username = strtolower($temp_username);
} else {
... query for the max number here
... concatenate the username with the max number
}
Ah and last but not least. Make sure your code is not vulnerable to SQL injection. Use bind parameters. Good start is this answer: Best way to defend against mysql injection and cross site scripting
There are many existing answers that correctly suggest using the LIKE operator in your WHERE clause. But there is one critical issue that none of the existing answers have addressed.
Two people could attempt to add the same username at the same (or nearly the same) time. Each would SELECT the count of existing usernames that are LIKE that name, and they each would generate the same number suffix, and you still get duplicates.
I am neither a mysql developer nor php developer, so I won't provide much in the way of specific syntax.
You will want to make sure your users table uses the InnoDB storage engine. Your code will need to:
START TRANSACTION
SELECT FOR UPDATE to make sure only one person can get the count of
a particular username at a given time
INSERT your new user
COMMIT your transaction.
See Select for update for more information.
Use this code instead:
$check_username = mysql_query("SELECT username FROM users WHERE username = '$temp_username' OR username LIKE '$temp_username.%' ");
example this will match:
johnsmith or joshnsmith.X where x will be 1 , 2 , 3 .......etc
DB Dump
CREATE TABLE Users (
`username` varchar(255) PRIMARY KEY,
`firstname` varchar(255),
`lastname` varchar(255)
);
INSERT INTO Users (`username`, `firstname`, `lastname`) VALUES (
'praveen.kumar', 'Praveen', 'Kumar'
),(
'praveen.kumar.1', 'Praveen', 'Kumar'
),(
'praveen.kumar.2', 'Praveen', 'Kumar'
);
Now to the SQL, we can do this way:
SELECT *
FROM `Users`
WHERE `username` LIKE "praveen.kumar%"
ORDER BY `username` DESC
Gives an output:
+-----------------+-----------+----------+
| USERNAME | FIRSTNAME | LASTNAME |
+-----------------+-----------+----------+
| praveen.kumar.2 | Praveen | Kumar |
| praveen.kumar.1 | Praveen | Kumar |
| praveen.kumar | Praveen | Kumar |
+-----------------+-----------+----------+
And you can get the latest one this way:
SELECT *
FROM `Users`
WHERE `username` LIKE "praveen.kumar%"
ORDER BY `username` DESC
LIMIT 1
The PHP Code:
<?php
# Outputs the largest number with that username.
$nextUser = substr($userNameFromDB, strrpos($userNameFromDB, "."));
$nextUser++;
?>
SQL Fiddle: http://sqlfiddle.com/#!2/ad149/1
Use the count() function and the like operator:
$check_username = mysql_query("
SELECT count(username)
FROM users
WHERE username like '$temp_username%'
");
It will return the number of existent names. No need to call mysql_num_rows.
You should use the count() function
$query = mysql_query("
SELECT count(user_name) cnt
FROM users
WHERE username = '$just_registered_username'
");
and then fetch the result using
$row = sql_fetchrow($query);
And then get the count of users as
$next_index = $row->cnt;
Then append it to the new username
$new_username = "{$just_registered_username}.{$next_index}";
Don't forget to add comments to your final code.
Also try and use PDO for database access.
If you want to find a user name that does not exist, you have to try combinations, until you find a non existing username.
Therefore, loop until you find a non existing name:
$temp_username = $first_name . $last_name;
$i=1;
$found = false;
while(!$found) {
$check_username = mysql_query(
"SELECT username FROM users WHERE username = '$temp_username'");
$found = mysql_num_rows($check_username);
if ($found){
$username = strtolower($temp_username);
}
else{
$temp_username = $first_name . $last_name . '.' . $i;
$i++
}
}

Checking is username exists on two tables PHP PDO?

I have a users table and a users_banlist table.
On my registration form i want to check all in one query whether the username someone entered on form exists in the users table and see if it also exists on the users_banlist table.
I can do them on there own in individual queries but would rather do it all in one.
Here is what I got, but even though I enter a username that is taken it does not tell me it's already taken.
$stmt = $dbh->prepare("
SELECT
users.user_login,
users_banlist.user_banlist
FROM
users ,
users_banlist
WHERE
users.user_login = ? OR
users_banlist.user_banlist = ?");
// checker if username exists in users table or users_banlist table
$stmt->execute(array($username, $username));
if ( $stmt->rowCount() > 0 ) {
$error[] = 'Username already taken';
}
Basically I think it is something to do with the execute or rowCount(), could anyone tell me where I am going wrong? Being new to pdo I'm finding it a little confusing at the moment.
You could use the query
SELECT
users.user_login
FROM
users
WHERE
users.user_login = ?
UNION ALL
SELECT
users_banlist.user_banlist
FROM
users_banlist
WHERE
users_banlist.user_banlist = ?
and then proceed as normal. What you were using is a CROSS JOIN which returns the cartesian product that produce rows which combine each row from the first table with each row from the second table. If one of those tables returns 0 rows you get 0 results
Use SQL JOINS instead
SELECT
users.user_login,
users_banlist.user_banlist
FROM
users INNER JOIN
users_banlist ON users.ID=users_banlist.user_id
WHERE
users.user_login = ? OR
users_banlist.user_banlist = ?
where users.ID and users_banlist.user_id are same

Joining tables in MySql with one common field but different values for the common field

how to join 3 tables with one common field like
table1:c_id,username,password,c_role
table2:p_id,username,password,c_role
table3:s_id,username,password,c_role
in this c_role field is common
here i assigned
enum '1' for c_role in table1
enum '2' for c_role in table2
enum '3' for c_role in table3
for giving rights to 3 different users like corres, principal and for a staff when they login..
Now when they login it should identify the user and take them to their page..
You should have one table that contains the following columns:
id (unique, primary), username, password, role (INT, would be assigned 1-3 for principal, staff or corre depending on the user)
Additionally
You could have another table called roles if you want set up like this:
id (unique, primary), title (options for title would be principal, staff, or corres)
When the user logs in just do something like
if($role == 1){
// redirect to principal page
}
elseif($role == 2){
// redirect to staff page
}
elseif($role == 3){
// redirect to corres page
}
I'm not certain but I believe this would work as well. Try this query.
(SELECT '1' AS role FROM table1 WHERE username = $username AND password = $password)
UNION ALL
(SELECT '2' AS role FROM table2 WHERE username = $username AND password = $password)
UNION ALL
(SELECT '3' AS role FROM table3 WHERE username = $username AND password = $password)
Assuming the user is only located in ONE of those three tables then it should match the username and password and find out which table the user is coming from. Then you can pull out the role by using
$role = $row['role'];
If the username/password combination is incorrect then $role would be empty or you could fetch the number of rows [using $iscorrectuser = mysql_num_rows($query)] where there is a match and the number of rows would be 0. You could then redirect the user trying to log in with a "Unsuccessful login" error message.
The only joins would be on username (and password ?) unless c_id, p_id and s_id are all the same id?
You can't join on role seeing as they are different in each table, aside from an utterly daft role = 1 in Table1 is the equivalent of role = 2 in table2.
Do you mean a union? As in you want
User Password Role
Fred Fr3d 1
Fred ??? 2
Fred ??? 3
Not sure what you are trying to achieve with this schema, but it breaks near every rule in the book, and doesn't seem to meet your needs....
Based on your comment, one way you might look at is.
Is
Users (UserID, UserName, Password etc) Key UserID
Roles (RoleID, RoleName etc) Key RoleID
UserRoles(UserID,RoleID) Key UserID,RoleID
You need to learn a bit about databases particularly normalisation, first three forms should do for most things.
Then
Select UserName, Password,RoleName From Users
inner join UserRoles on Users.UserID = UserRoles.UserID
inner join Roles on UserRoles.RoleID = Roles.RoleId
and such like become possible and efficient.
session and include functions are given:
session_start();
include("config.php");
if(isset($_POST['T_UserName']) && isset($_POST['T_Password']) && !empty($_POST['T_UserName']) && !empty($_POST['T_Password']))
{
username and password sent from form:
$T_UserName=$_POST['T_UserName'];
$T_Password=$_POST['T_Password'];
To protect MySQL injection:
$T_UserName = stripslashes($T_UserName);
$T_Password = stripslashes($T_Password);
$T_UserName= mysql_real_escape_string($T_UserName);
$T_Password = mysql_real_escape_string($T_Password);
$sql="SELECT * FROM login WHERE username='$T_UserName' and password='$T_Password'"; $result=mysql_query($sql);
Mysql_num_row is counting table row:
$count=mysql_num_rows($result);
If result matched $T_UserName and $T_Password, table row must be 1 row :
if($count==1)
{
Register $T_UserName, $T_Password and redirect to file "correspindex.php" :
session_register("T_UserName");
session_register("T_Password");
redirect to error page or display error message then :
if(isset($_POST['emp_role'])
{
$userinfo = mysql_fetch_assoc($sql);
$emp_role = $userinfo['emp_role'];
if($emp_role == 1)
{
header("location:corrrespondindex.php");
}
elseif($emp_role == 2 )
{
header("location:principalindex.php");
}
elseif($emp_role == 3)
{
header("location:staffindex.php");
}
closes out if the user DOES exist:
header("location:loginhome.php");
}
else
{
echo "Wrong Username or Password";
}
}
}
php is closed
this is the php code im getting so many error
i create 1table with id,username,password and role(ENUM,values as'1','2','3' –
any else shud i do in the code???

MYSQL>PHP - Trouble with a query relating to function that checks if a table contains a row of user details

I am having trouble with a function that checks if a set of user entered info (username and password) exists within either of the two possible tables where this information is stored.
The first table is the users table. It contains the first set of specific user information.
The last table is the listings table. It contains the second set of specific user information.
I have basically modified my original code to include the new listings table, and hence the trouble coming from within that task. The old code basically counted the number of results in the users table, if the result was greater than 0, then the function returned true, else false.
Now I have been stuck on the best way to go about adding another table to the query, and function. So I have been playing around with a union.
This was the original query:
SELECT COUNT(*) FROM users
WHERE id='$accNum' AND password='$password'
This returned a count of either 0 or 1 based on the info stored in the users table.
This is how I have reworked the query to include a count of the additional listings table:
SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
This returned a result set of two rows, the first relating to the users table, and the second relating to the listings table. Then a column called COUNT (*) that contained the result count. This is the result set that I see within php myadmin.
Now this is the function:
function databaseContainsUser($accNum, $password)
{
include $_SERVER['DOCUMENT_ROOT'] . '/../../includes/db.inc.php';
$accNum = mysqli_real_escape_string($link, $accNum);
$password = mysqli_real_escape_string($link, $password);
$sql = "SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
";
$result = mysqli_query($link, $sql);
if (!$result)
{
$error = 'Error searching for user.';
include 'error.html.php';
exit();
}
$row = mysqli_fetch_array($result);
if ($row[0] > 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
The problem that I have, is trying to work out how exactly to check the results to ascertain if the given log in credentials are valid.
I tried this: if (($row[0] > 0) || ($row[0] > 0)) But a var dump on $row showed that only the first row (count of users table) was being added to the array.
So I decided that this was complicated, and a long way to the final result.
So I tried selecting only the id column of the result as in:
...
`COUNT( * )` to `id`
...
$data = mysql_query($sql);
$num_sql = mysql_num_rows($data);
if ($num_sql > 0)
...
But this did not work out for me either.
But in either instance, my hours of trial and error have provided me with no success... So I've decided to seek help from the knowledgeable members of Stack Overflow!
So my question is this, what would be a logical way of going about this task? I am looking for any suggestions, or positive input what so ever here.
As I am fairly new to dabbling with PHP and mysql, if you would like to provide some code to explain your suggestions or input on the matter, it would more than likely help me to better understand the answer.
If you are checking existence only try doing this that way:
select case when
exists (SELECT 1 FROM users WHERE id = '$accNum' AND PASSWORD = '$password') or
exists (SELECT 1 FROM listings WHERE id = '$accNum' AND PASSWORD = '$password')
then 1 else 0
end as itDoesExist
It returns always one row with one column with 1 when record exists in at last one table (else 0).
Do not use count to check whether some specific record/-s exist/-s in table, it's usually slower than simple exists.
Looks like you're going to get two rows in the result no matter what. Try this:
$sql = "SELECT id,password
FROM users
WHERE id = '$accNum' AND password = '$password'
UNION
SELECT id,password
FROM listings
WHERE id = '$accNum' AND password = '$password'
";
Now you can just check mysql_num_rows() to see if there's a match in either of the tables.
There are a couple of ways to go about this; if we are to stick with the approach you started with; you can simplify the query to:
$sql = "SELECT COUNT(1) FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (SELECT COUNT(1) FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password')";
The reason you are only seeing one result, is because thats the way mysql_fetch_array() works, try doing this to get all results:
while ($row = mysql_fetch_array($result)) {
$data[] = $row;
}
var_dump($data);
Now you should have both values in there to validate with your conditional statements.

Categories