使用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循环?
谢谢!
答案 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;
}