![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Почему IF @@ERROR <> 0 не выполняется [MSSQL]
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
sniknik (2006-09-20 02:57:00) [1]> 2 sniknik:
> А при чем тут слип? и без него все работет..
не знаю при чем. у меня его не было.
но это ответ на
ANB © (19.09.06 18:44) [49]
> Слипнебось воткнул :) Так нечестно.
и у тебя в коде он > sleep(5000); тоже присутствует
> ну тут вы немного парите...
в смысле? я вообщето не банщик, парить не умею. и что должны показать дальнейшие цитаты?
незнаю как ты это все понял, но это не решение, это бред не зря я его (слово решение) и в кавычках писал и предупреждения выделял, причем бред не код, он правильный, а сама идея ловить и игнорировать ексепт на сервере чтобы передать его на клиента куда он и так передается если бы не словили и не проигнорировали... во всяком случае до тех пор пока не будет соответствующих механизмов в sql сервере (которые опять таки не для того чтобы подменять полное сообщение своим урезанным...).
> При чем тут автор?
вот, при том тут автор, был нормальный код над плохим идеологически решением (нормальное показано в [22], которое по невнятным причинам не подходит... но типа, "верьте так надо. иначе не получится")
и вот тут этот автор еще и свои изменения кода делает... вместо оптимизации (проверки в скрипте на существование/переход на временные/вынос ставшего ненужным куска за блок/х.з. чего еще) просто берет и закрывает пустым try except... только потому что у меня он был упомянут? но заметь была не рекомендация, не совет, а просто факт - "не закрытое вылетает". (не знает как по другому? а раз упомянули... не думаем, делаем так)
т.е. с одной стороны неграмотность в элементарных вопросах, с другой претензия на проблему "мирового маштаба", в чем я лично сомневаюсь. просто думаю если человек неспособен даже запрос грамотно составить то уж продумать схему взаимодействий сервера с клиентом и подавно. (если не знаеш, что и как действует, то как этим рулить?)
вот и аналогия про "супер гонщика".
а вот реальный совет
>> Будем дальше работать над едим вопросом, но уже в фонововм режиме.
> лучше бы думал и работал над задачей, чем над проблемами неудачной реализации.
игнорируется, а ведь это самый лучший совет во всей ветке....
Vedem (2006-09-20 01:43:00) [2]2 sniknik:
А при чем тут слип? и без него все работет..
> вообще впечатление такое, что просто сами себе трудности
> выдумываете... жизнь скучна без них?
> проблемы "мирового маштаба", которые ну никак по другому
> не решить только извратом, вернее так говорит автор... и
> тот же автор не может перевести(опознать) ошибку, о том
> что таблица уже создана... да это все одно что супер гонщик
> вдруг заявил "а чего это она не заводится? пишет бензина
> нет. чего ей надо?"... смешно.
ну тут вы немного парите...
Цитирую:
sniknik © (19.09.06 16:12) [27]
кстати могу предложить "решение"
т.к. выполнение скрипта прерывается только для внешнего источника, сервер то его все одно доделывает (иначе не могли бы работать тригера где это нужно и т.д.), а о прерывании QA явно пишет. то решение очевидно... или нет? ;о)
попросту сделай свою таблицу с сообщениями постоянной, ну и читай ее в другом блоке. типа
ВНИМАНИЕ, ЭТО ИЗВРАТ, ДЕЛАТЬ ТАК НЕ РЕКОМЕНДУЮПри чем тут автор?
>
> и тот же автор не может перевести(опознать) ошибку, о том
> что таблица уже создана...
sniknik © (19.09.06 18:16) [46]
> Вы его проверяли?
> ...
> НУ НЕТУ В ГРИДЕ ТОГО САМОГО ДАТАСЕТА!
специально для вас
http://img239.imageshack.us/img239/6469/lammh7.jpg
код взят as is из [40], без единого символа изменений. (кстати надеюсь понимаеш что создание таблицы (первый exec) при нажатии второй раз даст ошибку и код на ней прервется т.к. не защищен никакими try except?
оба, пока писал, да картинку делал...
> кроме Exception
> There is already an object named 't' in the database.
> к сожалению больше ничего нет....
вот и оно ;о))
Ну вы опередили хвала вам! :)
Еще раз всем спасибо.
sniknik (2006-09-19 20:44:00) [3]кстати
> ADOCommand1.CommandText:=
> 'create table t (msg varchar(255))';
> try
> ADOCommand1.Execute;
> except
> end;
зная что она есть... надеюсь это не рабочий проект? (и еше больше надеюсь что мне с ним столкнуться не придется ;о)))
вообще впечатление такое, что просто сами себе трудности выдумываете... жизнь скучна без них?
проблемы "мирового маштаба", которые ну никак по другому не решить только извратом, вернее так говорит автор... и тот же автор не может перевести(опознать) ошибку, о том что таблица уже создана... да это все одно что супер гонщик вдруг заявил "а чего это она не заводится? пишет бензина нет. чего ей надо?"... смешно.
sniknik (2006-09-19 20:36:00) [4]ANB © (19.09.06 18:44) [49]
> Слип небось воткнул :) Так нечестно.
повторяю, все рабочее как есть, и было с первого и единственного моего примера... на картинке видно кстати, специально так "снял" чтобы видно было.
слип и ничего более, кроме показаного в первый же раз, не нужно.
vedem © (19.09.06 18:58) [50]
> но к сожалению, при
> declare @t table (msg varchar(255))
> ....
> SELECT * FROM @t
> проблема осталась...
а подумать? или на @t свет клином сошолся? а ведь есть же еще и #t
> Будем дальше работать над едим вопросом, но уже в фонововм режиме.
лучше бы думал и работал над задачей, чем над проблемами неудачной реализации.
vedem © (19.09.06 19:09) [52]
> А как же работает эта сволочь под название Query Analyzer....
например выполняя пакет покомандно (подозреваю что и dblib ранее упоминавшийся также работает (если работает. не проверял)). и который кстати пишет, что на этой конкретной строке батч "терминирован"
vedem (2006-09-19 19:09:00) [5]А как же работает эта сволочь под название Query Analyzer....
ANB (2006-09-19 19:03:00) [6]
> declare @t table (msg varchar(255))
> ....
> SELECT * FROM @t
Это потому что паузу в одну команду не воткнешь :) А в разных - @t уже не существует
vedem (2006-09-19 18:58:00) [7]Спасибо sniknik
Что-то получилось, но не честно... :)
procedure TForm3.Button3Click(Sender: TObject);
begin
// Проверим коннект к нашей любимой базе....
ADOQuery1.SQL.Text := 'select * from authors';
ADOQuery1.Open;
// Тормознем до нажатия оки...
ShowMessage('Жду кнопку... Датасет увидел....');
DataSource1.DataSet := ADODataSet1;
//делаем таблицу
ADOCommand1.CommandText:=
'create table t (msg varchar(255))';
try
ADOCommand1.Execute;
except
end;
//после выполняем подряд
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(''Все ОК!'')';
try
ADOCommand1.Execute;
sleep(5000);
except
on E: Exception do ShowMessage(E.Message);
end;
ADODataSet1.CommandText:= 'SELECT * FROM t';
ADODataSet1.Open;
//любуемся на результат (т.к. больше, кроме самолюбования, смысла в нем нет)
end;
но к сожалению, при
declare @t table (msg varchar(255))
....
SELECT * FROM @t
проблема осталась...
Обход окольными путями того что работает в QA не есть гуд...
Будем дальше работать над едим вопросом, но уже в фонововм режиме.
Еще раз спасибо sniknik и всем кто принял участие.
ANB (2006-09-19 18:44:00) [8]
> sniknik © (19.09.06 18:16) [46]
Слип небось воткнул :) Так нечестно.
sniknik (2006-09-19 18:18:00) [9]> очевидно это код нужно оформить в виде хп на сервере
ничего не надо, все рабчее как есть. (ну кроме минимума знаний... ;о))
vedem (2006-09-19 18:16:00) [10]
> stud © (19.09.06 18:12) [44]
> vedem © (19.09.06 18:09) [43]
> '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(''Все ОК!'')';
> очевидно это код нужно оформить в виде хп на сервере, в
> противном случае до иферор дело не дойдет
Есть и ХП... Результат тот-же.... Собственно вопрос и возник после выявления что ХП не проработала до конца.
sniknik (2006-09-19 18:16:00) [11]> Вы его проверяли?
> ...
> НУ НЕТУ В ГРИДЕ ТОГО САМОГО ДАТАСЕТА!
специально для вас
http://img239.imageshack.us/img239/6469/lammh7.jpg
код взят as is из [40], без единого символа изменений. (кстати надеюсь понимаеш что создание таблицы (первый exec) при нажатии второйраз даст ошибку и код на ней прервется т.к. не защищен никакими try except?
оба, пока писал, да картинку делал...
> кроме Exception
> There is already an object named 't' in the database.
> к сожалению больше ничего нет....
вот и оно ;о))
vedem (2006-09-19 18:15:00) [12]Я не кипячусь, но хотелось бы рародится... Тем более что во-первых я доказываю что через ZEOS это работает (см DBLIB) а во-вторых при работе через ADO это черевато не выполнением до конца ХП, в следствии чего могут быть проблемы с транзакциями, открытыми в ХП, обработанными там же, но по Exception прерванными в процессе выполнения.
На транзакции проверял, вроде при обломе происходит Rollback, но на http://sql.ruмелькали темы по поводу проверки на @@trancount
stud (2006-09-19 18:12:00) [13]vedem © (19.09.06 18:09) [43]
'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(''Все ОК!'')';
очевидно это код нужно оформить в виде хп на сервере, в противном случае до иферор дело не дойдет
vedem (2006-09-19 18:09:00) [14]И слип не помогает :(
procedure TForm3.Button3Click(Sender: TObject);
begin
// Проверим коннект к нашей любимой базе....
ADOQuery1.SQL.Text := 'select * from authors';
ADOQuery1.Open;
// Тормознем до нажатия оки...
ShowMessage('Жду кнопку... Датасет увидел....');
DataSource1.DataSet := ADODataSet1;
//делаем таблицу
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;
sleep(5000);
ADODataSet1.CommandText:= 'SELECT * FROM t';
ADODataSet1.Open;
//любуемся на результат (т.к. больше, кроме самолюбования, смысла в нем нет)
end;
кроме Exception
There is already an object named 't' in the database.
к сожалению больше ничего нет....
vedem (2006-09-19 17:57:00) [15]Сейчас попробую сварганить ХП примерно с тем результатом...
ANB (2006-09-19 17:57:00) [16]
> ADOCommand1.Execute;
Вот сюда sleep(5000) поставь и все заработает :)
> ADODataSet1.CommandText:= 'SELECT * FROM t';
> ADODataSet1.Open;
> Все замечательно!
Не кипятись. Года 2 назад у меня вылезла эта проблема на боевом проекте. Здесь любители связки ADO+MS SQL, сказали мне, что я дурак и не умею готовить ADO. Проблема решилась только через DBLIB. :)
Кстати, BOL не описывает работу ADO. В нем грамотно разжевана работа сервера. В ADO.NET, повторюсь, проблема исправлена. Проверено лично.
vedem (2006-09-19 17:50:00) [17]
> 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.
ANB (2006-09-19 17:48:00) [18]
> а смысл последующих апдейтов, если не отработал первый?
Массовая обработка, например, при конвертации данных. update можешь заменить на insert. Я работал с такими хранимками. Причем менять их было нельзя, нужно было только вызывать и аккуратно складывать результаты.
stud (2006-09-19 17:39:00) [19]ANB © (19.09.06 17:31) [37]
update ....
...
много кода, который долго работает
update .... с ошибкой
...
много кода, который долго работает
update ....
много кода, который долго работает и есть принты
а смысл последующих апдейтов, если не отработал первый?
тут после каждого апдейта нужно вставлять сообщение или менять его
ANB (2006-09-19 17:31:00) [20]
> читать сразу после выполнения операции.
А кто сказал, что инфа уже попала туда, куда надо ?
Пример :
update ....
...
много кода, который долго работает
update .... с ошибкой
...
много кода, который долго работает
update ....
много кода, который долго работает и есть принты
select
ну и как достать ошибку, результат последнего запроса и все принты ?