SQL Server 2005, драйвер SQL для PHP v1.1 ест ошибки "транзакция обречена на триггер"
Короткая версия: драйвер sqlsrv (оболочка Native Client) "съедает" ошибки нарушения ограничений, генерируемые триггерами; Драйвер mssql (оболочкаntwdlib) сообщает о них просто отлично.
- SQL Server 2005
- PHP 5.3.1
- Драйвер SQL Server для 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;
Бег 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
блок. извините за путаницу.
edit 2010-03-03: просто чтобы вы, ребята, не слишком привязывались к уровню серьезности в RAISERROR
, реальный код пытается отбросить пойманную ошибку с ERROR_NUMBER
, ERROR_SEVERITY
а также ERROR_STATE
,
Кроме того, обратите внимание на задаваемые вопросы:
Вопрос: что случилось? Вы используете этот драйвер PHP? Используете ли вы представления с триггерами DML? Водитель сообщает об обреченных транзакциях?
пожалуйста, не пытайтесь получить награду, не имея непосредственного опыта в ситуации, описанной здесь.
3 ответа
Вы пробовали серьезность 10 или ниже? Кстати, мне всегда везло с драйвером SQL и PHP. В 2005 и 2008 годах. Если это не сработает, попробуйте другой сервер, чтобы убедиться, что это не ваша конфигурация сервера.
Я сталкивался с этой проблемой в прошлом, это не просто сложность 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 в коде выше.
Уровень серьезности 17 означает "Недостаточно ресурсов". Попробуйте использовать 16 вместо. ( Уровни серьезности сообщений об ошибках)
Из канонической справки: Обработка ошибок в SQL 2000 - фон
Уровень серьезности - число от 0 до 25. История с историей заключается в том, что если уровень серьезности находится в диапазоне 0-10, сообщение является информационным или предупреждением, а не ошибкой. Ошибки, возникающие в результате ошибок программирования в коде SQL, имеют уровень серьезности в диапазоне 11-16. Уровни серьезности 17-25 указывают на проблемы с ресурсами, проблемы с оборудованием или внутренние проблемы в SQL Server, а если уровень серьезности равен 20 или выше, соединение прерывается. Для долгой истории, посмотрите раздел Больше об Уровнях Серьезности для некоторых интересных лакомых кусочков. Для системных сообщений вы можете найти уровень серьезности в
master..sysmessages
, но для некоторых сообщений SQL Server использует другой уровень серьезности, чем вsysmessages
,
Также см.: Обработка ошибок в SQL 2005 и новее