使用PDO / PHP

时间:2018-12-06 16:58:38

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

使用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循环?

谢谢!

3 个答案:

答案 0 :(得分:2)

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());
}

答案 1 :(得分:1)

您必须为存储过程指定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

答案 2 :(得分:1)

我终于解决了我的问题。

您必须使用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;
  }
相关问题