Как исправить ошибку ORA-06550 при вызове процедур Oracle из 1С через ADODB?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

Интеграция конфигураций 1С:Предприятие со сторонними СУБД, в частности с Oracle Database, нередко реализуется посредством прямого подключения через драйверы ODBC и технологию COM-объектов ADODB. Однако при выполнении анонимных блоков PL/SQL разработчики часто сталкиваются с исключением синтаксического анализатора СУБД вида ORA-06550 и PLS-00103: Encountered the symbol " " when expecting one of the following. Разберем по шагам, почему возникает эта ошибка, как правильно форматировать данные при динамической сборке запросов и какие архитектурные альтернативы существуют.

Анализ проблемы: почему возникает ошибка PLS-00103

Рассмотрим типовую ситуацию. В коде 1С выполняется успешное подключение к базе Oracle, после чего формируется текст вызова хранимой процедуры через конкатенацию строк:


пQR = "BEGIN pk_pay.pr_import_1c(210393, To_Date('01.03.2017','dd.mm.yy'), 321, 1, 6, 0, Null, 'МД00-000695', Null, " + Сумма + ", To_Date('01.03.2017','dd.mm.yy'), 'Оплата...', 41, Null, 0, 1, Null, '6166061288', '616501001', '1С', 'INSERT'); END;";
пRS = CN.Execute(пQR);

Если переменная Сумма имеет тип Число (например, со значением 19800), то при обычном неявном приведении к строке или вызове Строка(Сумма) платформа 1С автоматически форматирует число в соответствии с региональными установками. По умолчанию в качестве разделителя групп разрядов вставляется неразрывный пробел: получается 19 800.

Когда сформированная строка передается на выполнение в СУБД Oracle, парсер встречает конструкцию ... Null, 19 800, To_Date(...) .... Синтаксический анализатор PL/SQL воспринимает число 19, после которого идет пробел и число 800, не разделенные оператором или запятой, и немедленно возвращает синтаксическую ошибку PLS-00103: Encountered the symbol " ".

Решение 1: Правильное форматирование чисел и дат через функцию Формат()

Если выгрузка строится путем генерации текста запроса, необходимо жестко контролировать представление чисел и дат, исключая системные разделители разрядов и настраивая понятный для Oracle разделитель дробной части.

  1. Отключение группировки разрядов: параметр ЧГ=0 отключает группировку тысяч, исключая появление пробелов в строке.
  2. Разделитель дробной части: параметр ЧРД=. заменяет стандартную запятую на точку, так как Oracle по умолчанию в литералах чисел ожидает точку.
  3. Форматирование нулевых значений и длины дробной части: параметры ЧДЦ=2 и ЧО=1 задают фиксированную точность и вывод нуля при отсутствии значения.

Посмотрим на пример правильного преобразования числового значения суммы перед подстановкой в текст команды:


ФорматированнаяСумма = Формат(СуммаДокумента, "ЧДЦ=2; ЧРД=.; ЧН=0.00; ЧГ=0; ЧО=1");
// Для числа 19800.5 получим строку "19800.50"

Для дат рекомендуется использовать явный вызов функции Oracle TO_DATE() с жестким форматом, сформированным через платформенные средства 1С:


ФорматированнаяДата = "TO_DATE('" + Формат(ДатаДокумента, "ДФ=yyyy-MM-dd") + "', 'YYYY-MM-DD')";

Решение 2: Переход на параметризованные команды ADODB.Command

Сборка тела PL/SQL-блока через склеивание строк несет серьезные риски: если в назначении платежа, комментарии или наименовании контрагента встретится символ одинарной кавычки (апостроф), строка нарушит структуру запроса и вызовет повторный сбой синтаксического анализатора. Разберем более надежный подход — использование объекта ADODB.Command и параметров.


Команда = Новый COMObject("ADODB.Command");
Команда.ActiveConnection = CN;
Команда.CommandType = 1; // adCmdText

ТекстКоманды = "BEGIN pk_pay.pr_import_1c(?, ?, ?, ?, ?); END;";
Команда.CommandText = ТекстКоманды;

// Добавление параметров в строгом соответствии с типами данных Oracle
// adInteger = 3, adDate = 7, adDouble = 5, adVarChar = 200, adParamInput = 1
Команда.Parameters.Append(Команда.CreateParameter("p_id", 3, 1, , ИдентификаторЧисло));
Команда.Parameters.Append(Команда.CreateParameter("p_date", 7, 1, , ДатаДокумента));
Команда.Parameters.Append(Команда.CreateParameter("p_sum", 5, 1, , СуммаДокумента));
Команда.Parameters.Append(Команда.CreateParameter("p_comment", 200, 1, 500, СодержимоеКомментария));
Команда.Parameters.Append(Команда.CreateParameter("p_action", 200, 1, 10, "INSERT"));

Команда.Execute();

Использование параметров полностью решает проблему форматирования чисел, региональных настроек дат и экранирования одинарных кавычек.

Особенности передачи идентификатора документа

Проанализируем распространенную ошибку при выборе уникального идентификатора для первого параметра процедуры. Часто разработчики пытаются передать выражение Строка(ДокументОбъект.УникальныйИдентификатор). Если параметр процедуры в пакете Oracle ожидает числовой тип (NUMBER), вызов завершится исключением ORA-06502: numeric or value error, поскольку GUID содержит дефисы и шестнадцатеричные символы.

В такой ситуации необходимо:

  1. Уточнить тип данных в сигнатуре процедуры Oracle: если там используется VARCHAR2, передача строки GUID допустима.
  2. Если используется суррогатный числовой первичный ключ, получать очередное значение из встроенной последовательности Oracle (Sequence) либо использовать отдельный числовой номер, если он предусмотрен архитектурой обмена.

Важные системные нюансы при работе с Oracle через ODBC в 1С

Рассмотрим технические тонкости, которые необходимо учитывать при развертывании обмена:

  1. Разрядность драйвера и платформы: если код выполняется на стороне сервера (директива #Если Сервер Тогда), разрядность установленного Oracle Client и драйвера ODBC должна совпадать с разрядностью службы ragent (32 или 64 бита). При несовпадении возникнет ошибка отсутствия источника данных DSN.
  2. Ограничения операционной системы: вызов объектов COMОбъект("ADODB.Connection") работает исключительно под управлением Windows. Если сервер 1С развернут на ОС Linux, этот механизм работать не будет.
  3. Управление транзакциями: при выполнении процедур модификации данных убедитесь, что в базе Oracle зафиксированы изменения. Если в ODBC-соединении отключен режим автоматической фиксации (AutoCommit), в конце блока необходимо передавать команду COMMIT; либо вызывать метод фиксации транзакции соединения.
  4. Альтернатива через Внешние источники данных: в платформе 1С:Предприятие 8 предусмотрен штатный механизм внешних источников данных. Он настраивается прямо в конфигураторе, поддерживает кроссплатформенную работу под Linux через unixODBC и позволяет вызывать хранимые процедуры СУБД с автоматической типизацией параметров без необходимости ручного управления COM-объектами.
← На главную