Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Горячая тема (более 10 ответов) Вопрос по ПолучитьОписаниеОшибки() (число прочтений - 5846 )
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Вопрос по ПолучитьОписаниеОшибки()
22. Декабря 2006 :: 12:36
Печать  
Скорее вопрос не по самой функции ПолучитьОписаниеОшибки(), а как получить текстовку сообщения об ошибке, полученной внутри хранимой процедуры, вызываемой с помощью 1с++.ODBCRecordSet.

В БД есть некоторая таблица MyTable с полем text_param: varchar(100) not null.

Если я выполняю следующее:
Код
Выбрать все
sSQL = "insert into MyTable(text_param) vlaues(null)";
Попытка
  RS.ВыполнитьСкалярный(sSQL);
Исключение
КонецПопытки
сОшибка = RS.ПолучитьОписаниеОшибки(); 



то естесственно в cОшибка храниться что-то типа такого:
"State 23000, native 515, message [Microsoft][ODBC SQL Server Driver][SQL Server]Cannot insert the value NULL into column 'text_param', table 'AMS.dbo.MyTable'; column does not allow nulls. INSERT fails.",

т.е. я вижу, что не выолнен insert в таблицу MyTable в поле text_param.

То же самое вижу в сОшибка даже если оператор insert офромлен в виде такой функции:
Код
Выбрать все
CREATE PROCEDURE testproc(
  @text_param varchar(100)
)
AS
BEGIN
  insert into TestTable(test) values (@text_param)
END,
а sSQL = "exec testproc null" 



НО, если я добавлю в хранимую процедуру оператор возврата, например:
Код
Выбрать все
CREATE PROCEDURE testproc(
  @text_param varchar(100)
)
AS
BEGIN
  insert into TestTable(test) values (@text_param)
  return 1;
END, 


или объявлю еще один дополнительный параметр функции как output,
то сОшибка возвращает уже другую ошибку: "State HY007, native 0, message [Microsoft][ODBC SQL Server Driver]Associated statement is not prepared".

Как мне узнать, что реально в процедуре произошла ошибка вставки записи, т.е. то сообщение, которое генерит сервер для оператора insert?
Дело в том, что в реальной процедуре куча операторов модификации данных, и как мне узнать, где именно ошибка непонятно. Независимо от того где она происходит я получаю одно и то же сообщение об ошибке "Associated statement is not prepared".

Подскажите куда копать.
  
Наверх
 
IP записан
 
DmitrO
1c++ power user
Отсутствует


ex developer

Сообщений: 579
Местоположение: г. Киров
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #1 - 22. Декабря 2006 :: 13:33
Печать  
ODBCRecordset возвращает описание только первой ошибки, на самом деле их может вернуться несколько.
  
Наверх
ICQ  
IP записан
 
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #2 - 23. Декабря 2006 :: 02:40
Печать  
Т.е. несколько ошибок получить не удастся? Как же узанть какая ошибка произошла внутри хранимой процедуры, если в ней куча оперторов?
  
Наверх
 
IP записан
 
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #3 - 23. Декабря 2006 :: 02:55
Печать  
Дело в том, что внутри процеды помимо исключений, которые могут вызвать стандартные операторы модификации данных, я генерю еще собственные исключения с сообщениями, которые в свою очередь хочу показать клиенту. Пытаюсь в эту процедуру заложить всю бизнес логику.
  
Наверх
 
IP записан
 
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #4 - 23. Декабря 2006 :: 02:59
Печать  
Появилась еще такая мысль.

В случае ошибки внутри процедуры писать ее сообщение в дополнительную таблицу, а оттуда читать по коду возвращаемому процедурой.

Ну тут тоже вопрос возникает. Свои сообщения (которые генерю с помощб raiseerror) записать нет проблем, а как в хранимой процедуре получить текстовку последнего сообщения об ошибке по модификации данных. Максимум, что получислось сделать - это получить шаблон ошибки из sysmessages. А как получить текст  с уже подставленными в шаблон данными не знаю.
  
Наверх
 
IP записан
 
DmitrO
1c++ power user
Отсутствует


ex developer

Сообщений: 579
Местоположение: г. Киров
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #5 - 23. Декабря 2006 :: 07:39
Печать  
sour писал(а) 23. Декабря 2006 :: 02:40:
Т.е. несколько ошибок получить не удастся? Как же узанть какая ошибка произошла внутри хранимой процедуры, если в ней куча оперторов?

А в чем проблема? Если она первая, ее вернет ПолучитьОписаниеОшибки.

Цитата:
Появилась еще такая мысль.

В случае ошибки внутри процедуры писать ее сообщение в дополнительную таблицу, а оттуда читать по коду возвращаемому процедурой.

Ну тут тоже вопрос возникает. Свои сообщения (которые генерю с помощб raiseerror) записать нет проблем, а как в хранимой процедуре получить текстовку последнего сообщения об ошибке по модификации данных. Максимум, что получислось сделать - это получить шаблон ошибки из sysmessages. А как получить текст  с уже подставленными в шаблон данными не знаю.

Звучит банально, но в BOL:Error Handling все описано.   Озадачен
  
Наверх
ICQ  
IP записан
 
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #6 - 23. Декабря 2006 :: 08:10
Печать  
Проблема в том, что, если хранимая процедура возвращает параметр (т.е. есть return или output параметр), то ПолучитьОписаниеОшибки ВСЕГДА возвращает "Associated statement is not prepared", а не "Cannot insert the value NULL into column 'text_param', table 'AMS.dbo.MyTable'; column does not allow nulls. INSERT fails", например, который происходит внутри процедуры.
  
Наверх
 
IP записан
 
DmitrO
1c++ power user
Отсутствует


ex developer

Сообщений: 579
Местоположение: г. Киров
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #7 - 23. Декабря 2006 :: 10:06
Печать  
А как вызывается процедура? Код покажи.
  
Наверх
ICQ  
IP записан
 
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #8 - 23. Декабря 2006 :: 11:29
Печать  
Любой из вариантов приводит к описанному поведению
1.
Код
Выбрать все
sSQL = "exec testproc null"; 


2.
Код
Выбрать все
sSQL = "
  |declare @id int
  |exec @id = testproc null
  |select @id"; 



Непосредственный вызов RS.ВыполнитьСкалярный(sSQL) или так RS.ВыполнитьИнструкцию(sSQL)
  
Наверх
 
IP записан
 
DmitrO
1c++ power user
Отсутствует


ex developer

Сообщений: 579
Местоположение: г. Киров
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #9 - 24. Декабря 2006 :: 07:07
Печать  
Партизанишь опять..
Тебе драйвер английским языком говорит, "я не могу подготовить запрос", если он так говорит, то запрос сервером не выполнялся.
Наверно не правильно ты ее вызываешь, раз он запрос подготовить не может. В приведенном SQL коде вобщем-то ошибок нет.
Чтобы определелить в чем косяк надо видеть полный код вызова, и определение процедуры.

И не надо стесняться приводить свой код.. Знайте, что бы вы не написали, этот форум и не такое видал Улыбка. Не надо партизанить, вы можете ненамерено утаить некоторые детали, и полного понимания картины в ответе не увидите, сами же и запутаетесь.
  
Наверх
ICQ  
IP записан
 
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #10 - 25. Декабря 2006 :: 01:58
Печать  
Полный таблицы в БД:
Код
Выбрать все
CREATE TABLE [dbo].[testtable] (
  [test] varchar(100) COLLATE Cyrillic_General_CI_AS NOT NULL
)
ON [PRIMARY]
GO 



Полный код хранимой процедуры в БД:

Код
Выбрать все
CREATE PROCEDURE testproc(
  @text_param varchar(100)
)
AS
BEGIN
  insert into TestTable(test) values (@text_param)
  return 1
END 



В обработке вызываю процедуру Сформировать.

Код
Выбрать все
Процедура Сформировать()
  RS = СоздатьОбъект("ODBCRecordSet");
    
	sSQL = "
	|exec testproc null
	|";

	Попытка
		RS.ВыполнитьСкалярный(sSQL);
	Исключение
	КонецПопытки;

	Сообщить(RS.ПолучитьОписаниеОшибки()); // Тут: State HY007, native 0, message [Microsoft][ODBC SQL Server Driver]Associated statement is not prepared
КонецПроцедуры 




Но только стоит в хранимой процедуре убарть оператор return, т.е. процедура такая:
Код
Выбрать все
CREATE PROCEDURE testproc(
  @text_param varchar(100)
)
AS
BEGIN
  insert into TestTable(test) values (@text_param)
END 



и в обработке ничего не меняя вызвать процедуру сформировать, то RS.ПолучитьОписаниеОшибки возвращает уже State 23000, native 515, message [Microsoft][ODBC SQL Server Driver][SQL Server]Cannot insert the value NULL into column 'test', table 'AMS.dbo.testtable'; column does not allow nulls. INSERT fails.

Вот такое странное поведение.
  
Наверх
 
IP записан
 
DmitrO
1c++ power user
Отсутствует


ex developer

Сообщений: 579
Местоположение: г. Киров
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #11 - 25. Декабря 2006 :: 09:43
Печать  
Да действительно, поведение сервера, а скорее всего даже драйвера ODBC весьма странное.
Если с сервера приходит только один результат, эта ситуация (невозможность содержания в колонке значений Null) возвращается как ошибка (SQL_ERROR) (State 23000).
Однако если, приходит несколько результатов или процедура имеет output параметры, или в процедуре явно указывался Return Code, то эта же ситуация приводит к удачному выполнению с сообщением (SQL_SUCCESS_WITH_INFO), с тем же самым сообщением (State 23000).
ODBCRecordset написан так, что игнорирует сообщения при удачном выполнении. И пытается определить количество колонок в первом возвращенном результате, при этом получет State HY007. Что в свою очередь неожидалось ODBCRcordset-ом. Т.к. в обычной ситуации, если бы insert прошел ошибки бы небыло, а определилось количество колонок=0, это означает что был DML запрос и его результат - количество измененных строк определялось бы отдельно, последующими вызовами ODBC.
Вобщем, такое поведение сбивает ODBCRecordset.

Вообще, ODBCRcordset не проработан на выполнение нескольких инструкций в одном запросе, соответственно, обработка ошибок при этом тоже страдает.

Надо также понимать еще особенность работы сервера: если передано несколько инструкций или вызываемая  ХП содержит несколько инструкций (не важно, важно что выполняется несколько), и в результате каких-то инструкций происходят ошибки, сервер никогда не перывает работу батча, он пытается выполнить все переданные инструкции, т.е. в MSSQL 2000 нет исключений, об этом в SQL соде должен заботиться сам программист.
  
Наверх
ICQ  
IP записан
 
sour
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 11
Зарегистрирован: 30. Ноября 2006
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #12 - 25. Декабря 2006 :: 09:50
Печать  
Короче говоря, через ODBCRecordSet не удастся получить ошибку внутри хранимой процедуры при все вышеперечисленных условиях? Как понять, что произошло на клтенте не удастся?
  
Наверх
 
IP записан
 
DmitrO
1c++ power user
Отсутствует


ex developer

Сообщений: 579
Местоположение: г. Киров
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Вопрос по ПолучитьОписаниеОшибки()
Ответ #13 - 25. Декабря 2006 :: 10:19
Печать  
Не совсем так.
Например такая процедура:
Код
Выбрать все
CREATE PROCEDURE testproc(
  @text_param varchar(100)
)
AS
BEGIN
  set nocount on
  insert into TestTable(test) values (@text_param)
  return 189
END
 


и вызвать таким кодом:
Код
Выбрать все
	Рез = Запрос.ВыполнитьСкалярный("
	|declare @i int
	|exec @i = testproc 'Привет'
	|select @i
	|");
	Сообщить(Рез);
 


мы вполне нормально получаем 189
Но если передать в процедуру null будет State HY007.
Т.е. в принципе Return Code получить можно, но если будет ошибка в инструкции - драйвер ведет себя не понятно. Имхо надо разбираться с драйвером и/или MS.
В тоже время если убрать в запросе select @i - то получаем State 23000. (???)
  
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать