【问题标题】:MSSQL procedure does not complete from PHPMSSQL 过程未从 PHP 完成
【发布时间】:2015-01-04 11:20:18
【问题描述】:

PHP: 5.4.20 Windows
服务器:Microsoft SQL Server 2012

我遇到了一个问题,当从 PHP 脚本调用时,以下存储过程没有完整运行(但它确实运行,没有返回错误):

CREATE PROCEDURE main_procedure (@uid int)
AS  
BEGIN
  DECLARE @NOW DATETIME
  SET @NOW = getDate()

  DELETE FROM metrics WHERE uid = @uid AND timestamp < @NOW
  EXEC update_metric_a @uid, @NOW
  EXEC update_metric_b @uid, @NOW
  EXEC update_metric_c @uid, @NOW
  EXEC update_metric_d @uid, @NOW
  EXEC update_metric_e @uid, @NOW
  EXEC update_metric_f @uid, @NOW
  EXEC update_metric_g @uid, @NOW
  EXEC update_metric_h @uid, @NOW
  EXEC update_metric_i @uid, @NOW
END

该函数通过以下方式调用:“EXEC main_procedure 1234”,其中 1234 是传递给各个 update_metric 函数的用户 ID。每个单独的 update_metric_n 过程都会为每个指标添加一条记录,然后解析过去 12 个月以使用逐月细分填充该行。

从 Microsoft SQL Management Studio 调用时,该过程正确执行所有步骤。

当从 PHP 调用时,它会运行除最后一个程序之外的所有程序。

其他的都运行正常,但由于某种原因最后一个没有运行。重新排序程序可确认问题不是上一个程序中的错误,因为它在移至列表顶部时运行良好。

这是我执行该过程的 PHP:

$conn = new PDO("sqlsrv:Server=######; Database=#####;", $user, $pass);
$conn->prepare("EXEC main_procedure ?");
$conn->execute(array("1234"));

任何想法为什么这会在第八个过程之后停止,但只有在通过 PHP 执行时?

【问题讨论】:

  • PHP 不知道服务器内部发生了什么。它不会告诉 mssql “嘿,这个存储的过程?除了 metric_i 行之外的所有事情”。 PHP 不可能知道存储过程中发生了什么。它只是通过字符串EXEC ... ? 发送并等待响应。
  • 这就是我的想法,但始终如一,最后一个过程在通过 PHP 调用时无法运行,但在直接从 MSSMS 执行时运行完美。这让我很困惑。我希望具有 SQL 或 PHP/PDO 内部知识的人知道可能导致这种情况的原因是什么?奇怪的是,它不会返回任何错误。它只是省略了其中一个过程。
  • 您在 php 中使用的凭据是否与您在 mssms 中的凭据相同?如果您尝试将单个 exec 与 php 分开运行会发生什么?也许最后一个有一些不同的权限,不允许php正在使用的帐户访问。
  • 最初不是,但我将脚本更改为以我在 MSSMS 中使用的同一用户身份运行,并且它做了同样的事情。我正在考虑的一件事是重写各个过程以使用直接 SQL 而不是游标。不知道这是否会有所不同。

标签: php sql-server stored-procedures pdo


【解决方案1】:

试试这个方法,差别不大,但值得一试。

不确定这是否是一个错字,但execute() 方法仅适用于由prepare() 返回的语句对象。

try {
    $conn= new PDO("sqlsrv:Server=######; Database=#####;", $user, $pass);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $stmt = $conn->prepare("EXEC dbo.main_procedure @uid = ?");
    $stmt->execute(array("1234"));
} catch (PDOException $e) {
    echo 'PDO failed: ' . $e->getMessage();
}

【讨论】:

  • 你是对的。我省略了 $stmt = .... 它应该读起来像你的代码。我进行了此更改并看到一条错误消息,指出“查询的活动结果不包含任何字段”。查找这个,似乎 SET NOCOUNT ON 应该解决这个问题。就我而言,它没有解决错误,但该过程确实完整运行。 (我想知道我是否在所有子过程中也需要它)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 2021-04-03
  • 1970-01-01
  • 2014-03-31
  • 2018-01-25
相关资源
最近更新 更多