Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как отловить ошибки в тригере [MSSQL]


Страницы:   1 2

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. Меня бы мой начальник прибил, если бы я так таблицы и поля называл...Читать невозможно.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо