SQL Server 2005、SQL Driver for PHP v1.1 吃掉了“触发器中注定的事务”错误
简短版本: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_SEVERITY
和ERROR_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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我过去也遇到过这个问题,这不仅仅是 PHP 的问题。由于某种原因,我无法在任何文档中找到并找到,您需要将非系统管理员的严重性指定为最大值 18。试试这个:
注意:我只是在上面的代码中将严重性从 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:
note: I have only changed the severity from 17 to 18 in the code above.
严重级别 17 表示“资源不足”。尝试使用 16 代替。 (错误消息严重级别)
来自规范参考:SQL 2000 中的错误处理 – 背景
另请参阅: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
Also see: Error Handling in SQL 2005 and Later
您是否尝试过 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.