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

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

Почему IF @@ERROR <> 0 не выполняется [MSSQL]


Страницы:   1 2 3

Vedem ©   (2006-09-18 17:56:00) 

Берем пример из BOL и немного его модифицируем
Examples
A. Use @@ERROR to detect a specific error
This example uses @@ERROR to check for a check constraint violation (error #547) in an UPDATE statement.

use pubs
go

declare @t table (msg varchar(255))

UPDATE authors SET au_id = '172 32 1176'
WHERE au_id = '172-32-1176'

IF @@ERROR = 547
  insert into @t values('A check constraint violation occurred')
ELSE
  insert into @t values('Все ОК!')

SELECT * FROM @t


Задача в следующем:
Нужно вернуть сообщения (и о нормальной работе и о возникших ошибках) в датасете.

При выполнении запроса в QA получаем 2 вкладки Grids и Messages

Messages:

Server: Msg 547, Level 16, State 1, Line 1
UPDATE statement conflicted with COLUMN CHECK constraint 'CK__authors__au_id__77BFCB91'.
The conflict occurred in database 'pubs', table 'authors', column 'au_id'.
The statement has been terminated.

(1 row(s) affected)

(1 row(s) affected)

Grids:

A check constraint violation occurred

При выполнении этого же запроса из приложения имеем Exception

UPDATE statement conflicted with COLUMN CHECK constraint 'CK__authors__au_id__77BFCB91'.
The conflict occurred in database 'pubs', table 'authors', column 'au_id'.
и отсутствие датасета.

То же самое произходит при выполнении ХП, при наличии ошибки выполнение ХП прерывается.

Вопрос: как получить датасет не зависимо от наличия ошибки?

BDS2006 + ADO + MSSQL 2000


stud   (2006-09-19 17:19:00) [21]

ANB ©   (19.09.06 17:09) [35]
Взводит специальный флаг на сервере и опрашивать его в цикле - жутко криво.

так а зачем а цикле?
читать сразу после выполнения операции.
но тут такой вопрос (с таблицами всякими), если получаем исключение в дельфи - можем его обработать как душе угодно,
зачем еще лезть в какието таблицы, чтобы прочитать что мы и так уже знаем???


ANB   (2006-09-19 17:09:00) [22]


> после окончания читать

здесь ключевое слово "после окончания". Взводит специальный флаг на сервере и опрашивать его в цикле - жутко криво.
Надо юзать ADO.NET. В нем нету этой проблемы. Или обращаться к серверу напрямую, без ADO, но это не очень просто.


stud   (2006-09-19 16:38:00) [23]

Ega23 ©   (19.09.06 16:34) [33]
возвращать id этой ошибочной записи через return?

так вроде до ретурна адо не доживет и его не получит.
как вариант:
в предложенную постоянную таблицу писать сообщения. в качестве ид - использовать spid "писателя".
перед выполнением запроса удалять данных с этим же спидом, после окончания читать по этому спиду.


Ega23   (2006-09-19 16:34:00) [24]

Есть идея.
Оформить сабжевый код в виде ХП, при возникновении ошибки добавлять инфу в таблицу ошибок, возвращать id этой ошибочной записи через return?


stud   (2006-09-19 16:32:00) [25]

vedem ©   (19.09.06 15:25) [20]
Мне нужно чтоб был возврат датасета, при RecordCount = 0 - считается что можно убить все записи по условию.

так в примере по идее при любом раскладе будет 1 запись!?


sniknik   (2006-09-19 16:20:00) [26]

про одну, в ссылках явно говорят что не поддерживается в 2000м.

> Кстати, дропнуть t надо...
зачем? она же ему постоянно нужна, ну пусть и пользуется.


ANB   (2006-09-19 16:18:00) [27]


> До выполнения IF @@ERROR.... дело не доходит

Доходит. Но ты об этом не узнаешь, т.к. ADO прекращает связь с сервером. Я ж грил - при прямом обращении - все ОК.

> ясно же сказали, что так делать нельзя

Можно. Но не через ADO.

> Возможно ли при возникновении исключения отписать куда-то
> информацию об этом исключении на серверной стороне?

Без проблем. Напиши такой же код, только с сохранением ошибки в обычную таблицу, выполни его и убедись, что запись в таблицу ляжет.
Проблема в том, что нужно отследить, когда процедура закончилась.
Она же может долго выполняться.


Ega23   (2006-09-19 16:14:00) [28]


> любуемся на результат (т.к. больше, кроме самолюбования,
>  смысла в нем нет)


Это не изврат, это в 2 транзакции. Это как раз не интересно.
Кстати, дропнуть t надо...


Ega23   (2006-09-19 16:12:00) [29]

Кстати: а если триггер?


sniknik   (2006-09-19 16:12:00) [30]

кстати могу предложить "решение"

т.к. выполнение скрипта прерывается только для внешнего источника, сервер то его все одно доделывает (иначе не могли бы работать тригера где это нужно и т.д.), а о прерывании QA явно пишет. то решение очевидно... или нет? ;о)
попросту сделай свою таблицу с сообщениями постоянной, ну и читай ее в другом блоке. типа
ВНИМАНИЕ, ЭТО ИЗВРАТ, ДЕЛАТЬ ТАК НЕ РЕКОМЕНДУЮ

делаем таблицу

ADOCommand.CommandText:=
 'create table t (id int identity primary key, msg varchar(255))';
ADOCommand.Execute

после выполняем подряд

ADOCommand.CommandText:=
 'SET NOCOUNT OFF '+
 'DELETE FROM T '+
 'UPDATE authors SET au_id = ''172 32 1176'' '+
 'WHERE au_id = ''172-32-1176'' '+
 'IF @@ERROR = 547 '+
 '  insert into t values(''A check constraint violation occurred'')  '+
 'ELSE  '+
 '  insert into t values(''Все ОК!'')';
ADOCommand.Execute

ADODataSet.CommandText:= 'SELECT * FROM t';
ADODataSet.Open;

любуемся на результат (т.к. больше, кроме самолюбования, смысла в нем нет)


Ega23   (2006-09-19 16:11:00) [31]


> ??? а это вообще разве нужно?


Не, тут другое.
Интересует сам академический вопрос:
Возможно ли при возникновении исключения отписать куда-то информацию об этом исключении на сервернойстороне?


vedem   (2006-09-19 16:03:00) [32]

И к сожалению MSSQL сервер в задаче ограничен 2000 :(


vedem   (2006-09-19 16:02:00) [33]

2 sniknik
Мне нужно анализировать результат DataSet! В которм есть инфа о правильном результате или! о возникшей ошибке в процессе выполнения запроса.
Обращаю внимание, что в приведенном прмере в качестве набора данных возвращается только сообщение, в реали в датасете должна быть дополнительная инфа...


vedem   (2006-09-19 15:58:00) [34]


> Ega23 ©   (19.09.06 15:32) [21]
>
> > интересная ветка по теме (и в конце ее еще ссылка)
>
>
> Очень интересная ветка.
> Но проблема так и не решена.
> Кстати, вот ещё что в голову пришло: а если текстовую информацию
> об ошибке через Raiserror передавать?

Для того чтобы выдавать текстовую информацию через Raiserror в запросе, нужно хотябы проверить состояние @@ERROR. К сожалению при вызове запроса (или ХП) при ошибке прерывается выполнение запроса и вылезает Excetion. До выполнения IF @@ERROR.... дело не доходит... В Query Analizer, как было сказано в первом посте, имеем сообщение об ошибке и результирующий набор данных (или как в чистом примере в BOL - информационное сообщение)


sniknik   (2006-09-19 15:43:00) [35]

> Последний мой вопрос, так и оставшийся без ответа...
почему это без ответа? ясно же сказали, что так делать нельзя (в последней ссылке вроде), по крайней мере до 2005 в котором появилась обработка исключений аналогичная дельфевской try except.

> Но проблема так и не решена.
??? а это вообще разве нужно?
try
 ADOCommand.CommandText:=
   'UPDATE authors SET au_id = ''172 32 1176'' '
   'WHERE au_id = ''172-32-1176''';
 ADOCommand.Execute;

 sInfo:= 'Все ОК!';
except
 on E: Exception do  
   sInfo:= 'A check constraint violation occurred. With message : ' + E.Message;
end;


Ega23   (2006-09-19 15:32:00) [36]


> интересная ветка по теме (и в конце ее еще ссылка)


Очень интересная ветка.
Но проблема так и не решена.
Кстати, вот ещё что в голову пришло: а если текстовую информацию об ошибке через Raiserror передавать?


vedem   (2006-09-19 15:25:00) [37]


> Хрен его знает. А если как ХП оформить с ouput-параметром?

результат тот же :(

> Fay ©   (18.09.06 18:49) [9]
> set xact_abort off

добровольно-принудительно выполняю перед запросом
 ADOConnection1.Execute('SET XACT_ABORT OFF');



> stud ©   (18.09.06 18:48) [8]
> так может проще проверку сделать на наличие /отсутствие
> нужной записи?
> чтобы без исключений

Задача на предварительную проверку возможности удаления записей, пример приведен для проверки и подобное есть в BOL
Мне нужно чтоб был возврат датасета, при RecordCount = 0 - считается что можно убить все записи по условию.
Но не будем вглублятся в нужный мне алгоритм, есть пример BOL, и он не работает... :(

> Zz_   (18.09.06 19:57) [16]
> >>Вопрос: как получить датасет не зависимо от наличия ошибки?
>
>
> Посмотреть NextRecordset

Попробую...


> sniknik ©   (18.09.06 20:45) [19]
> интересная ветка по теме (и в конце ее еще ссылка)
> http://www.sql.ru/forum/actualthread.aspx?bid=1&tid=277446&pg=1&hl=error+%ef%f0%ee%e4%ee%eb%e6%e8%f2%fc+%e2%fb%ef%ee%eb%ed%e5%ed%e8%e5
>

Последний мой вопрос, так и оставшийся без ответа...


sniknik   (2006-09-18 20:45:00) [38]

интересная ветка по теме (и в конце ее еще ссылка)
http://www.sql.ru/forum/actualthread.aspx?bid=1&tid=277446&pg=1&hl=error+%ef%f0%ee%e4%ee%eb%e6%e8%f2%fc+%e2%fb%ef%ee%eb%ed%e5%ed%e8%e5


Fay   (2006-09-18 20:16:00) [39]

А на самом деле, надо не трахать себе мозги, а либо перейти на MSSQL 2005, либо юзать AnyDAC


Fay   (2006-09-18 20:11:00) [40]

2 Ega23 ©   (18.09.06 19:56) [15]
Проверял?


Страницы:   1 2 3

Наверх

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