Как исправить ошибку "ORA-00907: missing right parenthesis" при работе с Внешними Источниками Данных Oracle в 1С 8.2?

Программист
← На главную

При работе с внешними источниками данных в 1С 8.2, в частности с базами данных Oracle, программисты часто сталкиваются с различными синтаксическими ошибками, которые возникают при выполнении запросов. Одной из таких распространенных ошибок является "ORA-00907: missing right parenthesis". В этой статье мы подробно разберем причину возникновения этой ошибки и предложим эффективные способы ее устранения, опираясь на опыт, описанный в форуме 1С и дополнительные технические данные.

Суть проблемы: ошибка "ORA-00907" при запросе с LEFT JOIN в 1С 8.2

Наш коллега столкнулся с ситуацией, когда при попытке выполнить запрос к базе данных Oracle через объект ВнешниеИсточникиДанных в 1С 8.2.19.130, система выдает ошибку "ORA-00907: missing right parenthesis". Это произошло при выполнении запроса, который включал оператор ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN) между двумя таблицами.

Рассмотрим код, который привел к ошибке:


Если ВнешниеИсточникиДанных.СПР.ПолучитьСостояние()=СостояниеВнешнегоИсточникаДанных.Отключен Тогда 
    ПараметрыПодключения=ВнешниеИсточникиДанных.СПР.ПолучитьОбщиеПараметрыСоединения();
    ПараметрыПодключения.СтрокаСоединения="DRIVER={Microsoft ODBC for Oracle}; UID=Пользователь; PWD=Пароль; SERVER=Сервер;";
    ПараметрыПодключения.СУБД="Oracle";
    ВнешниеИсточникиДанных.СПР.УстановитьОбщиеПараметрыСоединения(ПараметрыПодключения);
КонецЕсли;

ВнешниеИсточникиДанных.СПР.УстановитьСоединение();

Query = Новый Запрос;
Query.Текст = "ВЫБРАТЬ
                  |    FIDCMN.DOC_NUMBER,
                  |    FIDCMN.DOC_DATE,
                  |    FIBDOC.IS_UNLOAD
                  |ИЗ
                  |    ВнешнийИсточникДанных.СПР.Таблица.APR_FIDCMN КАК FIDCMN
                  |        ЛЕВОЕ СОЕДИНЕНИЕ ВнешнийИсточникДанных.СПР.Таблица.APR_FIBDOC КАК FIBDOC
                  |        ПО FIBDOC.DOC_CODE = FIDCMN.DOC_CODE
                  |ГДЕ
                  |    FIDCMN.RECORDID_DCTP = 722
                  |    И НЕ FIDCMN.DOC_NUMBER ЕСТЬ NULL 
                  |    И FIDCMN.DOC_DATE МЕЖДУ &Нач И &Кон";   
Query.УстановитьПараметр("Нач",НачалоПериода.Дата);
Query.УстановитьПараметр("Кон",КонецДня(КонецПериода.Дата));

Выборка=Query.Выполнить().Выбрать();

В данном случае для подключения используется драйвер Microsoft ODBC for Oracle. Ошибка, как мы видим, возникает на этапе выполнения запроса к внешней базе данных:

Ошибка выполнения запроса по причине: Ошибка внешней базы данных: ошибка при выполнении запроса по причине: Ошибка ODBC. SQLSTATE: 42000 Номер ошибки: 907 Описание: [Microsoft][ODBC driver for Oracle][Oracle]ORA-00907: missing right parenthesis

Самое интересное, что при выполнении аналогичного запроса через ADO (ActiveX Data Objects) к той же базе данных, все работает без каких-либо проблем. Это указывает на то, что проблема не в самой базе данных или в корректности SQL-запроса как такового, а скорее в способе его трансляции и выполнения через механизм Внешних Источников Данных 1С и используемый ODBC-драйвер.

Пошаговая диагностика и локализация проблемы

Когда мы сталкиваемся с такой ошибкой, важно методично подойти к ее диагностике. Давайте разберем шаги, которые помогут нам локализовать проблемный участок запроса:

  1. Проверка базового подключения: Прежде всего, убедитесь, что само подключение к внешней базе данных Oracle установлено корректно. Мы можем попробовать выполнить простейший запрос к одной из таблиц без каких-либо условий или соединений. Если даже такой запрос не работает, проблема может быть глубже – в настройках драйвера, сетевом доступе или параметрах подключения. В нашем случае, автор подтвердил, что запрос к одной таблице работает успешно.
  2. Изоляция проблемного участка: Ошибка ORA-00907 часто указывает на синтаксическую проблему. Если запрос с одной таблицей работает, значит, проблема, скорее всего, кроется в добавлении новых элементов запроса: соединений (ЛЕВОЕ СОЕДИНЕНИЕ), условий (ГДЕ) или использовании агрегатных функций. Начнем с минимально рабочего запроса и постепенно будем добавлять элементы, каждый раз проверяя его выполнение.
  3. Проверка скобок: Описание ошибки "missing right parenthesis" прямо указывает на отсутствие закрывающей скобки. Хотя в нашем случае запрос выглядит синтаксически верным для 1С, внутренняя трансляция в SQL для Oracle может внести свои коррективы. Попробуйте обернуть все условия в ГДЕ (WHERE) в дополнительные скобки, как это предложил один из участников форума. Несмотря на то, что для автора это не помогло, это стандартный диагностический шаг, который стоит выполнять.
  4. Сравнение с рабочим ADO-запросом: Это критически важный шаг. Если у нас есть рабочий запрос к той же базе данных через ADO, сравним его синтаксис с запросом 1С. Это поможет выявить различия в "диалектах" SQL, которые 1С может генерировать, и тем, что ожидает Oracle.

Вот рабочий ADO-запрос, который успешно выполняет нужную выборку:


Query = "Select fidcmn.doc_number,
             fidcmn.doc_date, 
             fibdoc.doc_number,
             fibdoc.is_unload
             from apr.fidcmn 
             left outer join apr.fibdoc
             on fibdoc.doc_code = fidcmn.doc_code
             where fidcmn.recordid_dctp = 722 and fidcmn.doc_number is not null
             and fidcmn.doc_date >= to_date('@@@@','DD-MM-YYYY') 
             and fidcmn.doc_date <= to_date('####','DD-MM-YYYY')";

Сравнивая этот запрос с запросом из 1С, мы можем выделить несколько ключевых отличий, которые могут быть источником проблемы:

Возможные причины ошибки и пути решения

1. Особенности трансляции запросов 1С и синтаксиса Oracle SQL

Основной причиной ошибки ORA-00907 при выполнении ЛЕВОЕ СОЕДИНЕНИЕ через Внешние Источники Данных в 1С 8.2 к Oracle, скорее всего, является несовместимость в интерпретации SQL-синтаксиса между тем, как 1С формирует запрос, и тем, как его обрабатывает промежуточный драйвер Microsoft ODBC for Oracle для СУБД Oracle.

В Oracle SQL синтаксис для LEFT JOIN может быть очень чувствителен к мелочам. Например, использование ключевого слова AS для алиасов таблиц в секции FROM/JOIN, хотя и допустимо в некоторых SQL-диалектах (например, T-SQL), в Oracle часто опускается или может быть интерпретировано по-другому, особенно старыми версиями драйверов или СУБД. Рабочий ADO-запрос демонстрирует, что без AS синтаксис корректен. Платформа 1С преобразует свой внутренний язык запросов в управляющие последовательности ODBC (ODBC Escape Sequences) и затем в нативный SQL СУБД. В этом процессе возможны ошибки трансляции, особенно для сложных конструкций, таких как LEFT JOIN, если драйвер не полностью поддерживает все нюансы или имеет свои особенности.

2. Решение: Смена ODBC/OLEDB драйвера

Наиболее эффективным и часто рекомендуемым решением в подобных ситуациях является использование нативных драйверов Oracle вместо стандартного Microsoft ODBC for Oracle. Драйверы от Microsoft иногда имеют ограничения или особенности в реализации, которые могут приводить к проблемам совместимости или некорректной трансляции сложных SQL-конструкций.

Мы предлагаем вам выполнить следующие шаги:

  1. Установите нативный драйвер Oracle:
    • Oracle ODBC Driver: Это официальный ODBC-драйвер от Oracle. Он обычно входит в состав Oracle Client.
    • Oracle Provider for OLE DB (OraOLEDB): Это провайдер OLE DB, который также можно использовать для подключения. Участники форума подтверждали успешную работу через OraOLEDB.Oracle.1.
    Убедитесь, что установленная версия Oracle Client (и, соответственно, драйвера) соответствует разрядности вашей операционной системы и платформы 1С (32-бит или 64-бит).
  2. Обновите строку соединения в 1С: После установки нативного драйвера, измените строку соединения в вашем коде 1С, чтобы использовать новый драйвер.

Пример строки соединения для Oracle ODBC Driver:


// Пример для Oracle ODBC Driver (потребуется DSN или явное указание)
// С использованием DSN (Data Source Name):
ПараметрыПодключения.СтрокаСоединения="DSN=MyOracleDSN; UID=Пользователь; PWD=Пароль;"; 

// Без DSN, напрямую (может варьироваться в зависимости от версии драйвера)
// DRIVER={Oracle in OraClient12Home1}; DBQ=MyServiceAlias; UID=Пользователь; PWD=Пароль;
// Или, если это более общий синтаксис для ODBC драйвера Oracle:
// DRIVER={Oracle ODBC Driver}; Server=Сервер:Порт/ИмяСервиса; UID=Пользователь; PWD=Пароль;

Пример строки соединения для OraOLEDB.Oracle.1 (OLE DB провайдер):


// Если 1С поддерживает OLE DB провайдеров через Внешние Источники Данных
// (в 8.2 чаще использовались ODBC, но возможность подключения к OLE DB провайдерам есть)
// Provider=OraOLEDB.Oracle;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=Сервер)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=ИмяСервиса)));User ID=Пользователь;Password=Пароль;

Как получить правильную строку соединения:

Мы можем легко сформировать правильную строку соединения, используя файл Universal Data Link (UDL). Это полезный инструмент для тестирования и получения строк подключения к различным базам данных:

  1. Создайте на рабочем столе пустой текстовый файл и переименуйте его в test.udl.
  2. Дважды щелкните по test.udl, чтобы открыть его свойства. Откроется окно "Свойства связи с данными".
  3. На вкладке "Поставщик" выберите нужный Oracle-драйвер. Например, "Microsoft OLE DB Provider for Oracle" (если вы хотите остаться на MS-драйвере, но попробовать OLE DB), или "Oracle Provider for OLE DB" (если вы установили нативный OraOLEDB).
  4. На вкладке "Подключение" введите данные для подключения к вашей базе данных Oracle: имя сервера, имя пользователя и пароль.
  5. Нажмите "Проверить подключение", чтобы убедиться в корректности введенных данных и работоспособности соединения.
  6. Сохраните изменения, нажав "ОК" и закрыв окно свойств.
  7. Откройте файл test.udl обычным текстовым редактором (например, "Блокнотом"). Внутри вы увидите сформированную строку соединения, которую можно скопировать и использовать в 1С.

Переключение на нативный драйвер Oracle значительно увеличивает шансы на корректную трансляцию SQL-запросов и устранение синтаксических ошибок, таких как ORA-00907, поскольку нативные драйверы лучше "понимают" тонкости SQL-диалекта своей СУБД.

3. Оптимизация и упрощение запроса 1С (если смена драйвера не помогла)

Если смена драйвера не решила проблему, или по каким-то причинам вы не можете его изменить, вам потребуется внимательно пересмотреть запрос 1С и попытаться максимально упростить его или адаптировать под особенности трансляции. Мы проанализируем возможные адаптации:

  1. Синтаксис алиасов таблиц: В Oracle SQL ключевое слово AS для алиасов таблиц в секции FROM/JOIN не является обязательным и иногда может вызывать проблемы с некоторыми драйверами или старыми версиями СУБД. В языке запросов 1С мы пишем ... КАК FIDCMN. Если бы была возможность, мы могли бы попробовать убрать КАК. Однако, язык запросов 1С довольно строго регламентирован, и прямое изменение синтаксиса в секции ИЗ может быть невозможно. В таких случаях проблема остается на стороне драйвера.
  2. Проверка параметров дат: Хотя ошибка ORA-00907 не напрямую связана с датами, некорректная обработка дат может усугубить ситуацию. Убедитесь, что формат дат в параметрах &Нач и &Кон не вызывает проблем при их передаче в Oracle. Нативные драйверы, как правило, лучше справляются с автоматическим преобразованием типов. Если проблема сохраняется, возможно, придется передавать даты в виде строк и использовать функции TO_DATE() в самом тексте запроса (это может потребовать динамического формирования текста запроса в 1С, что усложнит решение, так как 1С по умолчанию не позволяет использовать функции SQL-базы данных в своих запросах к внешним источникам).
  3. Постепенное усложнение запроса: Начните с запроса к одной таблице, затем добавьте ЛЕВОЕ СОЕДИНЕНИЕ без условий, затем постепенно добавляйте условия в секции ГДЕ. Это поможет точно определить, какой именно элемент запроса вызывает ошибку. В нашем случае, как мы выяснили из обсуждения, проблема проявляется именно при добавлении соединения, что сильно указывает на проблему трансляции ЛЕВОЕ СОЕДИНЕНИЕ и/или алиасов таблиц.

Исходя из опыта, наиболее вероятная причина кроется в специфике работы Microsoft ODBC for Oracle с конструкциями LEFT JOIN и алиасами таблиц, которые 1С формирует как ... КАК FIDCMN. Если драйвер некорректно транслирует это в нативный Oracle SQL, это может приводить к ошибке синтаксиса.

Дополнительные рекомендации по работе с Внешними Источниками Данных Oracle в 1С

Для успешной и стабильной работы с Oracle через Внешние Источники Данных в 1С мы рекомендуем следующие подходы:

  1. Используйте актуальные версии драйверов: Всегда устанавливайте последние стабильные версии нативных драйверов Oracle, совместимые с вашей версией СУБД и операционной системы. Это поможет избежать известных багов и обеспечит лучшую совместимость.
  2. Укажите правильный тип СУБД: В параметрах соединения Внешнего Источника Данных в 1С всегда явно указывайте ПараметрыПодключения.СУБД="Oracle", чтобы 1С могла применить специфические оптимизации и правила трансляции для данной СУБД.
  3. Тестируйте запросы в нативном SQL-клиенте: Перед тем как переносить сложные запросы в 1С, проверьте их работоспособность и производительность в SQL Developer, SQL*Plus или другом клиенте для Oracle. Это поможет исключить синтаксические ошибки на уровне самой СУБД и убедиться в логической корректности запроса.
  4. Ограничения Внешних Источников Данных: Помните, что в 1С 8.2 данные внешних источников доступны, как правило, только для чтения. Для записи требовались дополнительные обходные пути или использование других механизмов (например, через ADO), хотя в более поздних версиях 1С (начиная с 8.3.5) появилась возможность записи во внешние источники данных.
  5. Используйте функции 1С для работы с датами: 1С достаточно хорошо умеет работать с параметрами типа "Дата" в своих запросах. Обычно нет необходимости вручную преобразовывать даты в строки с использованием функций TO_DATE, если драйвер работает корректно. 1С сама позаботится о правильном форматировании даты для СУБД.

Заключение

Ошибка "ORA-00907: missing right parenthesis" при работе с Внешними Источниками Данных Oracle в 1С 8.2 при использовании ЛЕВОЕ СОЕДИНЕНИЕ чаще всего связана с особенностями трансляции SQL-запроса через Microsoft ODBC for Oracle. Наиболее надежным решением является переход на нативные Oracle драйверы, такие как Oracle ODBC Driver или OraOLEDB.Oracle.1, которые обеспечивают лучшую совместимость и корректную интерпретацию синтаксиса. В случае, если смена драйвера невозможна, детальный анализ и упрощение запроса, а также сравнение с рабочим нативным SQL-запросом, помогут выявить и устранить проблему. Всегда начинайте диагностику с изоляции проблемы и постепенно усложняйте запрос, чтобы точно определить источник ошибки.

← На главную