Как отловить ошибку SQL

1. Manticor 66 11.12.18 18:17 Сейчас в теме
Вопрос к знатокам SQL в 1С.

Есть некий скрипт на SQL, который восстанавливает базу:

Сначала соединяемся с SQL:
Функция SQLСоединение(Сервер, ИмяБазы = "", Логин = "", Пароль = "", текстОшибки = "") Экспорт
	SQLConnection = Новый COMОбъект("ADODB.Connection");
	если Логин = "" и Пароль = "" тогда
		ConnectString = "Provider=sqloledb;Server=" + Сервер + ";"+?(ИмяБазы = "", "","Database=" + ИмяБазы + ";") + "Trusted Connections=Yes;Integrated Security=SSPI;";	
	иначе
		ConnectString = "Provider=sqloledb;Server=" + Сервер + ";Database=" + ИмяБазы + ";UID=" + Логин + ";PWD=" + Пароль + ";";
	КонецЕсли;	
	
	SQLConnection.ConnectionString = ConnectString;
	Try
        SQLConnection.Open();        
    Except
        #Если Клиент Тогда 
            Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное);
		#Иначе
			текстОшибки = "Сервер SQL " + Сервер + Символы.ПС + ОписаниеОшибки();
			ЗаписьЖурналаРегистрации("Ошибка соединения с SQL", УровеньЖурналаРегистрации.Ошибка, ,, текстОшибки);
        #КонецЕсли 
        SQLConnection = Неопределено;
	EndTry;  
	Возврат SQLConnection;
КонецФункции

текСоединение = SQLСоединение(СерверSQL.Наименование,,,,текстОшибки)

//далее рабоатем с ADODB
Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = текСоединение;

Попытка	
ЗапросКБД = "EXEC dbo.sp_DatabaseRestore 
			|@Database = '"+БазаSQL_Аудит+"', 
			|@RestoreDatabaseName = '"+ИмяНовБазыSQL+"',
			|@BackupPathFull = '"+ ОбщийКаталогСохр + Кластер + СервSQL_Аудит + "\"+ БазаSQL_Аудит + "\FULL\',
			|@BackupPathDiff = '"+ ОбщийКаталогСохр + Кластер + СервSQL_Аудит + "\"+ БазаSQL_Аудит + "\DIFF\',
			//|@BackupPathLog = '" + ОбщийКаталогСохр + СервSQL_Аудит+"\"+ БазаSQL_Аудит + "LOG\',
			|@MoveFiles = 1,
			|@MoveDataDrive = '"+ ИмяДиска + ":\DATA\',
			|@MoveLogDrive =  '"+ ИмяДиска + ":\Logs\',
			|@RestoreDiff = 1,
			|@ContinueLogs = 0, 
			|@RunRecovery = 1,
			|@Debug = 1";
					
			Команда.CommandText = ЗапросКБД;
			Команда.CommandType = 1;
			Команда.Execute();
Исключение
			текстОшибки = Символы.ПС+ "Ошибка получения данных для сервера " + СтрСервер.Ссылка.Наименование + ОписаниеОшибки();
			Ошибки.Добавить(текстОшибки);						
			возврат Ложь
		КонецПопытки;

Показать


Из былого опыта известно, что если будет ошибка на стороне SQL, то произойдет исключение. Но!
На стороне SQL выходит информация в табло об ошибке(прикрепил скрин) и на стороне 1с не отрабатывается исключение.

Как в 1С понять, что произошла ошибка на SQL?
Прикрепленные файлы:
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. caponid 11.12.18 18:37 Сейчас в теме
А список ошибок при этом пуст?
Для каждого Ошибка из текСоединение.Errors Цикл
    Сообщить("Код: " + Ошибка.Number + " " + Ошибка.Description);
КонецЦикла;
3. Manticor 66 12.12.18 11:37 Сейчас в теме
(2) Странная картинка получается)

Ради тестирования сделал простой запрос на SQL, который выбирает пользователей из табл. юзеров:

ЗапросКБД = "Use [t00002105] Sel ect * Fr om [dbo].[v8users_old]";
			
			Команда.CommandText = ЗапросКБД;
			Команда.CommandType = 1;
			Команда.Execute();
			
			Для каждого Ошибка из текСоединение.Errors Цикл
				Сообщить("Код: " + Ошибка.Number + " " + Ошибка.Description);
			КонецЦикла;
Показать


В итоге в текСоединение.Errors всегда есть ошибка вида:
Код: 0 Changed database context to 't00002105'.

Почему он воспринимает это за ошибку? Хотя на стороне SQL все гладко?
4. caponid 12.12.18 11:50 Сейчас в теме
(3) Это не ошибка (код 0), а предупреждение (warning) - все таки смена контекста (USE) потенциально опасная операция.
5. Manticor 66 12.12.18 12:21 Сейчас в теме
(4) Ок, пробую такой запрос:
ЗапросКБД = 			
				"Use [" + Объект.КопияБазы.Наименование + "]
				|EXEC sp_rename 'v8users', 'v8users_old'
				|UPDATE [" + Объект.КопияБазы.Наименование + "].dbo.Params
				|SET FileName = 'users.usr_old'
				|WHERE FileName = 'users.usr'";
			
			//ЗапросКБД = "Use [t00002105] Sel ect * Fr om [dbo].[v8users_old]";
			
			Команда.CommandText = ЗапросКБД;
			Команда.CommandType = 1;
			Команда.Execute();
Показать


На стороне SQL ошибка:

Msg 15225, Level 11, State 1, Procedure sp_rename, Line 374 [Batch Start Line 0]
No item by the name of 'v8users' could be found in the current database 't00002105', given that @itemtype was input as '(null)'.

(0 rows affected)

1с же выдает: Код: 0 Changed database context to 't00002105'.

Получается, что не видит ошибки на стороне SQL ?
6. caponid 12.12.18 15:03 Сейчас в теме
Что то не то с настройками сервера?
У меня отрабатывает и исключение и вывод ошибок с коллекции Errors
ЗапросКБД = "EXEC sp_rename 'v8users1', 'v8users_old1'";
Команда.CommandText = ЗапросКБД;
Команда.CommandType = 1;
Попытка
    Команда.Execute();	
Исключение
	Сообщить(ОписаниеОшибки());
	Для каждого Ошибка из текСоединение.Errors Цикл
	    Сообщить("Код: " + Ошибка.Number + " " + Ошибка.Description);
	КонецЦикла;	
КонецПопытки; 
Показать

выдает
{ВнешняяОбработка.ADODBCon.Форма.Форма.Форма(13)}: Ошибка при вызове метода контекста (Execute): Произошла исключительная ситуация (Microsoft OLE DB Provider for SQL Server): No item by the name of 'v8users1' could be found in the current database 'TEST', given that @itemtype was input as '(null)'.
Код: -2 147 217 900 No item by the name of 'v8users1' could be found in the current database 'IWH2012', given that @itemtype was input as '(null)'.
8. Manticor 66 12.12.18 15:49 Сейчас в теме
(6)
EXEC sp_rename 'v8users1', 'v8users_old1'

То то и оно, если выполнять простой запрос Use [t00002105] Sel ect * Fr om [dbo].[v8users_old] из 1с, то не уходит в исключение.
7. caponid 12.12.18 15:15 Сейчас в теме
хм, а вот если есть USE, то все.. ошибки не проходят....
Скорее всего это связано с переключением контекста выполнения команды в самой команде...
надо документацию ADO читать..
9. Manticor 66 12.12.18 16:35 Сейчас в теме
(7) Где прокачаться можно? тема очень нужная. Постоянно с этим проблемы.
11. Manticor 66 12.12.18 16:59 Сейчас в теме
(10) гыгы) еще бы было ясно что именно читать там? :-)
13. MarchTomCat 13.12.18 15:23 Сейчас в теме
Я может не совсем понимаю "прелестей" работы с sql-запросами из 1с? Зачем такой изврат?
Для ТС - насколько я понял идет работа с бэкапами SQL - на мой взгляд проще и корректнее настроить планы обслуживания на стороне сервера SQL.
14. Manticor 66 14.12.18 14:10 Сейчас в теме
(13) Вопрос не в изврате, а в том, что не может драйвер на стороне 1С отловить ошибку SQL. НЕ обязательно делать скрипт с восстановлением. Это я привел как частный случай.
15. EVKash 14 14.12.18 15:17 Сейчас в теме
(14) Видимо не заморачивались разработчики, т.к. это прямое нарушение лицензионного соглашения.
http://v8.1c.ru/predpriyatie/questions_licence.htm#65
16. rinat_alp2 61 02.09.19 07:56 Сейчас в теме
Когда в скрипте SQL передается несколько строк, тогда для получения ошибок выполнения последующих после первой строк скрипта необходимо использовать метод NextRecordset.

Пример:
	ADOСоединение = Новый COMОбъект("ADODB.Connection");
	String = "driver={SQL Server};server=ServerName;Database=DataBaseName;Trusted_Connection=Yes";
	ADOСоединение.ConnectionTimeOut = 200;
	ADOСоединение.CommandTimeOut = 180;
	
	ADOСоединение.Open(String);
		
	ТекстКоманды = "
	|      SELECT 1;
	|      SELECT 1;
	|      print 1 / 0;";

	Command = Новый COMОбъект("ADODB.Command");
	Command.CommandType = 1;
	Command.ActiveConnection = ADOСоединение;
	Command.CommandTimeout = ADOСоединение.CommandTimeOut;
	Command.CommandText = ТекстКоманды;
	
	RecordSet= Command.Execute();

	//Для получения ошибок
	NextRecordSet = RecordSet.NextRecordSet();
	Пока NextRecordSet <> Неопределено Цикл
		NextRecordSet = NextRecordSet.NextRecordSet();
	КонецЦикла;
Показать


В результате ошибка на стороне СУБД в третьей строке скрипта будет выявлена исключением в вызывающем коде:
Ошибка при вызове метода контекста (NextRecordset): Произошла исключительная ситуация (Microsoft OLE DB Provider for ODBC Drivers): [Microsoft][ODBC SQL Server Driver][SQL Server]Обнаружена ошибка: деление на ноль.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот