-4

短版:sqlsrv 驱动程序(本机客户端包装器)“吃掉”触发器生成的约束违规错误;mssql 驱动程序(ntwdlib包装器)报告它们就好了。

  • SQL 服务器 2005
  • PHP 5.3.1
  • 适用于 PHP 1.1 的 SQL Server 驱动程序

夹具:

CREATE TABLE t (
  t INT NOT NULL PRIMARY KEY
);
CREATE VIEW v AS
  SELECT CURRENT_TIMESTAMP AS v
;
CREATE TRIGGER vt ON v
INSTEAD OF INSERT
AS BEGIN
BEGIN TRY
  INSERT INTO t SELECT 1 UNION ALL SELECT 1;
END TRY
BEGIN CATCH
  RAISERROR('fubar!', 17, 0);
END CATCH
END;

INSERT INTO v SELECT CURRENT_TIMESTAMP;通过 Management Studio运行收益率

(0 row(s) affected)
Msg 3616, Level 16, State 1, Line 1
Transaction doomed in trigger. Batch has been aborted.
Msg 50000, Level 17, State 0, Procedure vt, Line 8
fubar!

通过sqlsrv_query运行时没有报错:

$conn = sqlsrv_connect(...);
var_dump(sqlsrv_query($conn, 'INSERT INTO v SELECT CURRENT_TIMESTAMP'));
var_dump(sqlsrv_errors());

输出

resource(11) of type (SQL Server Statement)
NULL

应用程序(似乎)没有办法发现触发器失败,除非通过后面的语句失败。

问题:怎么了? 你使用这个 PHP 驱动程序吗?您是否使用带有 DML 触发器的视图?司机是否报告注定的交易

编辑 2010-02-17 11:50:问题的第一个版本错误地声称我看到了带有触发器的工件,其中包含一个简单的INSERT. 好吧,它只发生在违反约束的 DML 位于TRY块内时。对困惑感到抱歉。

编辑2010-03-03:只是为了让你们不要太依赖 中的严重性级别RAISERROR,真正的代码会尝试使用 和 重新抛出捕获ERROR_NUMBERERROR_SEVERITY错误ERROR_STATE

此外,请注意提出的问题:

问题:怎么了? 你使用这个 PHP 驱动程序吗?您是否使用带有 DML 触发器的视图?司机是否报告注定的交易

如果没有亲身经历过这里描述的情况,请不要试图收获赏金。

4

3 回答 3

0

您是否尝试过 10 或以下的严重性?顺便说一句,我对 SQL 驱动程序和 PHP 一直很幸运。在 2005 年和 2008 年。如果这不起作用,请尝试使用不同的服务器以确保它不是您的服务器配置。

于 2010-03-03T12:18:11.530 回答
0

严重级别 17 表示“资源不足”。尝试改用 16。(错误消息严重级别

来自规范参考:SQL 2000 中的错误处理 – 背景

严重性级别——一个从 0 到 25 的数字。故事是,如果严重性级别在 0-10 范围内,则消息是信息或警告,而不是错误。SQL 代码中的编程错误导致的错误具有 11-16 范围内的严重级别。严重级别 17-25 表示 SQL Server 中的资源问题、硬件问题或内部问题,如果严重级别为 20 或更高,则终止连接。长篇大论,请参阅更多关于严重级别的部分,了解一些有趣的花絮。对于系统消息,您可以在 中找到严重级别master..sysmessages,但对于某些消息,SQL Server 使用的严重级别与 中的不同sysmessages

另请参阅:SQL 2005 及更高版本中的错误处理

于 2010-03-03T03:57:33.720 回答
0

我过去也遇到过这个问题,不只是 PHP 这么复杂。出于某种原因,我无法在任何文档中找出并找到,您需要将严重性指定为非系统管理员的最大值为 18。尝试这个:

CREATE TABLE t (
  t INT NOT NULL PRIMARY KEY
);
CREATE VIEW v AS
  SELECT CURRENT_TIMESTAMP AS v
;
CREATE TRIGGER vt ON v
INSTEAD OF INSERT
AS BEGIN
BEGIN TRY
  INSERT INTO t SELECT 1 UNION ALL SELECT 1;
END TRY
BEGIN CATCH
  RAISERROR('fubar!', 18, 0);
END CATCH
END;

注意:我只在上面的代码中将严重性从 17 更改为 18。

于 2010-03-03T03:44:51.517 回答