简体   繁体   English

foreach循环中的MySQL查询

[英]MySQL query within foreach loop

I want to show all text messages from db where id=$e ( $err is an array). 我想显示所有来自db id=$e$err是一个数组)的文本消息。
Inserted the query into the foreach loop, it works well but it does extra work (does query for every value of array). 将查询插入到foreach循环中,虽然效果很好,但是却做了额外的工作(查询数组的每个值)。
Is there any other way to do it (i mean extract query from foreach loop)? 还有其他方法(我的意思是从foreach循环中提取查询)吗?
My code looks like this. 我的代码如下所示。

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>";
}

It is much more efficient to do this with implode() because it will only result in one database query. 使用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";
}

检查SQL IN子句

Firstly, a bit of a lecture: embedding strings directly into your queries is going to cause you trouble at some point (SQL injection related trouble to be precise), try to avoid this if possible. 首先,做一些演讲:将字符串直接嵌入查询中会在某种程度上引起麻烦(准确地说是与SQL注入相关的麻烦),请尽可能避免这种情况。 Personally, I use the PDO PHP library which allows you to bind parameters instead of building up a string. 就个人而言,我使用PDO PHP库,该库允许您绑定参数而不是构建字符串。

With regard to your question, I'm not sure I have understood. 关于您的问题,我不确定我是否理解。 You say that it does extra work, do you mean that it returns the correct results but in an inefficient way? 您说它做了很多工作,是否意味着它以低效的方式返回了正确的结果? If so then this too can be addressed with PDO. 如果是这样,那么这也可以通过PDO解决。 Here's the idea. 这是主意。

Step 1: Prepare your statement, putting a placeholder where you currently have '$e' Step 2: Loop through $err, in the body of the loop you will set the place holder to be the current value of $e 步骤1:准备语句,将占位符放在您当前拥有“ $ e”的位置步骤2:循环遍历$ err,在循环体中,将占位符设置为$ e的当前值

By doing this you not only address the SQL injection issue, you can potentially avoid the overhead of having to parse and optimise the query each time it is executed (although bear in mind that this may not be a significant overhead in your specific case). 通过这样做,您不仅可以解决SQL注入问题,还可以避免每次执行查询时都必须解析和优化查询的开销(尽管请记住,在您的特定情况下,这可能不是很大的开销)。

Some actual code would look as follows: 一些实际的代码如下所示:

// 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>";
}

One final point, if you want to simply execute the query once, instead of executing it inside the loop, this is possible but again, may not yield any performance improvement. 最后一点,如果您只想简单地执行一次查询,而不是在循环内执行查询,这是可能的,但是再次重申,可能不会带来任何性能改进。 This could be achieved using the IN syntax. 这可以使用IN语法来实现。 For example, if I'm interested in records with id in the set {5, 7, 21, 4, 76, 9}, I would do: 例如,如果我对ID为集合{5,7,21,4,4,76,9}中的ID的记录感兴趣,我会这样做:

SELECT * from err_msgs WHERE id IN (5, 7, 21, 4, 76, 9) SELECT * from err_msgs WHERE ID IN(5,7,21,4,76,9)

I don't think there's a clean way to bind a list using PDO so you would use the loop to build up the string and then execute the query after the loop. 我认为没有一种使用PDO绑定列表的干净方法,因此您可以使用循环来构建字符串,然后在循环后执行查询。 Note that a query formulated in this way is unlikely to give you any noticable performance improvment but it really does depend on your specific circumstances and you'll just have to try it out. 请注意,以这种方式制定的查询不太可能给您带来明显的性能改进,但实际上确实取决于您的特定情况,您只需要尝试一下即可。

You can do this much simpler by doing 您可以通过执行以下操作来简化此操作

$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>";
}

That way you don't have to keep sending queries to the database. 这样,您就不必继续向数据库发送查询。

Links: 链接:
http://php.net/manual/en/function.implode.php http://php.net/manual/zh/function.implode.php

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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