В процессе разработки и администрирования высоконагруженных систем на платформе 1С:Предприятие периодически возникают задачи, требующие максимальной производительности при обработке больших массивов данных. В таких случаях стандартные механизмы объектной техники 1С (запись документов, справочников или наборов записей регистров) могут не обеспечивать желаемой скорости. У разработчиков возникает соблазн обратиться к СУБД напрямую для выполнения быстрых операций выборки или обновления данных. Рассмотрим подробнее, как технически реализовать прямое подключение к MS SQL Server из кода 1С, проанализируем риски прямого изменения таблиц и разберем по шагам безопасные альтернативные подходы.
Прежде чем перейти к написанию кода подключения, выясним причину жестких ограничений, накладываемых лицензионным соглашением фирмы 1С на прямую модификацию таблиц базы данных. Клиент-серверная архитектура 1С спроектирована как трехзвенная система (клиент — сервер приложений — СУБД). Платформа берет на себя управление транзакциями, бизнес-логикой и объектной целостностью. Нарушение этого контура посредством выполнения прямых SQL-запросов UPDATE или DELETE влечет за собой серьезные технические проблемы:
_Version (имеющее тип данных timestamp или rowversion). Платформа использует его для контроля версий объектов. Если изменить данные напрямую и некорректно обновить или проигнорировать это поле, штатные сеансы пользователей начнут завершаться критическими ошибками блокировки («Дамп» или аварийное завершение процесса)._IDRRef) хранятся в бинарном формате binary(16). Порядок байтов в UUID на стороне СУБД и в платформе 1С отличается. Простое строковое копирование уникального идентификатора без побайтовой перестановки приведет к появлению «битых» ссылок, которые невозможно будет прочитать штатными средствами.Таким образом, прямое выполнение запросов изменения данных (UPDATE, DELETE, INSERT) допускается исключительно в критических ситуациях аварийного восстановления баз данных квалифицированными администраторами СУБД (DBA) и строго на копиях баз данных.
Поскольку физические имена таблиц (например, _InfoRg2105) и полей в СУБД генерируются платформой динамически при реструктуризации и могут изменяться после обновления конфигурации, писать жестко зашитые имена таблиц в SQL-запросах крайне небезопасно. Проанализируем ситуацию и воспользуемся штатным методом платформы для получения актуальной структуры хранения данных:
// Получаем точное имя таблицы СУБД для регистра сведений "ЦеныНоменклатуры"
МассивМетаданных = Новый Массив;
МассивМетаданных.Добавить(Метаданные.РегистрыСведений.ЦеныНоменклатуры);
ТаблицаСтруктуры = ПолучитьСтруктуруХраненияБазыДанных(МассивМетаданных, Истина);
Если ТаблицаСтруктуры.Количество() > 0 Тогда
ИмяТаблицыSQL = ТаблицаСтруктуры[0].ИмяТаблицыХранения;
Сообщить("Физическое имя таблицы в SQL: " + ИмяТаблицыSQL);
КонецЕсли;
Для создания прямого канала связи с базой данных используется COM-объект ADODB.Connection. Разберем два наиболее распространенных способа авторизации при подключении к СУБД.
Этот метод используется, когда у вас есть выделенная сервисная учетная запись на SQL-сервере с ограниченными правами (например, только на чтение определенных таблиц). Посмотрим на пример кода:
Процедура ВыполнитьПрямойЗапросSQL() Экспорт
// Инициализируем параметры подключения
СерверSQL = "SQL-SERVER-01\MS2019";
ИмяБазыSQL = "Enterprise_DB";
Пользователь= "ReaderUser";
Пароль = "StrongPassword123_";
// Создаем COM-объекты для работы с ADO
Попытка
Соединение = Новый COMОбъект("ADODB.Connection");
Команда = Новый COMОбъект("ADODB.Command");
Рекордсет = Новый COMОбъект("ADODB.Recordset");
Исключение
ЗаписатьЛогСобытий("Ошибка инициализации COM-объектов ADODB: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Формируем строку подключения (Connection String)
СтрокаПодключения = "Provider=SQLOLEDB.1;" +
"Data Source=" + СерверSQL + ";" +
"Initial Catalog=" + ИмяБазыSQL + ";" +
"User ID=" + Пользователь + ";" +
"Password=" + Пароль + ";";
Соединение.ConnectionTimeout = 30; // Таймаут соединения в секундах
Соединение.CommandTimeout = 120; // Таймаут выполнения запроса в секундах
// Открываем соединение с базой данных
Попытка
Соединение.Open(СтрокаПодключения);
Команда.ActiveConnection = Соединение;
Исключение
Сообщить("Не удалось установить соединение с сервером баз данных!");
ЗаписатьЛогСобытий("Ошибка авторизации SQL: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Пример выполнения безопасного запроса на чтение данных (SELECT)
ТекстЗапроса = "SELECT TOP 100 _Period, _Fld1520 FROM _InfoRg2105 ORDER BY _Period DESC";
Попытка
Команда.CommandText = ТекстЗапроса;
Рекордсет = Команда.Execute();
// Обходим полученную выборку данных
Пока Рекордсет.EOF() = 0 Цикл
ЗначениеПериода = Рекордсет.Fields("_Period").Value;
ЗначениеПоля = Рекордсет.Fields("_Fld1520").Value;
Сообщить("Дата: " + ЗначениеПериода + " | Значение: " + ЗначениеПоля);
Рекордсет.MoveNext();
КонецЦикла;
Рекордсет.Close();
Исключение
Сообщить("Ошибка выполнения запроса к СУБД: " + ОписаниеОшибки());
КонецПопытки;
// Обязательно закрываем соединение после работы
Если Соединение.State = 1 Тогда
Соединение.Close();
КонецЕсли;
КонецПроцедуры
При использовании клиент-серверного варианта работы платформы код на стороне сервера 1С выполняется под учетной записью операционной системы, под которой запущена служба сервера приложений (например, USR1CV8). Мы можем настроить права доступа для этого пользователя непосредственно в MS SQL Server и использовать доверительное соединение без хранения паролей в открытом виде в коде конфигурации:
Функция ПолучитьСоединениеTrusted(СерверSQL, ИмяБазыSQL)
Соединение = Новый COMОбъект("ADODB.Connection");
// Используем параметр Integrated Security=SSPI для сквозной авторизации Windows
СтрокаПодключения = "Provider=SQLOLEDB.1;" +
"Data Source=" + СерверSQL + ";" +
"Initial Catalog=" + ИмяБазыSQL + ";" +
"Integrated Security=SSPI;";
Попытка
Соединение.Open(СтрокаПодключения);
Возврат Соединение;
Исключение
ЗаписатьЛогСобытий("Не удалось подключиться через Trusted Connection: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
КонецФункции
Для удобства отладки или первоначальной настройки строки подключения системные администраторы могут использовать встроенный в операционную систему Windows диалог настройки связей данных (DataLinks). Проанализируем пример вызова этого системного окна из 1С:
Процедура ИнтерактивнаяНастройкаПодключения()
Попытка
Соединение = Новый COMОбъект("ADODB.Connection");
ДиалогСвязей = Новый COMОбъект("DataLinks");
// Открываем стандартное окно Windows "Свойства связи данных"
Если ДиалогСвязей.PromptEdit(Соединение) Тогда
СтрокаПодключения = Соединение.ConnectionString;
Сообщить("Полученная строка подключения: " + СтрокаПодключения);
КонецЕсли;
Исключение
Предупреждение("Не удалось открыть диалог настройки подключения!");
КонецПопытки;
КонецПроцедуры
Если вам требуется регулярно читать или изменять данные во внешних базах данных SQL или интегрировать систему с другими корпоративными СУБД, платформа 1С предоставляет мощные штатные объектные альтернативы, которые работают в рамках лицензионного соглашения и не нарушают работу кэша сервера приложений:
СоздатьОбъект() для безопасной записи и изменения данных.Использование прямого доступа к базам данных MS SQL оправдано только в узких сценариях оптимизации чтения сложных аналитических данных или при проведении регламентных операций обслуживания баз данных во время монопольного доступа к системе (когда пользователи и сервер приложений отключены).