Интеграция конфигураций 1С:Предприятие со сторонними СУБД, в частности с Oracle Database, нередко реализуется посредством прямого подключения через драйверы ODBC и технологию COM-объектов ADODB. Однако при выполнении анонимных блоков PL/SQL разработчики часто сталкиваются с исключением синтаксического анализатора СУБД вида ORA-06550 и PLS-00103: Encountered the symbol " " when expecting one of the following. Разберем по шагам, почему возникает эта ошибка, как правильно форматировать данные при динамической сборке запросов и какие архитектурные альтернативы существуют.
Рассмотрим типовую ситуацию. В коде 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 " ".
Если выгрузка строится путем генерации текста запроса, необходимо жестко контролировать представление чисел и дат, исключая системные разделители разрядов и настраивая понятный для Oracle разделитель дробной части.
ЧГ=0 отключает группировку тысяч, исключая появление пробелов в строке.ЧРД=. заменяет стандартную запятую на точку, так как Oracle по умолчанию в литералах чисел ожидает точку.ЧДЦ=2 и ЧО=1 задают фиксированную точность и вывод нуля при отсутствии значения.Посмотрим на пример правильного преобразования числового значения суммы перед подстановкой в текст команды:
ФорматированнаяСумма = Формат(СуммаДокумента, "ЧДЦ=2; ЧРД=.; ЧН=0.00; ЧГ=0; ЧО=1");
// Для числа 19800.5 получим строку "19800.50"
Для дат рекомендуется использовать явный вызов функции Oracle TO_DATE() с жестким форматом, сформированным через платформенные средства 1С:
ФорматированнаяДата = "TO_DATE('" + Формат(ДатаДокумента, "ДФ=yyyy-MM-dd") + "', 'YYYY-MM-DD')";
Сборка тела 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 содержит дефисы и шестнадцатеричные символы.
В такой ситуации необходимо:
VARCHAR2, передача строки GUID допустима.Рассмотрим технические тонкости, которые необходимо учитывать при развертывании обмена:
#Если Сервер Тогда), разрядность установленного Oracle Client и драйвера ODBC должна совпадать с разрядностью службы ragent (32 или 64 бита). При несовпадении возникнет ошибка отсутствия источника данных DSN.COMОбъект("ADODB.Connection") работает исключительно под управлением Windows. Если сервер 1С развернут на ОС Linux, этот механизм работать не будет.COMMIT; либо вызывать метод фиксации транзакции соединения.