如何在 PHP/MYSQL 中将两个 mysql 查询作为一个执行?

Posted

技术标签:

【中文标题】如何在 PHP/MYSQL 中将两个 mysql 查询作为一个执行?【英文标题】:How to execute two mysql queries as one in PHP/MYSQL? 【发布时间】:2010-10-22 14:13:57 【问题描述】:

我有两个查询,如下:

SELECT SQL_CALC_FOUND_ROWS Id, Name FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
SELECT FOUND_ROWS();

我想一次性执行这两个查询。

$result = mysql_query($query);

然后告诉我如何处理单独设置的每个表。实际上在 ASP.NET 中,我们使用数据集来处理两个查询

ds.Tables[0];
ds.Tables[1]; .. etc

如何使用 php/MYSQL 做同样的事情?

【问题讨论】:

这是可能的(参见***.com/a/28984274/632951)使用CLIENT_MULTI_STATEMENTS标志。 【参考方案1】:

像这样:

$result1 = mysql_query($query1);
$result2 = mysql_query($query2);

// do something with the 2 result sets...

if ($result1)
    mysql_free_result($result1);

if ($result2)
    mysql_free_result($result2);

【讨论】:

他不想避免两次执行mysql_query吗? 是的,我想避免两次 mysql 查询。在@Jon Benedicto 的回答中,他正在执行两个查询。 :( 我刚刚发布了另一个答案,展示了如何使用 MySQLi 一次性执行两个查询。【参考方案2】:

它在 PHP 网站上说 multiple queries are NOT permitted(编辑:这仅适用于 mysql 扩展。mysqli 和 PDO 允许多个查询) .所以你不能在 PHP 中做到这一点,但是,为什么你不能在另一个 mysql_query 调用中执行该查询(如 Jon 的示例)?如果您使用相同的连接,它仍然应该给您正确的结果。此外,mysql_num_rows 也可能有所帮助。

【讨论】:

这仅适用于 mysql 扩展。 mysqli 和 PDO 允许多个查询。【参考方案3】:

你不能使用SQL_CALC_FOUND_ROWS

通过 FOUND_ROWS() 可用的行数是暂时的,并且不打算在 SELECT SQL_CALC_FOUND_ROWS 语句之后的语句之后可用。

正如有人在您之前的问题中指出的那样,使用 SQL_CALC_FOUND_ROWS 通常比仅计数要慢。

也许你最好把它当作子查询来做:

SELECT 
 (select count(*) from my_table WHERE Name LIKE '%prashant%') 
as total_rows,
Id, Name FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;

【讨论】:

SQL_CALC_FOUND_ROWS 较慢,但在dev.mysql.com/doc/refman/5.0/en/… 链接我发现“但是,这比没有限制再次运行查询要快,因为不需要将结果集发送到客户端。” ?? 但不是在这种情况下,因为查询不能使用索引。 SQL_CALC_FOUND_ROWS 将导致一次表扫描,而您的子查询将导致两次,因此速度要慢得多。另外,您忘记在 total_rows 后面加一个逗号。 是的,好吧,您不会在没有限制的情况下再次运行查询。您正在运行一个计数(*),它发送一行。真的,Emil H 有一个很好的观点——它是对可疑值的微优化。要么运行两个查询,要么如果你绝对必须这样做,就像我解释的那样作为子查询来做。 (Emil H,感谢您指出缺少逗号。)【参考方案4】:

更新:显然可以通过将标志传递给mysql_connect()。见Executing multiple SQL queries in one statement with PHP 不过,任何当前的读者都应该避免使用mysql_-class 函数,而更喜欢 PDO。

在 PHP 中使用常规的 mysql-api 无法做到这一点。只需执行两个查询。第二个将如此之快,以至于无关紧要。这是微优化的典型例子。不用担心。

为了记录,可以使用 mysqli 和 mysqli_multi_query-function 来完成。

【讨论】:

我主要关心性能,如果我们两次访问数据库,我认为性能会下降。 如果您不相信,请做一个基准测试。执行 SELECT FOUND_ROWS() 查询并检索结果所需的时间可以忽略不计。你已经有了连接,结果集非常小(只有一个整数)。 顺便说一句,如果您担心性能,您应该花时间尝试摆脱 LIKE '%prashant%' 语句。这可能是一个真正的性能问题。根据经验:大多数 php 应用程序的瓶颈根本不在 php 中,而在数据库中。如果您想花时间优化您的应用程序,请花时间检查您的索引并解释您的查询。 我的第一个查询是插入,第二个是获取第一个的 ID。运行到 php 执行是没有问题的,因为记录插入到表中的速度非常快。【参考方案5】:

如果您不想执行两次查询,则必须使用 MySQLi 扩展:

if (mysqli_multi_query($link, $query))

    $result1 = mysqli_store_result($link);
    $result2 = null;

    if (mysqli_more_results($link))
    
        mysqli_next_result($link);
        $result2 = mysqli_store_result($link);
    

    // do something with both result sets.

    if ($result1)
        mysqli_free_result($result1);

    if ($result2)
        mysqli_free_result($result2);

【讨论】:

【参考方案6】:

你必须使用 MySQLi,下面的代码运行良好

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) 
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();


$query  = "SELECT CURRENT_USER();";
$query .= "SELECT Name FROM City ORDER BY ID LIMIT 20, 5";

/* execute multi query */
if ($mysqli->multi_query($query)) 
    do 
        /* store first result set */
        if ($result = $mysqli->store_result()) 
            while ($row = $result->fetch_row()) 
                printf("%s\n", $row[0]);
            
            $result->free();
        
        /* print divider */
        if ($mysqli->more_results()) 
            printf("-----------------\n");
        
     while ($mysqli->next_result());


/* close connection */
$mysqli->close();
?>

【讨论】:

【参考方案7】:

正如其他人所回答的,mysqli API 可以使用 msyqli_multi_query() 函数执行多查询。

不管怎样,PDO 默认支持多查询,您可以迭代多个查询的多个结果集:

$stmt = $dbh->prepare("
    select sql_calc_found_rows * from foo limit 1 ; 
    select found_rows()");
$stmt->execute();
do 
  while ($row = $stmt->fetch()) 
    print_r($row);
  
 while ($stmt->nextRowset());

但是,出于安全原因,多查询被广泛认为是一个坏主意。如果您对如何构造查询字符串不小心,您实际上可以得到classic "Little Bobby Tables" XKCD cartoon 中显示的确切类型的 SQL 注入漏洞。使用限制您进行单一查询的 API 时,这是不可能发生的。

【讨论】:

【参考方案8】:

是的,它可以不使用 MySQLi 扩展。

只需在mysql_connect 的第五个参数中使用CLIENT_MULTI_STATEMENTS

更多信息请参考Husni's post下方的cmets。

【讨论】:

以上是关于如何在 PHP/MYSQL 中将两个 mysql 查询作为一个执行?的主要内容,如果未能解决你的问题,请参考以下文章

试图在php MYSQL中将数据从一个表插入另一个表[关闭]

如何使用 datepicker、ajax、php、mysql 在两个日期之间生成报告?

php+mysql模糊查询功能

如何使用会话ID从php mysql中的两个或多个表中获取值

如何将带有前缀列的表连接到 PHP MySQL 或 Laravel 中的另外两个表

php,mysql时间差问题