Dynamic sql search in php - php

Trying to create a dynamic search functionality.
Goal : allowing user to search by email (if not empty), if empty (by last name), if both are not empty, than by both, etc.
I know I can write if statement depicting every scenario and than insert SQL command based on that, question is can this be handled in a more simplified manner. Thanks for your help.
Current function set up does OR across all fields, values are coming from $_POST:
find_transaction($email,$last_name,$first_name, $transaction_id)
{
GLOBAL $connection;
$query = "SELECT * ";
$query .= "FROM transactions WHERE ";
$query .= "email='{$email}' ";
$query .= "OR last_name='{$last_name}' ";
$query .= "OR first_name='{$first_name}' ";
$query .= "OR transaction_id='{$transaction_id}' ";
$query .= "ORDER BY date DESC";
$email = mysqli_query($connection,$query);
confirm_query($email);
return $email;
}

I do this all the time, it's not too much work. Basically build your WHERE statement dynamically based off your POST variables, using a series of if statements.
For example:
$where_statement = "";
// First variable so is simpler check.
if($email != ""){
$where_statement = "WHERE email = '{$email}'";
}
// Remaining variables also check if '$where_statement' has anything in it yet.
if($last_name != ""){
if($where_statement == ""){
$where_statement = "WHERE last_name = '{$last_name}'";
}else{
$where_statement .= " OR last_name = '{$last_name}'";
}
}
// Repeat previous 'last_name' check for each remain variable.
SQL statement would change to:
$query = "SELECT * FROM transactions
$where_statement
ORDER BY date DESC";
Now, the SQL will only contain filters depending on what values are present, so someone puts in just email, it would generate:
$query = "SELECT * FROM transactions
WHERE email = 'smith#email.com'
ORDER BY date DESC";
If they put in just last name, it would generate:
$query = "SELECT * FROM transactions
WHERE last_name = 'Smith'
ORDER BY date DESC";
If they put both, would generate:
$query = "SELECT * FROM transactions
WHERE email = 'email#email.com' OR last_name = 'Smith'
ORDER BY date DESC";
Etc., etc.
You could add as many variables you wish here, and basically if the specific variable is not blank, it will add it to the "$where_statement", and depending on if there is anything in the "$where_statement" yet or not, it will decide to start with = "WHERE ", or append .= " OR" (notice the '.=' and the space before 'OR'.

Better use Data Interactive table : http://datatables.net/
It's useful and no SQL-injection :) Good luck !

Related

How can I use multiple values in a "where" clause? [duplicate]

This question already has answers here:
MySQL query check two value in one column
(2 answers)
Closed 2 years ago.
My code and my database are the following
$my=mysql_query("select * from users where email='ids'")or die(mysql_error);
id___email___________pass
1 abc#d.com 123
2 xxx#x.uk 333
3 ah#cc.com 555
I need a syntax in which I will select * where id='1 , 3' and when I will echo $row[email] it will return
abc#d.com
ah#cc.com
Found the correct syntax:
$all=mysql_query("select * from users where id IN ('1','2','3')");
while($row = mysql_fetch_assoc($all))
{
echo $row['name'];
}
Use IN clause to get records for multiple emails.
$my=mysql_query("select * from users where email IN ('$email','$email2','$email3')")
or die(mysql_error);
Another, not optimal, solution is adding several options to the "where" clause.
Uses more resources, but, sometimes, is what you need.
By the way, I strongly, suggest put you SQL in a variable, first.
$myquery = "select * from users ";
$myquery .= "where (1 = 0) "; // defaults to false
$myquery .= "or (email='$email') "; // maybe true
$myquery .= "or (email='$email2') "; // maybe true
$myquery .= "or (email='$email3') "; // maybe true
$mydataset = mysql_query($myquery) or die(mysql_error);
There multiple "or" expression with a "=" string comparison, are the non optimal, more resources used, equivalent of the "in" operator.
Yet, sometimes is useful to know, or use, this equivalent. If you are not sure if the source string is case sensitive, or you want to trim the value for unwanted spaces, you could also replace the "=" operator by the "like" operator.
$email = trim($email);
$email2 = trim($email2);
$email3 = trim($email3);
$myquery = "select * from users ";
$myquery .= "where (1 = 0) "; // defaults to false
$myquery .= "or (email like '%$email%') "; // maybe true
$myquery .= "or (email like '%$email2%') "; // maybe true
$myquery .= "or (email like '%$email3%') "; // maybe true
$mydataset = mysql_query($myquery) or die(mysql_error);
Cheers.

MySQL search method through PHP

Quick question on a method to search mysql database with php.
Right now, I have a function that is supposed to search and return results. Say I have two databases, one being User and one being Profile. User stores the username, email, password. while Profile stores user first name, last name, address, birth day. Right now, I'm not sure how to go about this, but this is what I have so far.
I want to be able to search both tables and return a list of results via a table which I've got covered, but I don't know how to get the intricacies down.
The function will contain either NULL or value of the variable. Right now, this is my sketch up:
if(!empty($username)):
$append .= "WHERE";
$append .= "username = ".$username."";
endif;
if(!empty($email)):
$append .= "WHERE";
$append2 .= "email= ".$email."";
endif;
if(!empty($firstname)):
$append .= "WHERE";
$append2 .= "firstname = ".$firstname."";
endif;
if(!empty($lastname)):
$append .= "WHERE";
$append2 .= "lastname= ".$lastname."";
endif;
$sql = "select * FROM Users ".$append."";
$result = mysql_query($sql);
$sql2 = "select * FROM Profile ".$append2."";
$result2 = mysql_query($sql2);
$userId = mysql_fetch_row($result2);
$userId['id'] = $id; <-- this is the one I will call to display data.
How can I efficiently do this and search/return all unique/distinct user ID's? Both tables include a user ID / incremented ID number (User table is User_ID, Profile table is acct_id). I know this code is a bit wrong... Don't worry about escaping - I;'ve gotten that sorted. Should I use a JOIN statement?
Other problem I am facing is changing between WHERE and AND because sometimes if one var is set but another isn't, then we must use AND instead of just one WHERE. Any idea how to tackle this issue?
Thanks for your input!
For your WHERE clause it is probably best to use arrays and then implode() like this
$and_where = array();
if (!empty($username))
$and_where[] = "username = ".$username;
if (!empty($email))
$and_where[] = "email = ".$email;
//etc
if (count($and_where) > 0)
$where = " WHERE ".implode(" AND ", $and_where);
else
$where = "";
Are the two tables related in some matter? If acct_id is a foreign key to User_id you can just use an INNER JOIN ($where as shown above)
$query = "SELECT Users.col, ..., Profile.col, ... FROM Users
INNER JOIN Profile ON Users.user_id = Profile.acct_id".$where;
If they aren't, you could simply UNION them
$users_and_where = array();
$profiles_and_where = array();
if (!empty($username))
$users_and_where[] = "username = ".$username;
if (!empty($email))
$users_and_where[] = "email = ".$email;
//etc
if (!empty($firstname))
$profiles_and_where[] = "firstname = ".$firstname;
if (!empty($lastname))
$profiles_and_where[] = "lastname = ".$lastname;
//etc
if (count($users_and_where) > 0)
$users_where = " WHERE ".implode(" AND ", $users_and_where);
else
$users_where = "";
if (count($profiles_and_where) > 0)
$profiles_where = " WHERE ".implode(" AND ", $users_and_where);
else
$profiles_where = "";
$query = "(SELECT col1, col2, ... FROM Users".$users_where.")
UNION
(SELECT col1, col2, ... FROM Profile".$profiles_where.")";
You should try to avoid * in your queries and select the rows specifically, this way you don't have too much overhead in the future, when additional columns are introduced that your code doesn't use here.

MySql query on different input fields where some of them are NULL

Hello I have 3 fields on input form which are set via POST method to external php
$id=$_POST['id'];
$nombre=$_POST['nombre'];
$cedula=$_POST['cedula'];
where I would like to make a search option depending on which field have data inside it or if a user put data in all 3 or in only 2 fields to search from the input fields which are not NULL fields in the same table where there is a result.
my sql query is something like that $sql = "SELECT * FROM users WHERE userID = $id AND nombre = $nombre AND cedula = $cedula) ";
obviosly which is not working, what should I do to make it work. Do I need to change only the query or I need to put something before it to check first what is not NULL. Thanks
Firstly, your SQL statement should be updated to have enclosed ' (commas) around string values.
So, modify it to:
$sql = "SELECT * FROM users WHERE userID = '$id' AND nombre = '$nombre' AND pass = '$pass'";
// ----------------------------------------^---^--------------^-------^------------^-----^
Second thing is that you should search a field only when it has a value otherwise, it of no use.
So, your modified PHP code should be:
$sql = "SELECT * FROM users WHERE 1 ";
if (!empty($id)) {
$sql .= " AND userID = '$id' ";
}
if (!empty($nombre)) {
$sql .= " AND nombre= '$nombre' ";
}
if (!empty($pass)) {
$sql .= " AND pass= '$pass' ";
}
And your Database will be searched for the fields only if they have data filled in the form.
Try to add quote:
$sql = "SELECT * FROM users WHERE userID = ".$id." AND nombre = ".$nombre." AND pass = '".$pass."' ";
Yes, you will need to put a check before which will ignore the fields which are null.
Also, you would need to put the $variable inside single quotes ' if they are VARCHAR or CHAR types.

How to make query that ignores undefined variables?

How make mysql search defined just by what is written in html form, by user, and if some form box is stayed empty, mysql should ignore it. For example:
$sql = "SELECT * FROM catalog WHERE name= '".$name."' AND publisher = '".$publisher."' ";
mysql_query($sql);
This query will display all rows where name and publisher are together. Now, what if user insert just name, and left publisher box empty. The idea is that php/mysql ignore empty form box, and display every row with inserted name. But it will not do that because $publisher will be undefined, and error emerges. How to tell musql to ignore $publisher? More generally, the question is: how to generate query that make searching defined by certain criteria if they exists, and if they don't how to just ignore it?
You can build up the sql programmatically. I am assuming you have escaped the values properly.
$sql = "SELECT * FROM catalog";
$wheres = array();
if (!empty($name)) {
$wheres[] = " name = '$name'";
}
if (!empty($publisher)) {
$wheres[] = " publisher = '$publisher'";
}
if (count($wheres)) {
$sql .= " WHERE " . implode (' AND ', $wheres);
}
//RUN SQL
Also have a read through this, you are using a deprecated mysql library.
This will allow either the name or the publisher to be NULL.
<?php
$sql = "SELECT * FROM catalog WHERE (name= '".$name."' OR name IS NULL) AND (publisher = '".$publisher."' OR publisher IS NULL)";
mysql_query($sql);
Try like
$my_var = " ";
if($publisher) //if(!empty($publisher))
$my_var = " AND publisher = '".$publisher."' ";
$sql = "SELECT * FROM catalog WHERE name= '".$name."' ".$my_var;
if the publisher is empty then you need to pass the NULL value and PLZ note that it is a bad practise.It will causes many sql injection issues.Try to put validations for the things

How to select all where the condition is null?

I have a php code with a query:
$query = "SELECT * FROM TDdb WHERE status = $status AND occupation =$occupation";
I am sending the values status and occupation with a client application to this php code.
This works when I send both status and occupation. But I want it to return rows if I just send status but not occupation also ( I mean no matter what the occupation is).
does anyone have any suggestions?
I would appreciate any help.
PS: I want to do it without if statement and just but changing the query
Personally I would create a base query and append conditions wherever you have them, like so:
$sql = 'SELECT * FROM TDdb';
$conditions = array();
$args = array();
if ($action) {
$conditions[] = 'status = :status';
$args[':status'] = $status;
}
if ($occupation) {
$conditions[] = 'occupation = :occupation';
$args[':occupation'] = $occupation;
}
if ($conditions) {
$sql .= ' WHERE ' . join(' AND ', $conditions);
}
$stmt = $db->prepare($sql);
$stmt->execute($args);
Looks like you've got a few good options for how to do it in SQL, or how to make the SQL string variable in PHP.
One reason to consider using an 'if' in the PHP code for the database access performance.
When you introduce an 'or' condition like that in SQL, you're not going to get index access. It is much harder for the database to determine what path it should take than for the PHP code because the SQL engine optimizes the query without knowing what the variable will resolve to at execution.
You already know in the PHP which version of the query you really want. This will perform better if you make that choice there.
This will work if you pass an occupation or a NULL value.
SELECT *
FROM TDdb
WHERE status = $status
AND ($occupation IS NULL OR occupation = $occupation)
"SELECT * FROM TDdb WHERE status = '$status' AND (occupation = '$occupation' OR occupation IS NULL)";
Apart from the solution provided by #Tom and #Damien Legros, you may create two query strings one with occupation and one without occupation. Something like:
$query = "SELECT * FROM TDdb WHERE status = $status";
if ($occupation != "") {
/*When you have value for occupation*/
$query .= " AND occupation =$occupation";
}
So in this case, data will be returned if you have only the status field. Secondly, please check if the status and occupation fields in table are varchar then you have to enclose them in single quotes (').
Thanks everyone for help. specially jack.
finally i created my query like this:
$query = 'SELECT * FROM TDdb';
if ($status) {
$query = $query." WHERE status = '".$status."'";
}
if ($occupation) {
$query = $query." AND occupation = '".$occupation."'";
}

Categories