Работа с внешними базами данных через технологию ADODB — стандартная задача для интеграции 1С с другими системами (MS SQL, MySQL, PostgreSQL и др.). Однако при попытке обновить данные программисты часто сталкиваются с тем, что код выполняется без ошибок, но данные в таблице-источнике не меняются, либо обновляется только одна запись вместо группы. В этой статье мы подробно разберем, как правильно настроить объект Recordset, какие параметры выбрать и как избежать распространенных ошибок.
Рассмотрим типичную ситуацию: вы открываете набор записей (Recordset), находите нужные строки, меняете значения полей и вызываете метод Update(). Если обновление не происходит, причина обычно кроется в одном из трех факторов:
Update() работает только с текущей записью. Если записей в наборе много, а цикл обхода не прописан, изменения коснутся только первой строки.Recordset должен содержать первичный ключ (Primary Key) таблицы, чтобы ADO могло идентифицировать строку в базе.Проанализируем базовый код и выясним, как превратить его в рабочий инструмент.
Для того чтобы набор записей был доступен для редактирования, необходимо правильно указать параметры в методе Open. Рассмотрим синтаксис:
Recordset.Open(Source, ActiveConnection, CursorType, LockType)
Разберем значения, которые критически важны для записи данных:
1 (adOpenKeyset) или 2 (adOpenDynamic). Это позволяет видеть изменения других пользователей и, что важнее, вносить свои. Статический курсор (3) часто используется для клиентских наборов данных.1 (ReadOnly). Для редактирования нужно установить 3 (adLockOptimistic — оптимистическая блокировка, запись блокируется только в момент вызова Update).3 (adUseClient), ADO копирует данные на сторону клиента. Это удобно для 1С, но накладывает свои ограничения на типы курсоров.Пример правильной инициализации объекта в 1С:
Connection = Новый COMОбъект("ADODB.Connection");
Connection.Open(СтрокаПодключения);
rs = Новый COMОбъект("ADODB.Recordset");
rs.CursorLocation = 3; // adUseClient
rs.LockType = 3; // adLockOptimistic
rs.CursorType = 1; // adOpenKeyset
CommandText = "SELECT * FROM MyTable WHERE Status = 'New'";
rs.Open(CommandText, Connection);
Частая ошибка новичков — попытка обновить весь набор записей одной командой Update(). Важно понимать: Recordset — это указатель на конкретную строку. Чтобы изменить все отобранные записи, необходимо организовать цикл с переходом по строкам.
Рассмотрим подробнее процесс обновления в цикле:
Пока НЕ rs.EOF() Цикл
// Устанавливаем новые значения полей для ТЕКУЩЕЙ записи
rs.Fields("Active").Value = 0;
rs.Fields("ProcessDate").Value = ТекущаяДата();
// Фиксируем изменения в текущей записи
rs.Update();
// Переходим к следующей строке (обязательно!)
rs.MoveNext();
КонецЦикла;
Важный нюанс: В некоторых конфигурациях ADO метод MoveNext() автоматически вызывает Update(), если данные в полях были изменены. Однако явный вызов Update() считается правилом хорошего тона и защищает от неожиданного поведения драйвера базы данных.
Многие программисты, пришедшие из мира Delphi или старого Access (DAO), пытаются вызвать метод rs.Edit() перед изменением полей. В ADODB этого метода не существует. Как только вы присваиваете значение свойству Value любого поля, запись автоматически переходит в режим редактирования.
Если вам нужно обновить тысячи записей одним и тем же значением, использование Recordset будет крайне неэффективным. На каждую запись 1С будет отправлять отдельный запрос к серверу БД, что создаст огромную нагрузку на сеть.
Проанализируем ситуацию: если логика позволяет, гораздо быстрее выполнить прямой DML-запрос (Data Manipulation Language). Для этого используется объект Command или метод Execute объекта Connection.
// Пример выполнения прямого апдейта
ТекстЗапроса = "UPDATE tbl1 SET Active = 0, UsrID = '" + ТекущийПользовательИД + "' WHERE msgid = " + ИдентификаторСообщения;
Попытка
Connection.Execute(ТекстЗапроса);
Исключение
Сообщить("Ошибка выполнения запроса: " + ОписаниеОшибки());
КонецПопытки;
Этот способ работает в десятки раз быстрее, так как вся операция выполняется на стороне сервера базы данных одним транзакционным пакетом.
При передаче данных из 1С в ADO всегда следите за типизацией. Например, уникальный идентификатор (GUID) в 1С является объектом. SQL-сервер его «не поймет», поэтому всегда приводите его к строке: Строка(Ссылка.УникальныйИдентификатор()).
Также будьте внимательны с датами. SQL-сервер часто ожидает дату в формате YYYYMMDD или YYYY-MM-DD HH:MM:SS. Для надежности используйте форматирование:
Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss")
Подведем итог. Чтобы обновление через Recordset сработало:
LockType установлен в значение 3 (Optimistic).SELECT-запросе присутствуют ключевые поля таблицы.Пока НЕ rs.EOF() и не забывайте про rs.MoveNext().UPDATE через Connection.Execute().Соблюдение этих простых правил сделает вашу работу с внешними базами данных в 1С стабильной и производительной.