При работе с клиент-серверными базами данных 1С иногда возникают ситуации, когда сторонние системы записывают данные напрямую в таблицы MS SQL Server, минуя объектную модель 1С. Основная сложность заключается в том, что платформа 1С не знает о существовании этих записей, так как не срабатывают стандартные события конфигуратора, такие как ПередЗаписью или ПриЗаписи. В данной статье мы подробно разберем, как решить эту задачу, рассмотрим технические нюансы хранения GUID и предложим несколько эффективных стратегий мониторинга.
Прежде чем переходить к решениям, проанализируем ситуацию. Платформа 1С — это не просто надстройка над базой данных, а полноценный сервер приложений с собственной логикой кэширования. Когда сторонняя база данных выполняет команду INSERT INTO непосредственно в таблицу справочника (например, _Reference18X1), сервер приложений 1С об этом не уведомляется. В результате:
Рассмотрим наиболее надежный и часто используемый метод, который обсуждался на форуме. Суть заключается в том, чтобы создать механизм оповещения 1С о появлении новых данных через специальный маркер.
Для реализации этого метода нам потребуется изменить структуру справочника, добавив в него новый реквизит, например, НоваяЗапись (тип Булево), и обязательно проиндексировать его. Процесс будет выглядеть следующим образом:
INSERT устанавливает значение этого поля в TRUE (в SQL это будет 1).НоваяЗапись = Истина.Ложь.Пример запроса для регламентного задания в 1С:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СправочникТест.Ссылка КАК Ссылка
|ИЗ
| Справочник.ТестовыйСправочник КАК СправочникТест
|ГДЕ
| СправочникТест.НоваяЗапись = ИСТИНА";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
// Выполняем необходимую логику обработки
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.НоваяЗапись = Ложь;
Объект.Записать();
КонецЦикла;
Один из критических моментов при прямой записи в SQL — это генерация поля _IDRRef. Как отмечалось в дискуссии, 1С использует уникальные идентификаторы (UUID), но хранит их в SQL в бинарном виде BINARY(16).
Важное замечание: 1С использует специфический порядок байтов. Если вы просто используете NEWID() в SQL, вы получите «битый» идентификатор, который будет некорректно отображаться в 1С. Разберем по шагам, как правильно генерировать GUID на стороне SQL:
Стандартный GUID в SQL имеет структуру AAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE. Для корректной работы в 1С части этого GUID должны быть переставлены. Обычно это реализуется через сложную конвертацию. Рассмотрим пример функции на T-SQL для создания «правильного» идентификатора:
DECLARE @Guid UNIQUEIDENTIFIER = NEWID();
DECLARE @BinaryGuid BINARY(16);
SET @BinaryGuid = CAST(
SUBSTRING(CAST(@Guid AS BINARY(16)), 13, 4) +
SUBSTRING(CAST(@Guid AS BINARY(16)), 11, 2) +
SUBSTRING(CAST(@Guid AS BINARY(16)), 9, 2) +
SUBSTRING(CAST(@Guid AS BINARY(16)), 1, 8)
AS BINARY(16));
-- Теперь @BinaryGuid можно вставлять в поле _IDRRef
Если проигнорировать этот момент, вы рискуете получить дубли или ошибки при попытке обращения к объекту из кода 1С через ПолучитьСсылку(Новый УникальныйИдентификатор(...)).
Если регламентное задание «раз в минуту» работает слишком медленно, а бизнес-требования требуют моментальной реакции, проанализируем вариант использования SQL-триггеров.
Хотя напрямую вызвать код 1С из SQL-триггера невозможно, можно использовать механизм SQLCLR или системные хранимые процедуры для отправки HTTP-запроса к 1С. Многие разработчики жалуются, что «не получается авторизоваться из SQL». Это решается использованием заголовка Authorization.
Посмотрим на пример логики триггера, который дергает HTTP-сервис 1С:
_Reference18X1 вешается триггер AFTER INSERT.MSXML2.ServerXMLHTTP.POST запрос к опубликованному HTTP-сервису 1С с передачей ID новой записи.Пример (требует включения Ole Automation Procedures):
CREATE TRIGGER [dbo].[tr_OnInsert_1C_Record]
ON [dbo].[_Reference18X1]
AFTER INSERT
AS
BEGIN
DECLARE @Object INT;
DECLARE @Status INT;
EXEC sp_OACreate 'MSXML2.ServerXMLHTTP', @Object OUT;
EXEC sp_OAMethod @Object, 'open', NULL, 'POST', 'http://yourserver/base/hs/integration/notify', 'false';
EXEC sp_OAMethod @Object, 'setRequestHeader', NULL, 'Authorization', 'Basic <Base64String>';
EXEC sp_OAMethod @Object, 'send', NULL, '{"status": "new"}';
EXEC sp_OADestroy @Object;
END
Внимание: Использование триггеров на таблицах 1С является «грязным» хаком. При обновлении конфигурации таблицы могут пересоздаваться, и триггер будет удален. Всегда делайте резервные копии скриптов создания таких триггеров.
Если вы не хотите менять структуру таблиц 1С (добавлять флаги) и не хотите рисковать с триггерами, рекомендуем рассмотреть технологию CDC. Это встроенный механизм SQL Server, который фиксирует все изменения в выбранных таблицах и записывает их в отдельные системные таблицы.
Разберем преимущества этого подхода:
В этом случае 1С раз в несколько секунд может опрашивать таблицу изменений CDC, что гораздо быстрее, чем делать SELECT по всей таблице справочника.
Проанализируем важный юридический аспект. Согласно лицензионной политике «1С:Предприятие», прямое чтение и запись в таблицы базы данных SQL (кроме использования внешних источников данных) запрещены. Технически это работает, но в случае официального аудита или возникновения ошибок целостности данных, поддержка может отказать в помощи.
Рекомендация: Если есть возможность, все же убедите сторонних разработчиков использовать Web-сервисы или HTTP-сервисы. Проблема авторизации из T-SQL, упомянутая в теме, обычно связана с неправильной кодировкой учетных данных в формате Base64 или настройками брандмауэра. Использование стандартных API 1С гарантирует, что все GUID будут созданы правильно, а кэш сервера приложений обновится мгновенно.
Подведем итоги нашего исследования:
_IDRRef на стороне SQL обязательно учитывайте порядок байтов, специфичный для 1С._Version. 1С использует его для контроля версий объектов. Если вы оставите его пустым или запишете некорректное значение, пользователь может столкнуться с ошибкой «Данные изменены или удалены другим пользователем».