Работа с базами и выполнение запросов MSSQL на прямую, посредством встроенного языка 1С
Задача: выгрузить в удаленную базу MSSQL некие данные с произвольной структурой.
Решение: 1С умеет работать с COM соединениями. Их и используем.
Сначала напишем процедуру отвечающую за подключение к MSSQL, и выдающее на выходе ссылку на полученное соединение:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
Перем СтрокаИнициализацииSQL Экспорт; Перем ОлеСоединениеSQL Экспорт; // Объект ADO Connection Процедура ИнициализацияПодключения(Разорвать = ЛОЖЬ) Экспорт Перем ОлеЛинк, ОлеВрем; Если (ОлеСоединениеSQL <> Неопределено) ИЛИ (Разорвать) Тогда // Разрываем связь Попытка ОлеСоединениеSQL.Закрыть(); Исключение КонецПопытки; ОлеСоединениеSQL = NULL; Возврат; КонецЕсли; // Или устанавливаем ... Пока ИСТИНА Цикл ОлеСоединениеSQL = Новый COMОбъект("ADODB.Connection"); Если ОлеСоединениеSQL <> NULL Тогда Попытка //ОчиститьСообщения(); ОлеСоединениеSQL.Open(СтрокаИнициализацииSQL); Сообщить("Соединение с БД SQL установлено успешно", СтатусСообщения.Обычное); Возврат; Исключение Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное); Ответ = Вопрос("По указанной строке инициализации |Cоединение установить не удалось. |Вы хотите запустить ""Data Link Properties"" для настройки соединения?", РежимДиалогаВопрос.ДаНет, 20, КодВозвратаДиалога.Нет, "Подключение SQL..."); Если Ответ = КодВозвратаДиалога.Нет Тогда ОлеСоединениеSQL = NULL; Возврат; КонецЕсли; КонецПопытки; Иначе Ответ = Вопрос("Строка инициализации соединения не определена. |Вы хотите запустить ""Data Link Properties"" для настройки соединения", РежимДиалогаВопрос.ДаНет, 20, КодВозвратаДиалога.Нет, "Подключение SQL..."); Если Ответ = КодВозвратаДиалога.Нет Тогда ОлеСоединениеSQL = NULL; Возврат; КонецЕсли; КонецЕсли; ОлеЛинк = Новый COMОбъект("Datalinks"); Попытка ОлеВрем = ОлеЛинк.PromptNew(); СтрокаИнициализацииSQL = ОлеВрем.ConnectionString; сообщить(СтрокаИнициализацииSQL); ОлеВрем = NULL; Исключение Сообщить("Некорректное завершение Datalinks - " + ОписаниеОшибки(), СтатусСообщения.Важное); Возврат; КонецПопытки; КонецЦикла; КонецПроцедуры |
Далее в отдельные функции вынесем процедуры выполнения запросов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
// Функция ВыполнитьЗапросSQL() // Назначение: Выполняет запрос и загоняет результат в таблицу значений. // Выполняется медленно, т.к. каждый раз открывает и закрывает новый RECORDSET // Нужно использовать только в отчетах и обработках. // Параметры: // СтрокаТекстаЗапроса - строка содержащая текст запроса, // ТаблицаЗапроса - таблица значений в которую будет передан результат запроса, // ВыводитьСообщенияОСбоях - выводить сообщения о сбоях или нет, // ОлеНаборДанных - если передан параметр, то выходная формироваться не будет, а в него // будет записан соотв. Recordset // Возвращаемые значения: Истина - все хорошо, // Ложь - сбой. // Функция глВыполнитьЗапросSQL(СтрокаТекстаЗапроса, ТаблицаЗапроса = NULL, ВыводитьСообщенияОСбоях = ИСТИНА, ОлеНаборДанных = NULL) Экспорт // готовим текст запроса Если НЕ ЕстьСвязьSQL() Тогда Если ВыводитьСообщенияОСбоях Тогда Сообщить("Связь с SQL не установлена."); КонецЕсли; Возврат ЛОЖЬ; КонецЕсли; Состояние(НРег(СтрЗаменить(СтрокаТекстаЗапроса, Символы.ПС, " "))); Попытка ОлеКом = Новый COMОбъект("ADODB.Command"); ОлеКом.ActiveConnection = ОлеСоединениеSQL; ОлеКом.CommandType = 1; // {{HLDN.01-10:22:40D.20.07.2009-SHCAN // Увеличиваем допустимое время выполнения запроса - оптимизация SQL представляется затруднительной из-за особенностей JDE. ОлеКом.CommandTimeout = 120; // }}HLDN.01-10:22:40D.20.07.2009-SHCAN ОлеКом.CommandText = СтрокаТекстаЗапроса; // пробуем выполнить ОлеНаборДанных = ОлеКом.Execute(); Если ОлеНаборДанных.State() = 0 Тогда // Выполняли не SELECT а какую то команду типа UPDATE, DROP и т.д. Если ТипЗнч(ТаблицаЗапроса) <> Тип("ТаблицаЗначений") Тогда Если ВыводитьСообщенияОСбоях Тогда Сообщить("Команда SQL выполнена успешно"); КонецЕсли; Иначе ТаблицаЗапроса.Очистить(); ТаблицаЗапроса.Колонки.Добавить("Результат"); НоваяСтрока = ТаблицаЗапроса.Добавить(); НоваяСтрока.Результат = "Команда SQL выполнена успешно"; КонецЕсли; Возврат ИСТИНА; КонецЕсли; Исключение Если ВыводитьСообщенияОСбоях Тогда Сообщить(ОписаниеОшибки()); Сообщить("Запрос SQL не выполнен"); КонецЕсли; Возврат ЛОЖЬ; КонецПопытки; // Возвращаем результат, если не надо загонять в ТаблицаЗапроса Если ТипЗнч(ТаблицаЗапроса) <> Тип("ТаблицаЗначений") Тогда Возврат ИСТИНА; КонецЕсли; Попытка // Теперь загоняем результат в ТаблицаЗапроса чКолСтрок = ОлеНаборДанных.Recordcount(); чКолПолей = ОлеНаборДанных.Fields().Count; ТаблицаЗапроса.Очистить(); Если (чКолСтрок = 0) ИЛИ (чКолПолей < 1) Тогда ОлеНаборДанных.Close(); КонецЕсли; чСтрока = 0; // Заполняем заголовки колонок... Для чКол=1 По чКолПолей Цикл ТаблицаЗапроса.Колонки.Добавить(ОлеНаборДанных.Fields(чКол-1).Name); КонецЦикла; Если (ОлеНаборДанных.EOF()<>0) И (ОлеНаборДанных.BOF()<>0) Тогда ОлеНаборДанных.Close(); Возврат ИСТИНА; КонецЕсли; ОлеНаборДанных.MoveFirst(); Пока ОлеНаборДанных.EOF() = 0 Цикл чСтрока = чСтрока + 1; НоваяСтрока = ТаблицаЗапроса.Добавить(); чКол = 0; Для чКол = 0 По чКолПолей - 1 Цикл НоваяСтрока[чКол] = ОлеНаборДанных.Fields(чКол).Value КонецЦикла; ОлеНаборДанных.MoveNext(); КонецЦикла; // Закрываем набор... ОлеНаборДанных.Close(); Возврат ИСТИНА; Исключение Если ВыводитьСообщенияОСбоях Тогда Если ОлеНаборДанных.State()<>0 Тогда Сообщить(ОписаниеОшибки()); Сообщить("Запрос SQL не выполнен"); Иначе Сообщить("Команда SQL не выполнена"); Возврат ИСТИНА; КонецЕсли; КонецЕсли; Возврат ЛОЖЬ; КонецПопытки; КонецФункции //ВыполнитьЗапросSQL() Функция ЕстьСвязьSQL() Если ОлеСоединениеSQL <> NULL Тогда Возврат ИСТИНА; КонецЕсли; ОлеСоединениеSQL = NULL; Возврат ЛОЖЬ; КонецФункции //ЕстьСвязьSQL() |
В результате выполнение запроса сведется к следующим шагам:
1 2 3 4 5 6 |
СтрокаИнициализацииSQL = "Provider=SQLOLEDB.1;Password=пароль;Persist Security Info=True;User ID=пользователь;Initial Catalog=база;Data Source=сервер_базы"; ИнициализацияПодключения(); sql="INSERT INTO бла-бла-бла)"; глВыполнитьЗапросSQL(sql); ИнициализацияПодключения(ложь); //отключаемся от базы ОлеСоединениеSQL = Неопределено; |
При написании данной статьи неоценимую помощь оказал Вотинов Александр
Есть нюанс. Мне этот код во многом достался «по наследству». Так что можно сказать спасибо Сергею Новицкому и Сергею Копотю, а кому до них — не знаю, но возможно там тоже длинная цепочка 🙂 .
Программисты всех стран, объединяйтесь, в общем.