SQL Server 2005、SQL Driver for PHP v1.1 吃掉了“触发器中注定的事务”错误

发布于 2024-08-21 08:33:21 字数 1654 浏览 6 评论 0原文

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

  • SQL Server 2005
  • PHP 5.3.1
  • SQL Server Driver for PHP 1.1

固定装置:

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;

通过 Management Studio 运行 INSERT INTO v SELECT CURRENT_TIMESTAMP; 会产生

(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_NUMBER、ERROR_SEVERITYERROR_STATE

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

问题:What's up? 你使用这个 PHP 驱动程序吗?您是否将视图与 DML 触发器一起使用?司机是否报告注定的交易

在没有对此处描述的情况有第一手经验的情况下,请不要尝试获取赏金。

short version: the sqlsrv driver (Native Client wrapper) "eats" constraint violation errors generated from triggers; the mssql driver (ntwdlib wrapper) reports them just fine.

  • SQL Server 2005
  • PHP 5.3.1
  • SQL Server Driver for PHP 1.1

fixture:

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;

running INSERT INTO v SELECT CURRENT_TIMESTAMP; through Management Studio yields

(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!

no error is reported when I run it through sqlsrv_query:

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

outputs

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

the application has (it seems) no way to find out that the trigger failed other than through later statements failing.

The question: What's up? Do you use this PHP driver? Do you use views with DML triggers? Does the driver report doomed transactions?

edit 2010-02-17 11:50: the first version of the question incorrectly claimed that I saw the artifact with the trigger containing a simple INSERT. well, it only happens when the constraint-violating DML is inside a TRY block. sorry for the confusion.

edit 2010-03-03: just so that you guys don't get too attached to the severity level in RAISERROR, the real code tries to rethrow the caught error with ERROR_NUMBER, ERROR_SEVERITY and ERROR_STATE.

furthermore, please pay attention to the questions asked:

The question: What's up? Do you use this PHP driver? Do you use views with DML triggers? Does the driver report doomed transactions?

please don't try to harvest the bounty without having firsthand experience with the situation described here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞旧 2024-08-28 08:33:21

我过去也遇到过这个问题,这不仅仅是 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。

I have run into this problem in the past, it is not just PHP that intricacy. For some reason, that I can't figure out and find in any documentation, you need the specify the severity to it's max of 18 for non-sysadmins. Try this:

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;

note: I have only changed the severity from 17 to 18 in the code above.

月亮邮递员 2024-08-28 08:33:21

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

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

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

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

A Severity Level of 17 indicates "Insufficient Resources". Try using 16 instead. (Error Message Severity Levels)

From the canonical reference: Error Handling in SQL 2000 – a Background

Severity level – a number from 0 to
25. The stort story is that if the severity level is in the range 0-10,
the message is informational or a
warning, and not an error. Errors
resulting from programming errors in
your SQL code have a severity level in
the range 11-16. Severity levels 17-25
indicate resource problems, hardware
problems or internal problems in SQL
Server, and if the severity is 20 or
higher, the connection is terminated.
For the long story, see the section
More on Severity Levels for some
interesting tidbits. For system
messages you can find the severity
level in master..sysmessages, but for
some messages SQL Server employs a
different severity level than what's
in sysmessages.

Also see: Error Handling in SQL 2005 and Later

月下客 2024-08-28 08:33:21

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

Have you tried a severity of 10 or below? By the way I have always had good luck with the SQL Driver and PHP. On 2005 and 2008. If this doesn't work, try a different server to make sure it isn't your server config.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文