Форум: "Базы";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];
ВнизПочему IF @@ERROR <> 0 не выполняется Найти похожие ветки
← →
Vedem © (2006-09-18 17:56) [0]Берем пример из 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
При выполнении этого же запроса из приложения имеем ExceptionUPDATE 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-18 17:59) [1]Vedem © (18.09.06 17:56)
Вопрос: как получить датасет не зависимо от наличия ошибки?
а какой датасет при update??
← →
vedem © (2006-09-18 18:05) [2]SELECT * FROM @t
в конце запроса....
← →
ANB © (2006-09-18 18:05) [3]
> stud © (18.09.06 17:59) [1]
Последним идет селект.
> Вопрос: как получить датасет не зависимо от наличия ошибки?
Это глюк АДО. Он не дожидается завершения пакета / ХП считая первую же ошибку исключением. Лезь к серверу напрямую (например, используя DBLIB). Впрочем, может спецы по АДО подскажут лучшее решение ?
← →
vedem © (2006-09-18 18:16) [4]Из-за пары запросов менять средсво доступа - как-то не прикольно.
Проверял это на BDE, ODBC - результат тот же.
При использовании компонет Zeos, при "прямом доступе" (собственно посредством DBLIB) - работает как надо.
Неужели в АДО нет средств настроить нужное поведение?
← →
Ega23 © (2006-09-18 18:19) [5]
Begin tran ....
.....
if @@ERROR<>0 Goto RollBackTran
.......
Commit Tran
Goto Fin
:RollBackTran
RollBack Tran ....
Goto Fin
:Fin
Select * from ....
Не проверял, но вроде принудительных Raiserror нету....
← →
vedem © (2006-09-18 18:25) [6]
declare @t table (msg varchar(255))
begin tran
UPDATE authors SET au_id = "172 32 1176"
WHERE au_id = "172-32-1176"
IF @@ERROR = 547 begin
Rollback tran
insert into @t values("A check constraint violation occurred")
end ELSE begin
commit tran
insert into @t values("Все ОК!")
end
SELECT * FROM @t
результат тот=же :(
← →
Ega23 © (2006-09-18 18:46) [7]Хрен его знает. А если как ХП оформить с ouput-параметром?
← →
stud © (2006-09-18 18:48) [8]так может проще проверку сделать на наличие /отсутствие нужной записи?
чтобы без исключений
← →
Fay © (2006-09-18 18:49) [9]set xact_abort off
← →
Ega23 © (2006-09-18 19:13) [10]
> так может проще проверку сделать на наличие /отсутствие
> нужной записи?
Ты посмотри внимательней, там check на constraint наложен
> set xact_abort off
Не поможет, один хрен raise идёт...
← →
Fay © (2006-09-18 19:36) [11]Тогда делаем финт с "лишним" recordset-ом
set nocount OFF
....
← →
Fay © (2006-09-18 19:37) [12]Не, нифига... 8))
← →
Ega23 © (2006-09-18 19:46) [13]
> Тогда делаем финт с "лишним" recordset-ом
> set nocount OFF
Это я уже проверил, не канает... :о)
Только сообщение на insert уберёт...
← →
Fay © (2006-09-18 19:54) [14]Примерно так
use pubs
go
set xact_abort off
declare @t table (msg varchar(255))
begin tran
UPDATE authors SET au_id = "172 32 1176"
WHERE au_id = "172-32-1176"
IF @@ERROR = 0 begin
commit tran
insert into @t values("OK!")
end ELSE begin
rollback tran
insert into @t values("Fuck!")
end
SELECT * FROM @t
← →
Ega23 © (2006-09-18 19:56) [15]
> Fay © (18.09.06 19:54) [14]
Ну и что? первым всё равно сообщение об ошибке в QA идёт, как ни крутись...
← →
Zz_ (2006-09-18 19:57) [16]>>Вопрос: как получить датасет не зависимо от наличия ошибки?
Посмотреть NextRecordset
← →
Fay © (2006-09-18 20:11) [17]2 Ega23 © (18.09.06 19:56) [15]
Проверял?
← →
Fay © (2006-09-18 20:16) [18]А на самом деле, надо не трахать себе мозги, а либо перейти на MSSQL 2005, либо юзать AnyDAC
← →
sniknik © (2006-09-18 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
← →
vedem © (2006-09-19 15:25) [20]
> Хрен его знает. А если как ХП оформить с 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
> <Цитата>
Последний мой вопрос, так и оставшийся без ответа...
← →
Ega23 © (2006-09-19 15:32) [21]
> интересная ветка по теме (и в конце ее еще ссылка)
Очень интересная ветка.
Но проблема так и не решена.
Кстати, вот ещё что в голову пришло: а если текстовую информацию об ошибке через Raiserror передавать?
← →
sniknik © (2006-09-19 15:43) [22]> Последний мой вопрос, так и оставшийся без ответа...
почему это без ответа? ясно же сказали, что так делать нельзя (в последней ссылке вроде), по крайней мере до 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;
← →
vedem © (2006-09-19 15:58) [23]
> Ega23 © (19.09.06 15:32) [21]
>
> > интересная ветка по теме (и в конце ее еще ссылка)
>
>
> Очень интересная ветка.
> Но проблема так и не решена.
> Кстати, вот ещё что в голову пришло: а если текстовую информацию
> об ошибке через Raiserror передавать?
Для того чтобы выдавать текстовую информацию через Raiserror в запросе, нужно хотябы проверить состояние @@ERROR. К сожалению при вызове запроса (или ХП) при ошибке прерывается выполнение запроса и вылезает Excetion. До выполнения IF @@ERROR.... дело не доходит... В Query Analizer, как было сказано в первом посте, имеем сообщение об ошибке и результирующий набор данных (или как в чистом примере в BOL - информационное сообщение)
← →
vedem © (2006-09-19 16:02) [24]2 sniknik
Мне нужно анализировать результат DataSet! В которм есть инфа о правильном результате или! о возникшей ошибке в процессе выполнения запроса.
Обращаю внимание, что в приведенном прмере в качестве набора данных возвращается только сообщение, в реали в датасете должна быть дополнительная инфа...
← →
vedem © (2006-09-19 16:03) [25]И к сожалению MSSQL сервер в задаче ограничен 2000 :(
← →
Ega23 © (2006-09-19 16:11) [26]
> ??? а это вообще разве нужно?
Не, тут другое.
Интересует сам академический вопрос:
Возможно ли при возникновении исключения отписать куда-то информацию об этом исключении на серверной стороне?
← →
sniknik © (2006-09-19 16:12) [27]кстати могу предложить "решение"
т.к. выполнение скрипта прерывается только для внешнего источника, сервер то его все одно доделывает (иначе не могли бы работать тригера где это нужно и т.д.), а о прерывании 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:12) [28]Кстати: а если триггер?
← →
Ega23 © (2006-09-19 16:14) [29]
> любуемся на результат (т.к. больше, кроме самолюбования,
> смысла в нем нет)
Это не изврат, это в 2 транзакции. Это как раз не интересно.
Кстати, дропнуть t надо...
← →
ANB © (2006-09-19 16:18) [30]
> До выполнения IF @@ERROR.... дело не доходит
Доходит. Но ты об этом не узнаешь, т.к. ADO прекращает связь с сервером. Я ж грил - при прямом обращении - все ОК.
> ясно же сказали, что так делать нельзя
Можно. Но не через ADO.
> Возможно ли при возникновении исключения отписать куда-то
> информацию об этом исключении на серверной стороне?
Без проблем. Напиши такой же код, только с сохранением ошибки в обычную таблицу, выполни его и убедись, что запись в таблицу ляжет.
Проблема в том, что нужно отследить, когда процедура закончилась.
Она же может долго выполняться.
← →
sniknik © (2006-09-19 16:20) [31]про одну, в ссылках явно говорят что не поддерживается в 2000м.
> Кстати, дропнуть t надо...
зачем? она же ему постоянно нужна, ну пусть и пользуется.
← →
stud © (2006-09-19 16:32) [32]vedem © (19.09.06 15:25) [20]
Мне нужно чтоб был возврат датасета, при RecordCount = 0 - считается что можно убить все записи по условию.
так в примере по идее при любом раскладе будет 1 запись!?
← →
Ega23 © (2006-09-19 16:34) [33]Есть идея.
Оформить сабжевый код в виде ХП, при возникновении ошибки добавлять инфу в таблицу ошибок, возвращать id этой ошибочной записи через return?
← →
stud © (2006-09-19 16:38) [34]Ega23 © (19.09.06 16:34) [33]
возвращать id этой ошибочной записи через return?
так вроде до ретурна адо не доживет и его не получит.
как вариант:
в предложенную постоянную таблицу писать сообщения. в качестве ид - использовать spid "писателя".
перед выполнением запроса удалять данных с этим же спидом, после окончания читать по этому спиду.
← →
ANB © (2006-09-19 17:09) [35]
> после окончания читать
здесь ключевое слово "после окончания". Взводит специальный флаг на сервере и опрашивать его в цикле - жутко криво.
Надо юзать ADO.NET. В нем нету этой проблемы. Или обращаться к серверу напрямую, без ADO, но это не очень просто.
← →
stud © (2006-09-19 17:19) [36]ANB © (19.09.06 17:09) [35]
Взводит специальный флаг на сервере и опрашивать его в цикле - жутко криво.
так а зачем а цикле?
читать сразу после выполнения операции.
но тут такой вопрос (с таблицами всякими), если получаем исключение в дельфи - можем его обработать как душе угодно,
зачем еще лезть в какието таблицы, чтобы прочитать что мы и так уже знаем???
← →
ANB © (2006-09-19 17:31) [37]
> читать сразу после выполнения операции.
А кто сказал, что инфа уже попала туда, куда надо ?
Пример :
update ....
...
много кода, который долго работает
update .... с ошибкой
...
много кода, который долго работает
update ....
много кода, который долго работает и есть принты
select
ну и как достать ошибку, результат последнего запроса и все принты ?
← →
stud © (2006-09-19 17:39) [38]ANB © (19.09.06 17:31) [37]
update ....
...
много кода, который долго работает
update .... с ошибкой
...
много кода, который долго работает
update ....
много кода, который долго работает и есть принты
а смысл последующих апдейтов, если не отработал первый?
тут после каждого апдейта нужно вставлять сообщение или менять его
← →
ANB © (2006-09-19 17:48) [39]
> а смысл последующих апдейтов, если не отработал первый?
Массовая обработка, например, при конвертации данных. update можешь заменить на insert. Я работал с такими хранимками. Причем менять их было нельзя, нужно было только вызывать и аккуратно складывать результаты.
← →
vedem © (2006-09-19 17:50) [40]
> Ega23 © (19.09.06 16:34) [33]
> Есть идея.
> Оформить сабжевый код в виде ХП, при возникновении ошибки
> добавлять инфу в таблицу ошибок, возвращать id этой ошибочной
> записи через return?
> sniknik © (19.09.06 16:12) [27]
> кстати могу предложить "решение"
Вы его проверяли?
Может я чего-то не догоняю, ноprocedure TForm3.Button3Click(Sender: TObject);
begin
//делаем таблицу
ADOCommand1.CommandText:=
"create table t (id int identity primary key, msg varchar(255))";
ADOCommand1.Execute;
//после выполняем подряд
ADOCommand1.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(""Все ОК!"")";
ADOCommand1.Execute;
ADODataSet1.CommandText:= "SELECT * FROM t";
ADODataSet1.Open;
//любуемся на результат (т.к. больше, кроме самолюбования, смысла в нем нет)
end;
при этом, свойства
ADOCommand1.Connection и
ADODataSet1.Connection
привязаны к ADOConnection1,
DataSource1.Dataset := ADODataSet1
DBGrid1.DataSource := DataSource1
НУ НЕТУ В ГРИДЕ ТОГО САМОГО ДАТАСЕТА!
> Ega23 © (19.09.06 16:34) [33]
> Есть идея.
> Оформить сабжевый код в виде ХП, при возникновении ошибки
> добавлять инфу в таблицу ошибок, возвращать id этой ошибочной
> записи через return?
Все замечательно! До недавнего времени я считал что все работает на ура... НО! при отработке ХП и при связке BDS+ADO+MSSQL (в D7+ZEOS+MSSQL у меня все работало...) и возникновении критической ошибки в теле ХП, ХП будет прервана в процессе выполнения и добавлять инфу в таблицу ошибок не представляется возможным! Собственно с чем и борьба и вопрос о том же, только поставленный в соответствии с примерами из BOL.
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.049 c