Работа с внешними источниками данных в 1С — это мощный инструмент, который позволяет интегрировать сторонние базы данных непосредственно в программную среду предприятия. Однако при использовании СУБД Oracle разработчики часто сталкиваются со специфическими ошибками синтаксиса и проблемами типизации данных. Одной из самых коварных является ошибка "ORA-00923: ключевое слово FROM не найдено там, где оно ожидалось", а также трудности при получении больших текстовых объектов CLOB.
В этой статье мы подробно рассмотрим, почему возникают эти проблемы, как настроить систему для их предотвращения и какой программный код использовать для стабильного получения данных через COM-объекты ADODB.
Когда мы добавляем таблицы Oracle через стандартный механизм 1С, платформа самостоятельно формирует SQL-запросы к СУБД. Ошибка ORA-00923 обычно сигнализирует о синтаксической ошибке. Разберем основные причины, которые к этому приводят:
SELECT "Name" FROM "Table"). В Oracle идентификаторы, заключенные в кавычки, становятся чувствительными к регистру. Если в базе Oracle таблица создана как MY_TABLE (верхний регистр по умолчанию), а 1С запрашивает "my_table", Oracle не найдет объект и выдаст ошибку.DATE, COMMENT, ORDER, UID), драйвер может некорректно обработать запрос.Metadata Id Default. Если он настроен некорректно, драйвер может неправильно интерпретировать метаданные, передаваемые платформой 1С.Для решения проблемы в рамках штатного механизма рекомендуется проверить свойство «Имя в источнике» у каждой таблицы и поля в конфигураторе 1С. Оно должно в точности (включая регистр) соответствовать тому, как объект называется в схеме Oracle.
Если штатный механизм «Внешних источников данных» продолжает работать нестабильно, целесообразно рассмотреть вариант прямого подключения через COMОбъект. Это дает разработчику полный контроль над текстом SQL-запроса и процессом получения данных.
Рассмотрим пример кода для подключения и выполнения функции (или пакета) в Oracle, который возвращает набор записей:
ТаблицаЗаписей = Новый ТаблицаЗначений;
ТаблицаЗаписей.Колонки.Добавить("ID");
ТаблицаЗаписей.Колонки.Добавить("DOC_ID");
ТаблицаЗаписей.Колонки.Добавить("XML_DATA"); // Поле типа CLOB в Oracle
// Установка соединения (функция ПолучитьПодключение должна возвращать COM-объект ADODB.Connection)
Connect = ПолучитьПодключение();
Если Connect = Неопределено Тогда
Сообщить("Не смогли подключиться к базе Oracle");
Возврат;
КонецЕсли;
Command = Новый COMObject("ADODB.Command");
Command.ActiveConnection = Connect;
// Указываем имя вызываемой функции или SQL-запрос
Command.CommandText = "CORPORATE.PKG_WS.GETDOCUMENTSFORSEND";
Command.CommandType = 8; // adCmdUnknown или adCmdStoredProc
RecordSet = Новый COMОбъект("ADODB.RecordSet");
Попытка
RecordSet = Command.Execute();
Исключение
Сообщить("Ошибка выполнения запроса: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Пока RecordSet.EOF() = 0 Цикл
НоваяСтрока = ТаблицаЗаписей.Добавить();
Для i = 0 По RecordSet.Fields.Count-1 Цикл
ИмяКолонки = RecordSet.Fields.Item(i).Name;
// Здесь может возникнуть проблема с типом CLOB
НоваяСтрока[ИмяКолонки] = RecordSet.Fields.Item(ИмяКолонки).Value;
КонецЦикла;
RecordSet.MoveNext();
КонецЦикла;
Проанализируем ситуацию: при выполнении этого кода данные обычных типов (числа, строки) переносятся корректно, но поле XML_DATA, имеющее в Oracle тип CLOB (Character Large Object), в 1С отображается как Неопределено. Это происходит потому, что LOB-объекты представляют собой указатели на данные, а не сами данные в явном виде.
Выясним причину: тип CLOB может содержать гигабайты текста, поэтому драйвер не передает его «в лоб». Для получения этих данных в 1С есть несколько путей.
Способ 1. Преобразование на стороне Oracle.
Если вы знаете, что размер текста в поле не превышает лимитов строкового типа Oracle (традиционно 4000 символов, в новых версиях до 32767), самый простой способ — использовать функцию TO_CHAR в самом SQL-запросе или внутри хранимой процедуры:
SELECT TO_CHAR(XML_DATA) FROM MY_TABLE
В этом случае 1С получит обычную строку, и значение Неопределено исчезнет.
Способ 2. Использование метода GetChunk.
Если данные действительно большие (например, тяжелые XML-файлы), необходимо считывать их по частям (порциями). Разберем, как изменить цикл обхода RecordSet для работы с большими объектами:
// Фрагмент кода для чтения CLOB
РазмерПоля = RecordSet.Fields.Item("XML_DATA").ActualSize;
Если РазмерПоля > 0 Тогда
// Считываем данные порциями по 1024 символа
СодержимоеCLOB = "";
Порция = 1024;
Прочитано = 0;
Пока Прочитано < РазмерПоля Цикл
ЧастьДанных = RecordSet.Fields.Item("XML_DATA").GetChunk(Порция);
СодержимоеCLOB = СодержимоеCLOB + ЧастьДанных;
Прочитано = Прочитано + Порция;
КонецЦикла;
НоваяСтрока.XML_DATA = СодержимоеCLOB;
Иначе
НоваяСтрока.XML_DATA = "";
КонецЕсли;
Способ 3. Смена провайдера на OraOLEDB.
Проанализируем строку подключения. Часто для связи используется провайдер MSDASQL (Microsoft OLE DB Provider for ODBC). Однако при работе с Oracle гораздо эффективнее использовать родной провайдер OraOLEDB.Oracle.
При использовании этого провайдера в строке подключения можно указать параметр SPPrmsLOB=T. Это заставляет провайдер автоматически обрабатывать LOB-параметры и передавать их в понятном для COM-клиента (которым является 1С) строковом виде, что зачастую избавляет от необходимости использовать GetChunk.
Чтобы минимизировать ошибки взаимодействия 1С и Oracle, придерживайтесь следующих правил:
Использование прямого обращения через ADODB с правильной обработкой CLOB через GetChunk или TO_CHAR является наиболее надежным способом интеграции 1С и Oracle, позволяющим обойти ограничения стандартных механизмов платформы и специфические ошибки синтаксиса СУБД.