简体   繁体   中英

MySQL Query with multiple WHEREs, some may be empty

I am trying to create a query where a user can enter: first name, last name, nick name, grade, and gender. However, some of these fields may be empty.

I know how to create a query that will check all of those. However, how can I make it where it won't query for something if it's not given. For example, a user might want to search by last name and gender, but not the others.

How can I go about doing this? Thanks so much for the help!

@Ibu, this is what I have so far:

// Now we need to query the database for these terms
$sql_query = "SELECT * FROM `students` WHERE `first_name` = '" . $first_name . "' AND `last_name` = '" . $last_name . "' AND `nick_name` = '" . $nick_name . "' AND `grade` = '" . $grade . "' AND `gender` = '" . $gender . "'";
$result = mysql_query($sql_query);

// Let's check to make sure there is an actual result
$num_rows = mysql_num_rows($result);

if($num_rows < 1) {
    echo 'No student was found using that criteria.';
}

if($num_rows >= 1) {
    echo '<p>' . $num_rows . ' result(s) found. Below are the results:</p>';
    echo '<br />';
}

while($row = mysql_fetch_array($result)) {
    echo '
        <table border="1" width="400">
        <tr>
            <td colspan="2" align="center">Student Profile - ' . $row['last_name'] . ', ' . $row['first_name'] . '</td>
        </tr>
        <tr>
            <td>First Name: </td>
            <td>' . $row['first_name'] . '</td>
        </tr>
        <tr>
            <td>Last Name: </td>
            <td>' . $row['last_name'] . '</td>
        </tr>
        <tr>
            <td>Nick Name: </td>
            <td>' . $row['nick_name'] . '</td>
        </tr>
        <tr>
            <td>Grade: </td>
            <td>' . $row['grade'] . '</td>
        </tr>
        <tr>
            <td>Gender: </td>
            <td>' . $row['gender'] . '</td>
        </tr>
        </table> <br /><br />';

}

Erland Sommarskog is a de-facto source on this quesion:
http://www.sommarskog.se/dyn-search-2005.html#conclusion

I would write each parameterized AND in a format like this:

...AND ((@Param IS NULL)  OR (@Param = your_column))

You'll probably want to build the SQL query dynamically. Read Gail Shaw's blog post on Catch-all queries .

I usually prefer creating "clean" queries, by dynamically building the WHERE clause. Provided that you properly sanitized the data from $_POST and copied it into $data , with keys in $data named after the fields they will be used to filter:

$sql = "SELECT ..fields.. FROM ..table..";
$search_enabled_fields = array('firstname', 'lastname', 'email', /* ..etc.. */);
$conditions = array();
foreach ($search_enabled_fields as $field) {
  if (!empty($data[$field])) { // isset and not an empty string
    $value = $data[$field];
    // maybe you could sanitize $value here if you didn't before..
    $conditions[] = "$field = '$value'";
  }
}
if (count($conditions) > 0) {
  $sql .= " WHERE ". implode(' AND ', $conditions);
}
// now, execute your $sql query..

Improving this logic, you could also easily implement different filter types (eg. begins, contains, similar to..) for each field, and build optimized queries for most types of search.

Just check the $_POST vars and build the query on that.

Like this for example (this bad in that it does not sanitize the $_POST for injection, but its a good start):

$whereSet = false;
$where = '';
if(isset($_POST['name'])){
    $whereSet = true;
    $where .= "WHERE name = '{$_POST['name']}'\n";
}
if(isset($_POST['nick'])){
    if(!$whereSet){
        $where .= "WHERE ";
        $whereSet = true;
    }
    else {
        $where .= "AND ";
    }
    $where .= "nick = '{$_POST['nick']}'\n";
}
//...etc

Then just append the $where variable to the end of your query

$query = "select * from somewhere where 1 = 1";
if(isset($_POST['something'])){
  $query .= " and something = '{$_POST['something']}'";
}
if(isset($_POST['something_else'])){
  $query .= " and something_else = '{$_POST['something_else']}'";
}

etc. but with escaped input

the 1 = 1 is there to avoid having to check if we need to add the "where" keyword

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM