При интеграции сторонних баз данных с системой «1С:Предприятие 8» через механизм Внешних источников данных (ВИД) разработчики часто сталкиваются со следующей проблемой. При попытке прочитать данные из таблицы, имя которой совпадает с зарезервированным словом используемой СУБД (например, таблица order, select, group, user и т. д.), платформа генерирует SQL-запрос, который вызывает синтаксическую ошибку на стороне базы данных.
В этой статье мы подробно разберем, почему возникает эта ошибка, как устроена трансляция запросов платформой 1С и какими способами можно гарантированно решить эту проблему на уровне конфигурации 1С и настроек СУБД.
Рассмотрим классический пример. В конфигурации настроен внешний источник данных для СУБД MySQL (например, для интеграции с популярным интернет-магазином Opencart). Нам необходимо получить данные из таблицы заказов, которая в базе данных MySQL называется order. Мы пишем стандартный запрос в 1С:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| order_table.order_id КАК ИдентификаторЗаказа
|ИЗ
| ВнешнийИсточникДанных.Opencart.Таблица.order КАК order_table";
Выборка = Запрос.Выполнить().Выбрать();
При выполнении этого кода мы получаем ошибку СУБД, текст которой выглядит примерно так:
... syntax to use near 'order T1' at line 3
Выясним причину такого поведения. Дело в том, что платформа «1С:Предприятие» при обращении к внешним источникам транслирует внутренний язык запросов 1С в нативный SQL-синтаксис целевой СУБД. В процессе этой трансляции платформа автоматически присваивает таблицам короткие синонимы (алиасы), такие как T1, T2 и так далее. На стороне MySQL итоговый запрос превращается в следующую конструкцию:
SELECT T1.order_id FROM order T1
Поскольку слово order является зарезервированным оператором сортировки в стандарте SQL (используется в связке ORDER BY), парсер MySQL ожидает увидеть после него параметры сортировки, а не назначение алиаса таблицы T1. Чтобы СУБД поняла, что order — это имя физической таблицы, а не команда, его необходимо экранировать специальными символами. В MySQL для этого используются косые кавычки (бэктики): `order`.
Давайте подробно рассмотрим три практических способа заставить эту схему работать корректно.
Начиная с версий платформы 8.3.2 / 8.3.3, разработчики 1С добавили штатный инструмент для обхода подобных ограничений. Он заключается в специальном форматировании свойства метаданных «Имя в источнике данных».
Правило одинарных кавычек гласит: если значение свойства «Имя в источнике данных» (для таблицы или для отдельного поля) в конфигураторе 1С заключено в одинарные кавычки (апострофы), то платформа передает это имя в SQL-запрос к СУБД «как есть», отсекая внешние одинарные кавычки и полностью сохраняя внутреннее содержимое.
Разберем по шагам, как применить это правило для различных СУБД:
Opencart) и откройте список его таблиц.order).'`order`'. В результате платформа 1С отправит к MySQL запрос, содержащий экранированное имя: `order`.'[order]'. СУБД получит имя в виде: [order].'"order"'. СУБД получит имя в виде: "order".Важное примечание о режиме совместимости конфигурации:
Описанное выше поведение напрямую зависит от установленного режима совместимости вашей конфигурации:
"). Для MySQL это приводит к ошибкам, так как двойные кавычки по умолчанию воспринимаются этой СУБД как строковые литералы, а не как идентификаторы таблиц.Если вы не хотите или не имеете возможности менять свойства метаданных в конфигураторе 1С (например, если конфигурация находится на поддержке и закрыта для изменений), проблему можно решить административными средствами непосредственно в целевой базе данных.
Идея заключается в создании виртуального представления (SQL View), которое будет ссылаться на таблицу с зарезервированным именем, но само при этом будет иметь абсолютно «безопасное» имя с точки зрения синтаксиса (например, order_view).
Рассмотрим этот процесс на примере СУБД MySQL:
CREATE VIEW order_view AS
SELECT * FROM `order`;
order, а только что созданное представление order_view.
Запрос.Текст =
"ВЫБРАТЬ
| order_table.order_id КАК ИдентификаторЗаказа
|ИЗ
| ВнешнийИсточникДанных.Opencart.Таблица.order_view КАК order_table";
Этот способ является крайне надежным и часто практикуется системными архитекторами. Представление полностью прозрачно для платформы 1С: вы можете не только читать из него данные, но и выполнять операции записи (если СУБД поддерживает обновление конкретного представления).
Для разработчиков, работающих с СУБД MySQL, существует еще один элегантный способ подружить платформу 1С с зарезервированными именами без переименования таблиц и создания представлений. Это перевод сервера MySQL в режим совместимости со стандартами ANSI SQL.
По умолчанию MySQL использует для экранирования имен бэктики (`), в то время как платформа 1С при определенных условиях транслирует запросы, оборачивая имена таблиц в двойные кавычки ("). Если запустить MySQL со специальным флагом режима, СУБД начнет трактовать двойные кавычки как идентификаторы таблиц и полей (точно так же, как это делают MS SQL Server и PostgreSQL).
Чтобы активировать этот режим, выполните на сервере MySQL следующую команду:
SET GLOBAL sql_mode = 'ANSI_QUOTES';
Чтобы эта настройка сохранялась при перезапуске сервера MySQL, добавьте параметр в файл конфигурации сервера (my.cnf или my.ini) в секцию [mysqld]:
[mysqld]
sql_mode="ANSI_QUOTES"
После включения этого режима СУБД MySQL будет без проблем выполнять запросы, генерируемые платформой 1С, даже если имена таблиц содержат зарезервированные слова или спецсимволы, обернутые в двойные кавычки.
Мы проанализировали три надежных способа обхода ограничений при работе с зарезервированными именами во внешних источниках данных 1С. Подведем итог, какой метод выбрать: