#php #mysql #sql #database
#php #mysql #sql #База данных
Вопрос:
Я пытаюсь создать запрос, в котором пользователь может ввести: имя, фамилию, ник, класс и пол. Однако некоторые из этих полей могут быть пустыми.
Я знаю, как создать запрос, который проверит все это. Однако, как я могу сделать так, чтобы он не запрашивал что-либо, если это не указано. Например, пользователь может захотеть выполнить поиск по фамилии и полу, но не по остальным.
Как я могу это сделать? Большое спасибо за помощь!
@Ibu, это то, что у меня есть на данный момент:
// 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 />';
}
Комментарии:
1. покажите нам запрос, который у вас есть на данный момент
2. вы не получите никаких результатов с запросом, который у вас есть сейчас (если что-то осталось пустым)
3. @Neal, да, я знаю, вот почему я спрашиваю, что здесь делать 🙂
Ответ №1:
Эрланд Соммарског является фактическим источником по этому вопросу:
http://www.sommarskog.se/dyn-search-2005.html#conclusion
Я бы записал каждый параметризованный AND
в формате, подобном этому:
...AND ((@Param IS NULL) OR (@Param = your_column))
Комментарии:
1. Лучший выбор — хотя популярно создавать вместе какой-нибудь динамический оператор SQL, возможно, с «1 = 1», чтобы избежать необходимости решать, куда вставлять предложения «И». Это явно и полностью объявляет предполагаемый запрос.
2. @le dorfier однако это потенциально замедляет выполнение в зависимости от того, как настроена ваша СУБД. ссылка @Joe’s также отлично подходит для построения динамического SQL (который не будет кэшировать планы)
3. Существует также более лаконичная версия
(@Param = your_column) IS NOT FALSE
4. @Andrew Lazarus но если
@Param IS NULL
тогда это приведет к нарушению равенства во всем … Я никогда не видел, чтобы это было написано так, как у вас там.
Ответ №2:
Вероятно, вы захотите создать SQL-запрос динамически. Прочитайте сообщение в блоге Гейл Шоу о универсальных запросах.
Комментарии:
1. 1 @Joe Забавно, что всякий раз, когда возникает повторный вопрос по этой теме, вы публикуете Гейл Шоу, а я публикую Эрланда Соммарскога (оба фантастические)
2. @Matthew PK: У всех нас есть свои любимые. 🙂 Согласитесь, что оба превосходны. Фактически, Гейл цитирует работу Эрланда в своем посте. Я думаю, что предпочитаю Gail, потому что он немного более лаконичный и ему легче следовать. Эрланд исчерпывающий, что иногда может быть утомительным.
3. и Эрланд не может побеспокоиться о реализации веб-макета.
Ответ №3:
Обычно я предпочитаю создавать «чистые» запросы, динамически создавая предложение WHERE. При условии, что вы должным образом очистили данные из $_POST
и скопировали их в $data
, а ключи в $data
названы в честь полей, которые они будут использовать для фильтрации:
$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..
Улучшая эту логику, вы также могли бы легко реализовать различные типы фильтров (например, начинается, содержит, аналогично ..) для каждого поля и создавать оптимизированные запросы для большинства типов поиска.
Ответ №4:
Просто проверьте $_POST
переменные и создайте запрос на основе этого.
Например, так (это плохо тем, что не очищает $_POST
для инъекции, но это хорошее начало):
$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
Затем просто добавьте $where
переменную в конец вашего запроса
Комментарии:
1. это чрезвычайно подвержено sql-инъекции!
Ответ №5:
$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']}'";
}
и т.д., Но с экранированным вводом
значение 1 = 1 используется для того, чтобы не проверять, нужно ли добавлять ключевое слово «where»