'SELECT FOUND_ROWS()'当结果为空时返回最小值1

问题描述:

当MSQL查询的结果为空时,我得到SELECT FOUND_ROWS()返回0'SELECT FOUND_ROWS()'当结果为空时返回最小值1

我有以下函数调用getBasket();

function viewBasket(){ 
    include('classes/Orders.php'); 

    $BasketID = 10; 
    $numRows=100; 
    $data = Orders::getBasket($numRows, $BasketID); 

    $results['basket'] = $data['results']; 
    $results['totalRows'] = $data['totalRows']; 

    require("templates/Basket.php"); 
}; 

getBasket()使用LEFT OUTER JOIN和场所到一个数组中,然后返回到viewBasket()建立所要求的结果。然后

public static function getBasket($numRows, $BasketID) { 
    $order="Name ASC"; 
    $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); 

    $sql = " 
SELECT SQL_CALC_FOUND_ROWS B.BasketID 
         , BP.ProductID 
         , BP.Quantity 
         , P.Name 
         , P.Price 
         , PT.NameType 
         FROM Basket B 
         LEFT 
         JOIN BasketProducts BP 
         ON B.BasketID = BP.BasketID 
         LEFT 
         JOIN Products P 
         ON BP.ProductID = P.ProductID 
         LEFT 
         JOIN ProductTypes PT 
         ON P.ProductTypeID = PT.ProductTypeID 
        WHERE B.BasketID = :BasketID 
        ORDER 
         BY $order 
        LIMIT :numRows; 
"; 

    $st = $conn->prepare($sql); 
    $st->bindValue(":numRows", $numRows, PDO::PARAM_INT); 
    $st->bindValue(":BasketID", $BasketID, PDO::PARAM_INT); 
    $st->execute(); 
    $list = array(); 

    while ($row = $st->fetch()) { 
     $basket = new Orders($row); 
    $list[] = $basket; 
    } 

    // Now get the total number of articles that matched the criteria 
    $sql = "SELECT FOUND_ROWS() AS totalRows"; 
    $totalRows = $conn->query($sql)->fetch(); 
    $conn = null; 
    return (array ("results" => $list, "totalRows" => $totalRows[0])); 
} 

我的HTML通过viewBasket();

<p>You have <?php echo $results['totalRows']?> item<?php echo ($results['totalRows'] != 1) ? 's' : '' ?> in your Basket</p> 

它的工作原理回声存储在$resultstotalRows值,但只是不会发送一个0,如果表是空的!
谢谢,亚当

得益于@VolkerK输入和@ Phate01我已经解决了这个问题。

如果从basketProducts返回的rowNULL,我清除了设置在basket表中的BasketID。即如果我已从与该用户关联的产品中删除最后的row,则从Basket中删除购物车会话。

$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); 
    $st = $conn->prepare ("select BasketID FROM basketProducts WHERE BasketID = :basketID"); 
    $st->bindValue(":basketID", $basketID, PDO::PARAM_INT); 
    $st->execute(); 

    $row = $st->fetch(); 
    $conn = null; 


    /** 
    * If the row returned from BasketProducts DOES NOT include the customers $basketID 
    * remove the row. 
    **/ 
    if($row == 0){ 
     $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); 
     $st = $conn->prepare ("DELETE FROM Basket WHERE BasketID = :basketID LIMIT 1"); 
     $st->bindValue(":basketID", $basketID, PDO::PARAM_INT); 
     $st->execute(); 

     $row = $st->fetch(); 
     $conn = null; 
    }else{ 
    //do nothing 
    } 

@VolkerK,我有联系的快速阅读和它的消失在我的头上。今晚会读,但你介意解释这可能对我有帮助吗?

+0

您可以使用外键将表之间的关系创建到数据库中。我无法完全解释它们,因为我不知道英语:D,但是您一定要学会使用它们,因为它们是SQL的基础知识 – Phate01 2015-02-05 15:37:21

if($results['totalRows'] > 0){ 
echo $results['TotalRows']; 
else{ 
echo '0'; 
} 

IF条件之前echo ING会做到这一点。

+0

感谢Mostafa,不幸的是它仍然显示'1'。在数组上运行'var_dump'会显示它包含值,但它们都是'NULL'; '阵列(1){ [0] => 对象(订单)#5(4){ [ “订单ID”] => NULL [ “客户id”] => NULL [ “OrderItemID”] => NULL [“ProductID”] => NULL } }' – atoms 2015-02-05 14:34:40

+0

然后将IF条件改为:if(!$ results ['TotalRows']){.......} ' – 2015-02-05 14:40:20

尝试投它:在Windows下:(MyISAM数据默认)

return (array ("results" => $list, "totalRows" => (int)$totalRows[0])); 
+0

Thanks @ Phate01,不幸的是它仍然显示1.在数组上运行'var_dump'显示它包含值,但它们都是'NULL';数组(1){[0] =>对象(Orders)#5(4){[“OrderID”] => NULL [“CustomerID”] => NULL [“OrderItemID”] => NULL [“ProductID”] => NULL}}' – atoms 2015-02-05 14:37:11

使用PHP-5.6.3和mysql-5.6,我不能重现该问题。

<?php 
define('DB_DSN', 'mysql:host=localhost;dbname=test;charset=utf8'); 
define('DB_USERNAME', 'localonly'); 
define('DB_PASSWORD', 'localonly'); 
var_dump(getBasket(10, 1)); 


function getBasket($numRows, $BasketID) { 
    $order="Name ASC"; 
    $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); 
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 
    setup($conn); // boilerplate: creating empty, temp tables 

    $sql = " 
     SELECT 
      SQL_CALC_FOUND_ROWS 
      Basket.BasketID, BasketProducts.ProductID, BasketProducts.Quantity, 
      Products.Name, Products.Price, ProductTypes.NameType 
     FROM 
      soBasket as Basket 
     LEFT OUTER JOIN 
      soBasketProducts as BasketProducts 
     ON 
      Basket.BasketID = BasketProducts.BasketID 
     LEFT OUTER JOIN 
      soProducts as Products 
     ON 
      BasketProducts.ProductID = Products.ProductID 
     LEFT OUTER JOIN 
      soProductTypes as ProductTypes 
     ON 
      Products.ProductTypeID = ProductTypes.ProductTypeID 
     WHERE 
      Basket.BasketID = :BasketID 
     ORDER BY 
      " . $order . " LIMIT :numRows 
    "; 

    $st = $conn->prepare($sql); 
    $st->bindValue(":numRows", $numRows, PDO::PARAM_INT); 
    $st->bindValue(":BasketID", $BasketID, PDO::PARAM_INT); 
    $st->execute(); 
    $list = array(); 

    while ($row = $st->fetch()) { 
     $basket = new Orders($row); 
      $list[] = $basket; 
    } 

    // Now get the total number of articles that matched the criteria 
    $sql = "SELECT FOUND_ROWS() AS totalRows"; 
    $totalRows = $conn->query($sql)->fetch(); 
    $conn = null; 
    return (array ("results" => $list, "totalRows" => $totalRows[0])); 
} 

class Orders { 
    public $_data; 
    public function __Construct(array $data) { 
     $this->_data = $data; 
    } 
} 


function setup($pdo) { 
    $queries = array(
     " 
      CREATE TEMPORARY TABLE soBasket (
       BasketID int 
      ) 
     ", 
     " 
      CREATE TEMPORARY TABLE soBasketProducts (
       ProductID int, 
       BasketID int, 
       Quantity int 
      ) 
     ", 
     "  
      CREATE TEMPORARY TABLE soProducts ( 
       ProductID int, 
       ProductTypeID int, 
       Price DECIMAL(10,2), 
       Name varchar(64) 
      ) 
     ", 
     "  
      CREATE TEMPORARY TABLE soProductTypes (
       ProductTypeID int , 
       NameType varchar(64) 
      ) 
     " 
    ); 
    foreach($queries as $q) { 
     $pdo->exec($q); 
    } 
} 

打印

array(2) { 
    'results' => 
    array(0) { 
    } 
    'totalRows' => 
    int(0) 
} 
+0

唯一的区别是两个setAttribute(),他没有设置 – Phate01 2015-02-05 14:43:46

+0

...并将temp-tables +别名替换为查询中的“原始”名称。但是,是的,这是我的观点:我无法复制它。所以,下一步可能是复制我的_self-contained_示例(+调整数据库参数)并检查结果。 – VolkerK 2015-02-05 14:44:33

+0

非常感谢您抽时间@VolkerK。你帮我改变了我的想法。我清除了篮子桌子上的BasketID,现在显示了它。我想现在如果我在product上创建一个函数,如果最后一个产品移除了,则从表中删除该行。不确定它是最好的解决方案,但认为它应该工作。完成后更新 – atoms 2015-02-05 14:53:24