Интеграция устаревших платформ, таких как 1С:Предприятие 7.7, с современными корпоративными базами данных (например, Oracle Database) — задача частая, но сопряженная с целым рядом технических нюансов. Основная сложность заключается в правильном конфигурировании драйверов подключения, обработке прав доступа в операционных системах Windows 7/10, а также в специфике вызова хранимых процедур и функций пакетов Oracle из кода 1С.
В этой статье мы подробно разберем, как организовать надежное соединение с сервером Oracle с помощью технологии ADO, как обойти типичные ошибки инициализации (включая популярную ошибку ORA-00604), а также научимся вызывать функции инициализации контекста сессии непосредственно из среды 1С 7.7.
Для подключения к Oracle из 1С 7.7 обычно используют один из двух OLE DB провайдеров:
Важное примечание: Платформа 1С 7.7 является исключительно 32-разрядным (x86) приложением. Это означает, что на компьютере, с которого выполняется подключение, обязательно должен быть установлен 32-битный клиент Oracle (Oracle Client x86), даже если сама операционная система Windows является 64-битной. 64-битные драйверы ADO платформа 1С 7.7 использовать не сможет.
Рассмотрим два основных варианта формирования строки подключения к базе данных. Выбор зависит от того, используем ли мы локальный конфигурационный файл tnsnames.ora или хотим жестко прописать параметры сервера прямо в коде.
Вариант А. Использование файла tnsnames.ora
Для начала проанализируем структуру конфигурационного файла tnsnames.ora, который располагается по пути установки вашего Oracle-клиента (например, C:\oracle\product\11.2.0\client_1\network\admin\tnsnames.ora). Пропишем в него алиас нашей базы данных:
MOON =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 123.4.56.78)(PORT = 1111))
)
(CONNECT_DATA =
(SID = PRD)
)
)
Теперь в 1С 7.7 мы можем подключиться, указав имя этого алиаса в параметре Data Source:
Соединение = СоздатьОбъект("ADODB.Connection");
Соединение.Provider = "OraOLEDB.Oracle"; // Или "MSDAORA.1"
Соединение.ConnectionString = "Data Source=MOON;User ID=XXXX;Password=xxxx;";
Попытка
Соединение.Open();
Сообщить("Соединение с Oracle успешно установлено!");
Исключение
Предупреждение("Не удалось подключиться: " + ОписаниеОшибки());
КонецПопытки;
Вариант Б. Подключение без tnsnames.ora (Direct Connection / EZ Connect)
Если на клиентских компьютерах нет возможности централизованно настраивать файлы конфигурации, мы можем передать всю структуру параметров подключения (Description) непосредственно в строку соединения:
Соединение = СоздатьОбъект("ADODB.Connection");
Соединение.Provider = "OraOLEDB.Oracle";
ConnectionString = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=123.4.56.78)(PORT=1111))(CONNECT_DATA=(SID=PRD)));User Id=XXXX;Password=xxxx;";
Соединение.ConnectionString = ConnectionString;
Попытка
Соединение.Open();
Сообщить("Прямое подключение установлено успешно!");
Исключение
Предупреждение("Ошибка прямого подключения: " + ОписаниеОшибки());
КонецПопытки;
При тестировании подключения в среде Windows 7 или Windows 10 администраторы и разработчики часто сталкиваются со следующей системной ошибкой:
Microsoft OLE DB Provider for Oracle: ORA-00604: error occurred at recursive SQL level %s
Выясним причины её возникновения и разберем способы решения этой проблемы.
Причина 1. Ограничение прав доступа к каталогу Oracle Client
Компоненты ADO запускаются операционной системой в контексте пользователя, под которым работает сессия 1С. Если у этого пользователя отсутствуют полные права на чтение файлов в папке установленного клиента Oracle (например, C:\app или C:\oracle), драйвер не может прочитать библиотеки локализации и падает в рекурсивную системную ошибку.
Решение: Перейдите в проводнике к корневой папке установленного клиента Oracle, откройте её "Свойства" -> вкладка "Безопасность". Нажмите кнопку "Изменить" и добавьте права "Чтение и выполнение" (Read & Execute) для группы пользователей "Прошедшие проверку" (Authenticated Users) или конкретного локального пользователя. Обязательно примените изменения ко всем дочерним объектам и перезагрузите компьютер.
Причина 2. Конфликт региональных настроек (NLS_LANG)
Если кодировка операционной системы не совпадает со значениями, ожидаемыми клиентом Oracle, инициализация сессии прерывается.
Решение: Откройте редактор реестра regedit и перейдите в ветку 32-битного окружения: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_... (или HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_... для 32-битных ОС). Найдите строковый параметр NLS_LANG и установите для него корректное значение русской локали, например: RUSSIAN_RUSSIA.CL8MSWIN1251.
Во многих корпоративных системах (например, Oracle E-Business Suite — OEBS) после успешного открытия физического соединения требуется выполнить логическую авторизацию пользователя во внутреннем реестре пакетов СУБД. Нам необходимо запустить PL/SQL-функцию:
xxeq_interface.login(user_name, password) RETURN numeric
Для корректного вызова этой функции в среде 1С 7.7 мы задействуем объект ADODB.Command. Обратите внимание на важнейшее правило технологии ADO при работе с Oracle: возвращаемый параметр функции (ReturnValue) всегда должен создаваться и добавляться в коллекцию параметров самым первым по порядку! Только после него добавляются входные параметры.
Рассмотрим детальный пример реализации этого механизма:
Функция ВыполнитьАвторизациюВ_OEBS(Соединение, ИмяПользователя, Пароль)
Команда = СоздатьОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;
Команда.CommandText = "xxeq_interface.login";
Команда.CommandType = 4; // Соответствует системной константе adCmdStoredProc
// 1. Создаем и добавляем параметр для возвращаемого значения (Index = 0)
// Параметры метода CreateParameter: Имя, Тип (3 = adInteger), Направление (4 = adParamReturnValue)
ПарамВозврат = Команда.CreateParameter("result", 3, 4);
Команда.Parameters.Append(ПарамВозврат);
// 2. Создаем и добавляем входящие параметры (имена должны точно соответствовать сигнатуре в СУБД)
// Параметры: Имя, Тип (200 = adVarChar), Направление (1 = adParamInput), Размер, Значение
ПарамUser = Команда.CreateParameter("user_name", 200, 1, 50, ИмяПользователя);
Команда.Parameters.Append(ПарамUser);
ПарамPass = Команда.CreateParameter("password", 200, 1, 50, Пароль);
Команда.Parameters.Append(ПарамPass);
Попытка
Команда.Execute();
Результат = Число(ПарамВозврат.Value);
Возврат Результат;
Исключение
Сообщить("Ошибка вызова инициализирующей функции: " + ОписаниеОшибки(), "!");
Возврат -1;
КонецПопытки;
КонецФункции
После того как соединение установлено и контекст сессии успешно проинициализирован функцией авторизации, мы можем выполнять SQL-запросы на выборку данных и переносить результаты в объекты 1С (например, в ТаблицаЗначений).
Разберем готовый шаблон функции чтения данных:
Процедура ЗагрузитьДанныеИзOracle()
// Открываем соединение
Соединение = СоздатьОбъект("ADODB.Connection");
Соединение.Provider = "OraOLEDB.Oracle";
Соединение.ConnectionString = "Data Source=MOON;User ID=XXXX;Password=xxxx;";
Попытка
Соединение.Open();
Исключение
Предупреждение("Не удалось открыть сессию с сервером Oracle!");
Возврат;
КонецПопытки;
// Выполняем логический вход в систему
РезультатВхода = ВыполнитьАвторизациюВ_OEBS(Соединение, "oebs_user", "oebs_pass");
Если РезультатВхода <> 1 Тогда // Предположим, что 1 - признак успешного входа
Предупреждение("Авторизация в пакете xxeq_interface отклонена СУБД!");
Соединение.Close();
Возврат;
КонецЕсли;
// Выполняем произвольный SQL-запрос
Команда = СоздатьОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;
Команда.CommandType = 1; // adCmdText
Команда.CommandText = "SELECT kod, nreg, name FROM kod_amort WHERE active = 1";
Попытка
Выборка = Команда.Execute();
Исключение
Предупреждение("Ошибка выполнения SQL-запроса: " + ОписаниеОшибки());
Соединение.Close();
Возврат;
КонецПопытки;
// Переносим результат выборки в Таблицу Значений 1С
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("Код");
ТЗ.НоваяКолонка("РегНомер");
ТЗ.НоваяКолонка("Наименование");
Если Выборка.EOF() = 0 Тогда
Пока Выборка.EOF() = 0 Цикл
ТЗ.НоваяСтрока();
// Чтение значений полей через обращение к коллекции Fields
ТЗ.Код = СокрЛП(Выборка.Fields.Item("kod").Value);
ТЗ.РегНомер = Число(Выборка.Fields.Item("nreg").Value);
ТЗ.Наименование = СокрЛП(Выборка.Fields.Item("name").Value);
Выборка.MoveNext();
КонецЦикла;
КонецЕсли;
// Закрываем выборку и соединение
Выборка.Close();
Соединение.Close();
// Выводим полученную таблицу для анализа пользователю
ТЗ.ВыбратьСтроку("Загруженные амортизационные коды из Oracle");
КонецПроцедуры
Используя предложенные методики, мы можем гибко управлять сессиями Oracle непосредственно из программного кода платформы 1С 7.7, обеспечивая высокую скорость обмена данными и корректную обработку транзакций и процедур авторизации.