![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как отловить ошибки в тригере [MSSQL]
Helen © (2007-04-05 10:45:00)Добрый день. У меня такая проблемс: есть приложение (написано не мной), которое пишет данные в MS SQL 2000. У таблице, в которую пишутся данные, создан тригер instead of insert. Данные пишутся-пишутся, а потом вдруг приложение выдает ошибку:
Ошибка записи в БД: Could not find prepared statement with handle -1.
И все, данные перестают писаться, перезапуск программы не помогает. После удаления и повторного создания тригера все опять работает, т.е. дело в тригере. Вопрос: как узнать, по какой причине он зависает?
MsGuns (2007-04-10 21:43:00) [1]Лена, я после того, как увидел твой триггер, неделю не спал !
КТО КОМПЕНСИРУЕТ МНЕ ПСИХОУРОН ?
;)
Jan1 (2007-04-10 19:45:00) [2]
> Курсор уже сделала, изменила логику тригера (в том числе
> избавилась от commit и rollback tran). Вобщем все работает
> как часы, еще и duration уменьшилась.
зачем курсор?
Helen (2007-04-10 10:34:00) [3]>ЮЮ © (09.04.07 03:31) [32]
Спасибо большое за совет про исключение, приму к сведению.
Курсор уже сделала, изменила логику тригера (в том числе избавилась от commit и rollback tran). Вобщем все работает как часы, еще и duration уменьшилась.
ЮЮ (2007-04-09 03:31:00) [4]> как (не используя rollback tran)?
Достаточно возбудить "серьезное" исключене. Например:
CREATE TRIGGER U_WorkLines_OnInsert ON dbo.U_WorkLines
INSTEAD OF INSERT
AS
BEGIN
DECLARE @Admin int
SELECT @Admin = dbo.UuaIsUserAdmin()
IF (@Admin <> 1) AND EXISTS(SELECT WorkTermActivity FROM inserted WHERE dbo.UuaWorkTermActivities_Id(WorkTermActivity) = 0) BEGIN
RAISERROR('#1: U_WorkLines_OnInsert: This record cannot be inserted', 16, 1)
RETURN
END
INSERT INTO U_WorkLines SELECT * FROM inserted
END
Если проверять надо "по записям", создать CURSOR по inserted и пробещать ао всему inserted по записям
ANB (2007-04-06 13:16:00) [5]on Table1 insteadof insert
У тебя триггер, заменяющийоперацию вставки. Просто не делай ничего - и всех делов то.
Helen (2007-04-06 12:54:00) [6]>В триггере так много косяков, что удивительно как он вообще работает.
Расскажите где косяки, а то всю жизнь и буду косячить
Helen (2007-04-06 12:53:00) [7]Из последних сообщений понимаю, что у меня неправильный подход к написанию тригеров. Так, ткнете носом, как надо делать?
Первый же вопрос: тригер for insert, в теле делаем проверку данных, данные нас не удовлтворяют, хотим отменить вставку, как (не используя rollback tran)?
ЮЮ (2007-04-06 12:42:00) [8]P/S/ Точне до [26] (не все скопировал в буфер)
> сервер автоматически начинает транзакцию
Также также он её автоматически и закончит. Не дело триггера ввязвываться а это тонкое дело.
Более того, cервер ли?
> В теле транзакции разработчик может реализовывать различные
> алгоритмы...
ANB (2007-04-06 12:42:00) [9]
> задам глупый вопрос, но... как это сделать?
Сделай хранимку с отдельной транзакцией, создай табличку и безусловно пиши в нее понятный тебе текст для трассировки - чего делалось.
В триггере так много косяков, что удивительно как он вообще работает.
ЗЫ. Кстати, оракл запрещает триггерам манипулировать транзакциями. Судя по этому коду - правильно делает.
ЗЫЫ. Хотя savepoint/rollback to - непонятно зачем запрещены.
ЮЮ (2007-04-06 12:35:00) [10]> алгоритмы...
C таким триггером сложновато будет выполнить такое:
BEGIN TRAN
INSERT INTO Table1 VALUES(...)
...
INSERT INTO Table1 VALUES(...)
...
IF ... COMMIT TRAN ELSE rollback TRAN
ибо решение о COMMIT/rollback принял за меня триггер.
Более того, триггер не позволит выполнить и пакетную вставку типа
INSERT into Table1
SELECT * FROM ... WHERE ...
ибо вставляеят только первую запись из пакета
...В конце концов, работа тригера сводится либо к фиксации, либо к откату транзакции.
Максимум, что может позволить триггер - вызвыть EXEPTION, но никак не подтверждать/откатывать транзакцию, которрую НЕ ОН СТАРТОВАЛ.
А все работать перестает из-за наличия записей в temp_CurrAvar и логике триггера. Он не работать перестает, а делает Rollback, ИМХО.
Helen (2007-04-06 12:26:00) [11]задам глупый вопрос, но... как это сделать?
ANB (2007-04-06 12:23:00) [12]
> Helen (06.04.07 12:20) [23]
Тады без вариантов придется логировать, чтобы выяснить, где триггер клинит.
Helen (2007-04-06 12:20:00) [13]Честно говоря, не понимаю, зачеи здесь RoollBack и Commit присутствуют, если BEGIN TRAN нет? Наверное, такой подход и называют "бизнес-логика расположена на сервере" :)
Когда пользователь начинает вставку данных, сервер автоматически начинает транзакцию, в которой и выполняется тригер. В теле транзакции разработчик может реализовывать различные алгоритмы...В конце концов, работа тригера сводится либо к фиксации, либо к откату транзакции.
ЮЮ (2007-04-06 12:11:00) [14]> Тут случайно выяснилась еще одна особенность: если создан
> тригер, то после запуска программы, она отказывается писать
> в SQL-сервер. Удаляю тригер, запись начинается. Создаю тригер,
> запись продолжается без проблем.
Очевидно причиной служат записи в temp_CurrAvar
По ним, очевидно, и предполагается выявлять ошибочные данные
При наличии записи вызывается rollback TRAN
Честно говоря, не понимаю, зачеи здесь RoollBack и Commit присутствуют, если BEGIN TRAN нет? Наверное, такой подход и называют "бизнес-логика расположена на сервере" :)
Jan1 (2007-04-06 12:10:00) [15]
> Записи приходят только по одной.
не факт. это важно если вы будет работать с данными как набором.
Helen (2007-04-06 12:05:00) [16]>А если создан триггер, но пустой ?
если создан пустой тригер, то после запуска программы записи пишутся нормально
Helen (2007-04-06 12:00:00) [17]>Вообще то inserted - набор данных и строк в нем может быть несколько. А триггер обрабатывает только одну
Записи приходят только по одной.
ANB (2007-04-06 11:56:00) [18]
> то после запуска программы, она отказывается писать в SQL-
> сервер.
А если создан триггер, но пустой ?
> SELECT @DateIns=ins.DATTIME, @Region=ins.REGION, @AtsNum=ins.
> ATSNUM, @Adr1=ins.ADR1, @Adr2=ins.ADR2, @Adr3=ins.ADR3,
> @Err=ERCODE, @ErType=ins.ERTYPE
> FROM inserted as ins
Вообще то inserted - набор данных и строк в нем может быть несколько. А триггер обрабатывает только одну.
Helen (2007-04-06 11:43:00) [19]>4. Меня бы мой начальник прибил, если бы я так таблицы и поля называл...Читать невозможно.
Я бы тоже прибила того, кто создавал эти таблицы
Тут случайно выяснилась еще одна особенность: если создан тригер, то после запуска программы, она отказывается писать в SQL-сервер. Удаляю тригер, запись начинается. Создаю тригер, запись продолжается без проблем.
2. Перед COMMIT TRAN и rollback TRAN делать проверку на наличие активной транзакции @@trancount
Если есть активная транзакция, то что?
Jan1 (2007-04-06 11:13:00) [20]1. в начало триггера - set nocount on
2. Перед COMMIT TRAN и rollback TRAN делать проверку на наличие активной транзакции @@trancount
3.
> SET @Date=SUBSTRING(@DateIns, 7, 2)+'.'+SUBSTRING(@DateIns,
> 4, 2)+'.'+SUBSTRING(@DateIns, 1, 2)+' '+SUBSTRING(@DateIns,
> 10, 8)
вот тут я не понял - зачем такой изврат?
4. Меня бы мой начальник прибил, если бы я так таблицы и поля называл...Читать невозможно.