Работа с файлами формата DBF (dBase) остается актуальной задачей при интеграции 1С с внешними системами, оборудованием или старыми базами данных. Одной из наиболее сложных проблем является запись данных в поля типа MEMO (длинный текст). Обычные SQL-запросы через метод Execute часто терпят неудачу, когда длина строки превышает 254 символа. В этой статье мы подробно разберем, почему это происходит и как правильно организовать запись больших объемов данных с использованием провайдера Visual FoxPro (VFPOLEDB).
Рассмотрим ситуацию: вы пытаетесь выполнить стандартный SQL-запрос INSERT INTO, передавая длинную строку непосредственно в тексте команды. Проанализируем типичную ошибку: Command contains unrecognized phrase/keyword или Syntax error. Причина кроется в архитектуре SQL-движка Visual FoxPro: строковые константы (литералы), заключенные в кавычки, имеют жесткое ограничение по длине — обычно это 254 или 255 символов.
Если ваша переменная ЗаписьМ содержит XML-структуру или длинное описание товара, парсер драйвера просто не сможет обработать такую длинную строку внутри текста команды. Чтобы обойти это ограничение, нам необходимо передавать данные не как текст команды, а как параметры.
Самый надежный и профессиональный способ записи в поля типа MEMO — это использование объекта ADODB.Command. Этот метод позволяет передавать данные во внутренний буфер драйвера напрямую, минуя парсер SQL-текста. Разберем этот процесс по шагам.
Сначала создадим соединение и саму таблицу. Обратите внимание на тип поля M (Memo) в команде CREATE TABLE:
Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionString = "Provider=vfpoledb.1;Data Source=" + КаталогДляВыгрузки + ";";
Соединение.Mode = 3; // adModeReadWrite
Соединение.Open();
// Создаем таблицу с полем CODE2 (строка) и INFO (Memo)
Соединение.Execute("CREATE TABLE Calculation.dbf (CODE2 C(10) NOT NULL, INFO M NOT NULL)");
Теперь подготовим команду для вставки данных. Вместо конкретного значения в SQL-запросе мы ставим знак вопроса ?, который служит плейсхолдером для параметра:
// Создаем объект команды
Command = Новый COMОбъект("ADODB.Command");
Command.ActiveConnection = Соединение;
Command.CommandText = "INSERT INTO Calculation (CODE2, INFO) VALUES ('" + Строка(КодТовара) + "', ?)";
// Создаем и настраиваем параметр для поля MEMO
// Используем тип 201 (adLongVarChar) для длинных строк или 129 (adChar)
param = Command.CreateParameter("PINFO", 201, 1, 1000000, ЗначениеМемоПоля);
// Добавляем параметр в коллекцию команды
Command.Parameters.Append(param);
// Выполняем запись
Command.Execute();
Соединение.Close();
Рассмотрим подробнее параметры метода CreateParameter:
201 соответствует adLongVarChar. Это наиболее подходящий тип для Memo-полей. Иногда используют 129 (adChar), но для очень больших текстов лучше выбирать Long-типы.1 означает adParamInput (входной параметр).Если работа с объектом Command кажется избыточной, можно воспользоваться объектом Recordset. Этот метод удобен тем, что драйвер сам управляет записью в связанные файлы .fpt (в которых физически хранятся данные MEMO-полей).
Проанализируем пример записи через Recordset:
RecordSet = Новый COMОбъект("ADODB.Recordset");
// Открываем таблицу. 1 - adOpenKeyset, 3 - adLockOptimistic
RecordSet.Open("SELECT * FROM Calculation", Соединение, 1, 3);
RecordSet.AddNew();
RecordSet.Fields("CODE2").Value = "001";
RecordSet.Fields("INFO").Value = ЗаписьМ; // 1С передаст строку любой длины
RecordSet.Update();
RecordSet.Close();
Этот способ часто работает медленнее при массовой загрузке, но он гораздо стабильнее в плане обработки спецсимволов и кодировок, так как вы работаете напрямую с полями объекта базы данных.
При работе с MEMO-полями в формате DBF важно помнить о нескольких критических моментах, которые могут повлиять на результат:
.dbf, а в отдельном файле с расширением .fpt. Если вы переносите базу данных, всегда копируйте пару файлов (DBF + FPT) вместе. Если FPT-файл будет отсутствовать или поврежден, DBF-файл не откроется.Extended Properties="Codepage=1251;" или CharSet=1251;.VFPOLEDB как для записи, так и для чтения..fpt быстро растет, так как старые блоки данных не удаляются автоматически. В полноценном FoxPro для этого используется команда PACK, но через OLE DB это сделать сложно (требуется эксклюзивный доступ). Иногда проще пересоздать файл при полной выгрузке.Подведем итог: для успешной записи длинных текстов в DBF используйте связку ADODB.Command и ADODB.Parameter. Это снимет все ограничения на длину строки и обеспечит корректную передачу данных в поле типа M.