Как исправить ошибку "Record is not locked" при выполнении UPDATE запроса к DBF базе 1С v7.7 через VFPOLEDB?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При работе с базами данных 1С v7.7, хранящимися в формате DBF, иногда возникает необходимость в прямом редактировании данных без использования штатных механизмов конфигуратора или платформы. Один из способов решения такой задачи — это использование OLEDB-провайдера Visual FoxPro (VFPOLEDB.1) для выполнения SQL-запросов. Однако, при попытке выполнить команду UPDATE, пользователи часто сталкиваются с ошибкой "FAILED! ICommandText::Execute(): Record is not locked.". Давайте разберем, почему возникает эта ошибка и как ее эффективно устранить, а также рассмотрим другие подводные камни при работе с VFPOLEDB.

Понимание проблемы: "Record is not locked"

Ошибка "Record is not locked" указывает на то, что операция записи (в нашем случае, UPDATE) не может быть выполнена, поскольку запись или таблица заблокированы. В контексте DBF-файлов и Visual FoxPro это может происходить по нескольким причинам:

  1. Неправильные настройки сессии OLEDB: По умолчанию, драйвер может не иметь достаточных прав или не настроен на правильную обработку блокировок файлов в многопользовательской среде.
  2. Монопольный доступ к файлам: Если база 1С v7.7 открыта в монопольном режиме другим процессом (например, самой платформой 1С), это может блокировать доступ для любых внешних операций записи.
  3. Некорректный синтаксис SQL-запроса: Хотя сама ошибка "Record is not locked" может не напрямую указывать на синтаксис, неправильно сформированный запрос может приводить к проблемам с позиционированием на записи или некорректной попытке ее модификации.
  4. Проблемы с индексами (CDX): Иногда изменения в данных не отражаются или вызывают ошибки, если связанные индексные файлы (CDX) не обновляются корректно.

Шаг 1: Инициализация OLEDB-соединения с учетом особенностей Visual FoxPro

Для успешной работы с DBF-файлами 1С v7.7 через VFPOLEDB.1 необходимо правильно инициализировать объект OLEDBData и выполнить ряд команд EXECSCRIPT. Эти команды настраивают среду Visual FoxPro, управляя блокировками, кэшированием и проверкой таблиц.

Настройки строки соединения

Прежде всего, убедимся, что строка соединения указана корректно, включая режим записи Mode=ReadWrite:


ОлеДБ = СоздатьОбъект("OLEDBData");
Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ() + ";Mode=ReadWrite;Collating Sequence=MACHINE";
Если ОлеДБ.Соединение(Соединение) = 0 Тогда
    Сообщить("Не соединились");
    Возврат;
КонецЕсли;

Здесь КаталогИБ() возвращает путь к вашей информационной базе 1С v7.7. Параметр Collating Sequence=MACHINE обеспечивает сравнение строк без учета регистра и специфики национальных алфавитов, что важно для корректной работы с 1С.

Команды EXECSCRIPT для управления средой Visual FoxPro

После установки соединения, нам нужно выполнить несколько системных команд Visual FoxPro через метод Выполнить объекта СоздатьКоманду(). Эти команды критически важны для обхода типичных проблем с блокировками и кэшированием:

  1. SET ANSI OFF: Эта команда отключает режим ANSI SQL. Visual FoxPro имеет свой диалект SQL, и отключение режима ANSI помогает избежать конфликтов и обеспечить правильную интерпретацию запросов, особенно при использовании специфических конструкций.
  2. SET REPROCESS TO 60 SECONDS: Устанавливает, как долго (в секундах) Visual FoxPro будет пытаться повторно получить доступ к заблокированному файлу или записи. Если файл заблокирован, VFP будет ждать до 60 секунд, прежде чем выдать ошибку. Это помогает при временных блокировках.
  3. SET REFRESH TO 0,-1: Контролирует кэширование данных. Значения 0,-1 указывают на то, что буферы данных не будут автоматически обновляться с диска, и что при каждом обращении к данным будет выполняться чтение с диска. Это гарантирует, что мы всегда работаем с актуальными данными и не сталкиваемся с проблемами кэширования старых состояний таблицы.
  4. SET TABLEVALIDATE TO 0: Отключает проверку целостности таблиц при их открытии. В некоторых случаях, проверка таблиц может приводить к временным блокировкам заголовков DBF-файлов, особенно при совместном доступе. Отключение этой проверки может помочь избежать ошибок блокировки.

Полный блок инициализации будет выглядеть так:


ОлеДБ = СоздатьОбъект("OLEDBData");
Соединение = "Provider=vfpoledb.1;Mode=ReadWrite;Data Source="+КаталогИБ()+";Collating Sequence=machine;";
Если ОлеДБ.Соединение(Соединение)=0 Тогда
    Сообщить("Не соединились");
    Возврат;
КонецЕсли;

рс = ОлеДБ.СоздатьКоманду();

// Настройки среды Visual FoxPro
рс.Выполнить("EXECSCRIPT('SET ANSI OFF')");  
рс.Выполнить("EXECSCRIPT('SET REPROCESS TO 60 SECONDS')");
рс.Выполнить("EXECSCRIPT('SET REFRESH TO 0,-1')");    
рс.Выполнить("Exec('SET TABLEVALIDATE TO 0')");

// Важно: После всех настроек, создаем новую команду для выполнения UPDATE
рс = ОлеДБ.СоздатьКоманду();

Важно: После выполнения всех команд EXECSCRIPT, создайте новый объект команды (рс = ОлеДБ.СоздатьКоманду();) для выполнения основного запроса. Это гарантирует, что последующие запросы будут выполняться в новой настроенной сессии.

Шаг 2: Корректный синтаксис UPDATE запроса для VFPOLEDB

Одной из частых причин ошибки может быть некорректный синтаксис UPDATE запроса, который отличается от стандартного MS SQL или других диалектов. В Visual FoxPro SQL, при использовании псевдонимов таблиц, их необходимо указывать не только в секции FROM, но и в секции SET, а также при обращении к полям в WHERE.

Пример неверного синтаксиса и его последствия

Изначальный запрос автора, который приводил к ошибке "Record is not locked" или "Column is not found", выглядел примерно так (с учетом отладочной информации):


// Пример некорректного запроса, который приводил к ошибке
ТекстЗапроса = "
|UPDATE  
|    ra405
| SET sp408 = '   3TB   ' 
|FROM ra405 AS Tab
|where (Tab.IDDOC = '   2T   ')
| AND  (Tab.sp408 = '   IG   ')
|";

В этом запросе есть несколько потенциальных проблем:

  1. В секции SET используется только имя поля sp408, без указания псевдонима таблицы Tab. Это может быть причиной, по которой драйвер не может однозначно определить, какое поле обновлять.
  2. Для UPDATE в VFP SQL часто требуется явное указание псевдонима в секции SET, если он используется в FROM.
  3. При отсутствии FROM или неправильном использовании псевдонимов, может возникать ошибка "Column ' ' is not found".

Корректный синтаксис UPDATE запроса

Правильный синтаксис UPDATE для VFPOLEDB, который успешно решил проблему автора, выглядит следующим образом:


ТекстЗапроса = "
|UPDATE  
|    Tab
| SET $Tab." + тзПотомки.Реквизит + " = :Объект 
|FROM $" + тзПотомки.Метаданные + " AS Tab
|where (Tab.IDDOC = :Док)
| AND  ($Tab." + тзПотомки.Реквизит + " = :Источник)
|";

Давайте рассмотрим ключевые отличия и объяснения:

  1. UPDATE Tab: В секции UPDATE мы указываем псевдоним таблицы (Tab), который определен в секции FROM. Это критически важно для VFPOLEDB.
  2. SET $Tab.Реквизит = :Объект: При обращении к полю, которое нужно обновить, мы явно используем псевдоним таблицы Tab (например, $Tab.sp408). Префикс $ перед именем поля указывает на то, что это поле метаданных 1С, что является стандартной практикой при работе с DBF-файлами 1С.
  3. FROM $Метаданные AS Tab: Секция FROM используется для определения таблицы, к которой применяется обновление, и присвоения ей псевдонима Tab. Здесь $Метаданные представляет собой физическое имя DBF-файла 1С (например, $ra405 для регистра накопления).
  4. where (Tab.IDDOC = :Док) AND ($Tab.Реквизит = :Источник): В секции WHERE также обязательно используем псевдоним таблицы (Tab.IDDOC, $Tab.Реквизит) для фильтрации записей.

После подготовки запроса, устанавливаем параметры:


рс.УстановитьТекстовыйПараметр("Объект", Приемник);
рс.УстановитьТекстовыйПараметр("Источник", Источник);
рс.УстановитьТекстовыйПараметр("Док", Док.ТекущийДокумент());

И затем выполняем запрос:

рс.ВыполнитьИнструкцию(ТекстЗапроса);

С таким синтаксисом запрос будет корректно интерпретирован VFPOLEDB, и операция UPDATE должна пройти успешно, устраняя ошибку "Record is not locked".

Шаг 3: Проверка результатов и отладка

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

Использование Запрос.Отладка(1)

Для проверки корректности сформированного SQL-запроса перед его выполнением, используйте метод Отладка(1):


// Устанавливаем режим отладки для вывода текста запроса
рс.Отладка(1); 
рс.ВыполнитьИнструкцию(ТекстЗапроса);
рс.Отладка(0); // Отключаем режим отладки

Эта команда выведет окончательный текст запроса (с подставленными значениями параметров) в окно сообщений 1С, что позволит вам визуально проверить синтаксис и значения.

Повторная проверка данных

После выполнения UPDATE запроса, всегда рекомендуется выполнить SELECT запрос к той же таблице с теми же условиями, чтобы убедиться, что данные были изменены. Вы можете также переоткрыть 1С v7.7 или обновить соответствующие отчеты, чтобы увидеть, отразились ли изменения в пользовательском интерфейсе. Иногда могут возникать проблемы с кэшированием данных в самой платформе 1С, если файлы были изменены напрямую.

Дополнительные аспекты: Ошибка "База данных не установлена"

В ходе работы с OLEDB, помимо проблем с UPDATE, может возникнуть ошибка "База данных не установлена" при выполнении SELECT запросов. Эта ошибка указывает на то, что OLEDB-провайдер не смог определить базу данных или каталог, с которым он должен работать.

Причина ошибки

Как правило, эта ошибка возникает, если вы используете код, предназначенный для работы со SQL-базой (например, 1С++ для SQL), или если строка подключения не содержит параметра Data Source с указанием пути к DBF-файлам. Автор столкнулся с этой проблемой, когда случайно использовал блок кода без явной строки подключения к DBF-базе.

Решение

Убедитесь, что в вашей строке соединения явно указан путь к каталогу информационной базы 1С v7.7. Например:


Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ() + ";Mode=ReadWrite;Collating Sequence=MACHINE";

Здесь Data Source=" + КаталогИБ() + " указывает на каталог, где расположены DBF-файлы вашей базы данных. Без этого параметра провайдер не сможет "установить" базу данных и выдаст соответствующую ошибку.

Заключение

Прямое манипулирование DBF-файлами 1С v7.7 через VFPOLEDB.1 является мощным инструментом, но требует глубокого понимания особенностей Visual FoxPro SQL и механизмов блокировки файлов. Следуя описанным шагам — правильная инициализация OLEDB-соединения с помощью команд EXECSCRIPT и использование корректного синтаксиса UPDATE запроса с явным указанием псевдонимов таблиц — вы сможете успешно выполнять операции записи и избежать распространенных ошибок, таких как "Record is not locked". Всегда помните о необходимости резервного копирования данных перед выполнением прямых изменений.

← На главную