Как решить ошибку конвертации даты при записи в СУБД Firebird из 1С?

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

Интеграция сторонних баз данных с платформой «1С:Предприятие» через механизм Внешних источников данных — это мощный инструмент, упрощающий обмен информацией и построение сквозных бизнес-процессов. Однако при попытке не просто прочитать, но и записать данные обратно в стороннюю СУБД, разработчики часто сталкиваются со специфическими ошибками совместимости типов данных. Одной из самых распространенных является ошибка конвертации даты при работе с СУБД Firebird через ODBC-драйвер.

В этой статье мы подробно проанализируем, почему возникает ошибка conversion error from string при попытке обновить запись в таблице Firebird, разберем причины конфликта типов данных и рассмотрим три эффективных способа решения этой проблемы в зависимости от ваших задач и уровня доступа к сторонней базе данных.

Почему возникает ошибка под капотом СУБД?

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


СтрокаВИ = ВнешниеИсточникиДанных.ВИ.Таблицы.COUNTERD.НайтиПоПолю("ID", 2);
ОбТекстрока = СтрокаВИ.ПолучитьОбъект();
ОбТекстрока.DELTA = 36;
ОбТекстрока.Записать();

При выполнении метода Записать() платформа генерирует и отправляет через ODBC-драйвер SQL-запрос обновления (UPDATE). В результате мы получаем ошибку следующего вида:

Ошибка ODBC. SQLSTATE: HY000. Номер ошибки: -413. Описание: [ODBC Firebird Driver][Firebird]conversion error from string "2019-11-29 00:00:00"

Выясним причину такого поведения. Дело в принципиальном различии хранения типов даты и времени в 1С и Firebird:

  1. Особенности типа «Дата» в 1С: В платформе 1С тип данных Дата всегда является составным — он содержит и календарную дату, и время (даже если время не указано в явном виде, оно по умолчанию равно 00:00:00).
  2. Строгая типизация Firebird (Dialect 3): В базах данных Firebird (начиная с Dialect 3) типы строго разделены. Поле DATE хранит исключительно дату (без времени), поле TIME — только время, а поле TIMESTAMP — дату и время одновременно.
  3. Суть конфликта: При записи объекта 1С пытается передать в СУБД значения всех реквизитов сущности. Поле DELTADATE, имеющее в Firebird тип DATE, получает от 1С строковое представление даты и времени в формате "YYYY-MM-DD HH:MM:SS". Драйвер ODBC пытается напрямую записать эту строку в поле DATE. Поскольку в Firebird Dialect 3 неявное приведение строки формата Timestamp к чистому типу DATE запрещено, СУБД возвращает ошибку -413.
  4. Проблема пустой даты: Ситуация усугубляется, если дата в 1С не заполнена. Платформа отправляет пустую дату как "0001-01-01 00:00:00", что гарантированно вызывает сбой при парсинге ODBC-драйвером.

Способ 1. Исключение неиспользуемых полей из метаданных 1С

Если для бизнес-логики вашей задачи поля с датой (например, DELTADATE и DELTATIME) обновлять не требуется, а нужно лишь изменить числовой показатель DELTA, самым простым и безопасным решением будет редактирование состава внешнего источника данных в конфигураторе 1С.

Разберем этот процесс по шагам:

  1. Откройте конфигуратор вашей базы данных 1С.
  2. Найдите нужный внешний источник данных в ветке метаданных и перейдите к списку его таблиц.
  3. Откройте свойства таблицы (в нашем примере это COUNTERD) и перейдите на вкладку Поля.
  4. Снимите флажки или полностью удалите из списка полей те колонки, которые имеют тип данных Дата и вызывают ошибку конвертации.
  5. Сохраните конфигурацию базы данных.

После этого платформа 1С при вызове метода Записать() больше не будет пытаться передавать значения этих полей в SQL-запросе UPDATE. Это мгновенно решит проблему со строковой ошибкой приведения типов.

Борьба с сопутствующими триггерами СУБД (Ошибка -836)

Иногда после исключения проблемных полей из метаданных 1С мы можем натолкнуться на другую ошибку СУБД:

Ошибка ODBC. SQLSTATE: HY000. Номер ошибки: -836. Описание: [ODBC Firebird Driver][Firebird]exception 9. E_EDIT_FORBIDDEN. Редактирование запрещено. At trigger 'UPD_BEF_COUNTERD0'

Проанализируем ситуацию. Данная ошибка означает, что на стороне Firebird сработал внутренний триггер (в данном случае UPD_BEF_COUNTERD0, выполняющийся перед обновлением записи), который заблокировал транзакцию. Это происходит по следующим причинам:

Чтобы решить эту проблему, необходимо проанализировать триггер внутри СУБД Firebird. Сделать это из 1С напрямую невозможно. Выполните следующие действия:

  1. Используйте специализированную утилиту администрирования баз данных Firebird (например, IBExpert, FlameRobin или стандартную консоль isql).
  2. Подключитесь к вашей базе данных под учетной записью администратора (обычно это SYSDBA).
  3. Найдите таблицу COUNTERD и перейдите к списку её триггеров.
  4. Изучите код триггера UPD_BEF_COUNTERD0. Скорее всего, вы обнаружите условие, которое запрещает редактирование записи, если определенные поля пусты или не соответствуют заданным критериям безопасности.
  5. Согласуйте изменение логики триггера или временно деактивируйте его, если это допускается регламентом работы с базой данных.

Способ 2. Запись данных через прямой SQL-запрос с явным приведением типов (CAST)

Если изменять структуру таблиц СУБД запрещено, а редактировать метаданные 1С нежелательно, мы можем отказаться от высокоуровневой объектной техники записи 1С (метода Записать()) и перейти к использованию прямых параметризованных SQL-запросов. Это позволит нам полностью контролировать передаваемый в СУБД синтаксис и использовать встроенные функции преобразования типов.

Рассмотрим пример реализации такого подхода с использованием явного приведения типов с помощью конструкции CAST на стороне Firebird. Для этого воспользуемся возможностями прямого выполнения запросов во внешнем источнике данных или через внешнее соединение ADODB.Connection:


// Пример записи данных через прямое выполнение SQL-запроса
ТекстЗапроса = "UPDATE COUNTERD 
                SET DELTA = ?, 
                    DELTADATE = CAST(? AS DATE) 
                WHERE ID = ?";

// В параметр для DELTADATE передается строка из 1С в формате "YYYY-MM-DD"
// Использование CAST(? AS DATE) заставит Firebird корректно преобразовать строку

Использование конструкции CAST(? AS DATE) заставляет Firebird самостоятельно и корректно преобразовать переданную из 1С строку в соответствующий тип данных DATE на этапе компиляции SQL-запроса, полностью исключая возникновение ошибки -413.

Способ 3. Изменение типов данных на стороне СУБД Firebird

Если вы являетесь администратором или разработчиком интегрируемой базы данных Firebird, самым надежным и архитектурно правильным решением будет изменение типа данных самой колонки. Если изменить тип поля DELTADATE с DATE на TIMESTAMP, это решит проблему совместимости раз и навсегда.

Тип TIMESTAMP в Firebird хранит и дату, и время, поэтому он без каких-либо ошибок и дополнительных преобразований принимает строковые значения формата "YYYY-MM-DD HH:MM:SS", которые 1С передает по умолчанию при записи объектов внешних источников данных.

Для изменения типа поля в Firebird выполните следующий SQL-скрипт:

ALTER TABLE COUNTERD ALTER COLUMN DELTADATE TYPE TIMESTAMP;

После этого обновите структуру внешнего источника данных в 1С. Объектная техника записи начнет работать в штатном режиме без ошибок конвертации и без необходимости переписывать код на стороне 1С.

Важные рекомендации по настройке ODBC и окружения

При работе с внешними источниками данных через ODBC также крайне важно обращать внимание на технические нюансы окружения:

Применяя описанные подходы, мы сможем эффективно настроить стабильный обмен данными между «1С:Предприятием» и СУБД Firebird, избегая ошибок преобразования типов и конфликтов с внутренними триггерами базы данных.

← На главную