【问题标题】:Fetching 2 different results from one stored procedure with PDO/PHP使用 PDO/PHP 从一个存储过程中获取 2 个不同的结果
【发布时间】:2018-12-06 16:58:38
【问题描述】:

使用 SQL Server 数据库构建 Symfony 4 API,我遇到了一个问题:我必须从一个存储过程中获取两个不同的结果。

第一个结果是一个数据数组,第二个只是一个 int 值。

我正在编写后端分页代码,这就是为什么我需要获取数据以及表格中的总行数。

这是我的存储过程:

ALTER PROCEDURE [SP IDENTIFIER] 

    (
        @Limit INT,
        @Offset INT

    )
AS
BEGIN

    SET NOCOUNT ON; 

    SELECT 
        COUNT(*) AS 'TOTAL'
    FROM DataBaseName

SELECT Field1, Field2, Field3
FROM DataBaseName
ORDER BY Field1 DESC
OFFSET @Offset ROWS
FETCH NEXT @Limit ROW ONLY


END

当我测试我的 API 时,它只返回我的第一个请求的结果(行数值)。

这是我的存储库方法:

  public function getDatas($limit, $offset)
  {
    $request = "EXEC SPName ?, ?";
    $answer = $this->_em->getConnection()->prepare($request);
    $answer->bindParam(1, $limit);
    $answer->bindParam(2, $offset);
    $answer->execute(); 


    return $answer->fetchAll();
  }

你知道有什么方法可以让 PDO 返回他从请求中得到的所有结果吗?也许在 fetch 选项中,或者以某种方式在 $answer 中执行 fetchAll 循环?

谢谢!

【问题讨论】:

    标签: php sql-server symfony pdo doctrine-orm


    【解决方案1】:

    MS SQL Server 支持可以返回多个结果集的存储过程。使用 PHP 和 PDO,您可以使用 PDOStatement::nextRowset() 方法检索这些结果集。重要的是要知道,即使您的存储过程中有输出参数,您也需要获取所有结果集以获取输出值。

    你可以试试这个:

    public function getDatas($limit, $offset)
    {
        $request = "EXEC SPName ?, ?";
        $answer = $this->_em->getConnection()->prepare($request);
        $answer->bindParam(1, $limit);
        $answer->bindParam(2, $offset);
        $answer->execute(); 
    
        do {
            // Fetch records with $answer->fetchAll();
        while ($answer->nextRowset());
    }
    

    【讨论】:

    • 感谢您的回答,我觉得很有趣!我不明白为什么,但这还不行,就像 Doctrine 不知道 nextRowset() 方法一样。 “试图调用类“Doctrine\DBAL\Statement”的名为“nextRowset”的未定义方法。” $answer 似乎不是真正的 PDO 实例...!
    【解决方案2】:

    您必须为存储过程指定 OUTPUT 参数,并且您的客户端代码必须能够接受输出。

    自从我使用 SQL Server 以来已经有几个月了,但我很确定我使用的版本不允许 ALTER 用于存储过程,而且我不再拥有 SQL Server,所以我无法测试我是什么交给你。

    另外,我认为您第一次“认为”该过程正在运行,但我猜该变量已经加载了有效值,因此它似乎设置正确。

    请尝试以下操作并修改您的客户端代码以接受@myCount:

    IF OBJECT_ID('SP IDENTIFIER', 'P') IS NOT NULL  
        DROP PROCEDURE [SP IDENTIFIER];  
    GO  
    
    CREATE PROCEDURE [SP IDENTIFIER]
              @Limit INT, @Offset INT, @myCount INT OUTPUT
    AS
    BEGIN
    
    SET NOCOUNT ON; 
    
    SELECT @myCount = COUNT(*)
    FROM DataBaseName
    
    SELECT Field1, Field2, Field3
    FROM DataBaseName
    ORDER BY Field1 DESC
    OFFSET @Offset ROWS
    FETCH NEXT @Limit ROW ONLY
    
    END
    

    【讨论】:

      【解决方案3】:

      我终于解决了我的问题。

      您必须使用 nextRowSet() 方法。您可以使用 Doctrine 在您的语句对象上调用它,但不再使用 Doctrine 2。 因此,您首先必须通过在 getConnection() 之后调用 getWrappedConnection() 方法来获取真正的 PDO 对象。

      在此之后,您只需循环输入数据并将它们堆叠到数组或对象中。

      这是我的解决方案:

        public function getPaginedSubscriptions($limit, $offset)
        {
          $sql = "EXEC DB_EXTRANET_V2.dbo.P_S_ORDER_00 ?, ?";
          $request = $this->_em->getConnection()->getWrappedConnection()->prepare($sql);
          $request->bindParam(1, $limit);
          $request->bindParam(2, $offset);
          $request->execute();
      
          do{
            $datas[] = $request->fetchAll();
          } while($request->nextRowSet());
      
          return $datas;
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-03
        相关资源
        最近更新 更多