Вопрос:
Я хочу показать все текстовые сообщения из db, где id=$e ($err – массив).
Вставив запрос в цикл foreach, он работает хорошо, но он выполняет дополнительную работу (выполняет запрос для каждого значения массива).
Есть ли другой способ сделать это (я имею в виду запрос на получение из цикла foreach)?
Мой код выглядит так.
foreach ($err as $e) { $result = $db -> query(«SELECT * from err_msgs WHERE id=’$e'»); $row = $result -> fetch_array(MYSQLI_BOTH); echo «<li><span>».$row[1].»</span></li>»; } Лучший ответ:
Это намного эффективнее с помощью метода implode(), поскольку это приведет только к одному запросу базы данных.
if (!$result = $db->query(«SELECT * FROM ‘err_msgs’ WHERE ‘id’='».implode(«‘ OR ‘id’='»,$err).»‘»)) { echo «Error during database query<br />n»; // echo $db->error(); // Only uncomment this line in development environments. Don’t show the error message to your users! } while ($row = $result->fetch_array(MYSQLI_BOTH)) { echo «<li><span>».$row[1].»</span></li>n»; } Ответ №1
Проверьте предложение SQL IN.
Ответ №2
Во-первых, небольшая часть лекции: встраивание строк непосредственно в ваши запросы в какой-то момент вызовет у вас проблемы (например, проблемы, связанные с SQL-инъекцией), старайтесь избегать этого, если это возможно. Лично я использую библиотеку PDO PHP, которая позволяет вам связывать параметры вместо создания строки.
Что касается вашего вопроса, я не уверен, что понял. Вы говорите, что это делает дополнительную работу, вы имеете в виду, что она возвращает правильные результаты, но неэффективно? Если это так, то это тоже можно решить с помощью PDO. Вот идея.
Шаг 1: Подготовьте свое выражение, помещая местозаполнитель, где у вас в настоящее время есть “$ e”. Шаг 2: Петля через $ err, в теле цикла вы установите держатель места как текущее значение $ e
Делая это, вы не только обращаетесь к проблеме SQL-инъекций, вы можете избежать накладных расходов на необходимость синтаксического анализа и оптимизации запроса каждый раз, когда он выполняется (хотя имейте в виду, что это не может быть значительным накладным расходами в вашем конкретном случае).
Некоторые фактические коды выглядят следующим образом:
// Assume that $dbdriver, $dbhost and $dbname have been initialised // somewhere. For a mysql database, the value for $dbdriver should be // «mysql». $dsn = «$dbdriver:host=$dbhost;dbname=$dbname»; $dbh = new PDO($dsn, $dbuser, $dbpassword); $qry = «SELECT * from err_msgs WHERE id = :e» $sth = $dbh->prepare($qry); foreach ($err as $e) { $sth->bindParam(«:e», $e); $sth->execute(); $row = $sth->fetch(); // Prints out the *second* field of the record // Note that $row is also an associative array so if we // have a field called id, we could use $row[«id»] to // get its value echo «<li><span>».$row[1].»</span></li>»; }
Один последний момент, если вы хотите просто выполнить запрос один раз, вместо того, чтобы выполнять его внутри цикла, это возможно, но опять же, может не дать какого-либо улучшения производительности. Этого можно добиться с помощью синтаксиса IN. Например, если меня интересуют записи с идентификатором в наборе {5, 7, 21, 4, 76, 9}, я бы сделал:
SELECT * from err_msgs WHERE id IN (5, 7, 21, 4, 76, 9)
Я не думаю, что существует чистый способ привязки списка с использованием PDO, поэтому вы должны использовать цикл для создания строки, а затем выполнить запрос после цикла. Обратите внимание, что запрос, сформулированный таким образом, вряд ли даст вам какое-либо заметное улучшение производительности, но он действительно зависит от ваших конкретных обстоятельств, и вам просто нужно попробовать его.
Ответ №3
Вы можете сделать это намного проще, выполнив
$err_csv = implode(«‘,'»,$err); $sql = «SELECT FROM err_msgs WHERE id IN (‘$err_csv’)»; $result = $db -> query($sql); while ($row = $result -> fetch_array(MYSQLI_BOTH)) { echo «<li><span>».$row[1].»</span></li>»; }
Таким образом, вам не нужно отправлять запросы в базу данных.