Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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

При выполнении этого же запроса из приложения имеем 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-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.042 c
5-1143640846
Gaval
2006-03-29 18:00
2006.11.19
fastreport


15-1162375283
Карелин Артем
2006-11-01 13:01
2006.11.19
Зарплаты/жилье в Подольске. Что почем?


2-1162301177
LiberlX
2006-10-31 16:26
2006.11.19
Закрытие модального окна


15-1162279588
Карелин Артем
2006-10-31 10:26
2006.11.19
Кто за удаленным компьютером сидит?


15-1161803262
vidiv
2006-10-25 23:07
2006.11.19
Про то же переименовывание...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский