Вход | Регистрация
 
1С:Предприятие :: 1С:Предприятие 7.7 и ранее

v7: Доступ через vfpoledb.1 к таблице DBF

v7: Доступ через vfpoledb.1 к таблице DBF
Я
   maestro-72
 
05.10.20 - 09:47
Добрый день!
Столкнулся с проблемой доступа к данным через АДО (ну перепробовал много вариантов ничего не помогает) Смысл в следующем, имеется куча таблиц DBF к ним доступ из сети, пользователи с ними работают через писанную ранее оболочку все здорово, но из этих таблиц нужно быстро сформировать новые. Делал через XBASE все работает, но очень долго. Попробовал через АДО и наткнулся на то что для некоторых таблиц выдается сообщение: имя таблицы has become corrupted. The table will need to be repaired before using again. Все, тупик... Пробовал разные провайдеры, пытался найти консольную утилиту, чтобы исправить заголовок таблицы. Все тщетно. А очень  хочется чтобы решалась задача через запрос из за скорости выполнения последнего. Вивер эти поврежденные таблицы открывает без проблем, после открытия вивером проблем с запросом нет.  Вопрос собственно - как заставить запрос игнорировать данную ошибку (я подозреваю что в заголовке неверно указано количество строк) или посоветуйте утилиту консольную которой можно было бы в случае неудачи поправить заголовок и выполнить запрос повторно.

Делаю так:
База = СоздатьОбъект("OLEDBData");
Соединение="Provider=vfpoledb.1;Mode=ReadWrite;Data Source=" Сок ЛП(ВыбКаталог) "BAZA\" ";Collating Sequence=machine;";
;
Если База.Соединение(Соединение)=0 Тогда
Сообщить("Не соеденились");
Возв ат;
КонецЕсли;
Зап осСКЛ = База.СоздатьКоманду();

Вот тут дальше в цикле

Запрос = "INSERT INTO """ СокрЛП(ТЗСопост.Путь) "\" "BAZA\" СокрЛП(ИмяФ) """ Select * from """ СокрЛП(ПутьФ) СокрЛП(ИмяФ) """ WHERE GRWK in (" СокрЛП(ТЗСопост.СтрGRWK) ")";
Попытка
ЗапросСКЛ.Выполнить(Запрос);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

Какие то таблицы норм, а на каких то вылетает с верхней ошибкой. Прошу помощи
   Mikeware
 
1 - 05.10.20 - 09:54
а что поправляет вьюер в "битых" таблицах?
   Mikeware
 
2 - 05.10.20 - 09:54
Да, и работу даже через xbase можно сильно ускорить, используя индексы.
   maestro-72
 
3 - 05.10.20 - 10:00
Я не знаю, в индексе нет требуемого выражения, а запрос прекрасно справляется с таблицами без индекса. У некоторых таблиц нет индекса вообще (типа справочники)
   Mikeware
 
4 - 05.10.20 - 10:01
(3) ну так сделай индекс, какой нужно.
   maestro-72
 
5 - 05.10.20 - 10:02
(1) Не знаю что поправляет, но после открытия в DBFWiever таблица прекрасно обрабатывается запросом. А вот фокс ее не открывает (туже ошибку выдает
   maestro-72
 
6 - 05.10.20 - 10:06
(4) Все равно это построчное чтение и запись, скорости далеки от Insert
   Mikeware
 
7 - 05.10.20 - 10:09
(5) ну так посмотри. сделай копию, сравни после открытия сравнивалкой бинарников
   Злопчинский
 
8 - 05.10.20 - 10:09
(5) ну так сравни до и после проблемный дбф.
   Mikeware
 
9 - 05.10.20 - 10:09
(6) а инсерт не построчно делает? :-)
   Андроны едут
 
10 - 05.10.20 - 10:12
(5) что мешает поправить файлы открытием в дбвивере с помощью обработки или батника.
   maestro-72
 
11 - 05.10.20 - 10:15
(9) Построчно, только 1с это делает на порядок медленнее. Я сравнивал скорости чтения при работе в Delphi с DBF и XBASE так вот ощущение, что в XBASE мы в Москву через Пекин добираемся
   maestro-72
 
12 - 05.10.20 - 10:16
(10) Да, хочу консольное приложение блабла.EXE таблица.DBF поправил и запрос к ней сделал, не нашел нигде, везде либо виверы либо надо через приложение открывать таблицу интерактивно
   maestro-72
 
13 - 05.10.20 - 10:17
Как то прям грустно, механизм есть, а такой капризный к таблицам и путей обхода не наблюдается
   Злопчинский
 
14 - 05.10.20 - 10:19
Не суетись.
все получится.
   tgu82
 
15 - 05.10.20 - 10:28
(0) Когда-т о на турбопаскале писал программку которая записывала реальное количество строк в заголовлк ДБФ. Интересно что Clipper чихл на эти ошибки с высокой колокольни а вот фохпро ругался
   maestro-72
 
16 - 05.10.20 - 10:34
(15) Вот! Проблема Clipper. Не сохранилось ничего из наработок
   maestro-72
 
17 - 05.10.20 - 10:47
А 1с77 как то с  битами и байтами работает, я подумал может просто через XBASE запросить количество строк в таблице, и поправить в заголовке. Ну может через ADODB.Streem... ?
   Злопчинский
 
18 - 05.10.20 - 11:22
(17) внешними способами через FSO и прочие объекты ОС
   maestro-72
 
19 - 05.10.20 - 11:29
(18) Поискал, но чет не нашел примеров для замены байта. не соображу никак
   tgu82
 
20 - 05.10.20 - 11:37
*********************************************************************  
 * Назначение :     Приведение в соответствие значение количества записей   
 *        в заголовке таблице и реального количества записей  
 * Автор :     Владимир Максимов  
 * Дата :     31.08.2008  
 * Версия FoxPro: Visual FoxPro с 3 по 9  
 *        Возможно, этот код будет работать и в версиях FoxPro 2.x  
 *        если убрать объявления LOCAL и MessageBox()   
 *        Но это не проверялось  
 *********************************************************************  
    
* Пользователь выбирает файл для проверки  
* 5 параметр в функции GetFile() был введен только в версии Visual FoxPro 6  
 * для младших версий FoxPro его надо удалить  
  Local lcFileName  
  lcFileName = GetFile("DBF","","",0,"Выбор файла для проверки количества записей")  
  If Empty(m.lcFileName)  
     * Файл не был выбран  
      Return  
  EndIf  
    
 * Открываю файл и запоминаю его дескриптор (идентификатор)  
  Local lnFD  
  lnFD = Fopen(m.lcFileName,12)  
  If m.lnFD < 0  
      MessageBox("Не удалось открыть файл" + Chr(13) + ;  
          m.lcFileName + Chr(13) + ;  
          "Возможно, он открыт другим приложением")  
  EndIf  
    
 * Теоретически, здесь хорошо бы добавить проверку на тот факт,   
 * что данный файл - это DBF-таблица (анализ первого байта)  
 * Но в данном случае предполагается, что пользователь понимает, что он делает  
 * Если, тем не менее, Вы хотите создать универсальную утилиту, то  
 * посмотрите код программы CPZERO.PRG из поставки FoxPro.  
 * Эта программа находится в каталоге TOOLS\CPZERO корневой папки FoxPro  
    
 * Определяю количество записей записанное в заголовке файла  
 * байты с 4 по 7  
  LOCAL lnReccount  
  =FSEEK(m.lnFD,4)  
  lnReccount =    ASC(FREAD(m.lnFD,1)) + ;  
          ASC(FREAD(m.lnFD,1)) * 256 + ;  
          ASC(FREAD(m.lnFD,1)) * 256 * 256 + ;  
          ASC(FREAD(m.lnFD,1)) * 256 * 256 * 256  
                
 * Определяю позицию, с которой начинается собственно данные (первая запись)  
 * байты с 8 по 9  
  LOCAL lnDataStart  
  lnDataStart =     ASC(FREAD(m.lnFD,1)) + ;  
          ASC(FREAD(m.lnFD,1)) * 256  
    
 * Определяю количество символов в одной записи, включая метку на удаление  
 * байты с 10 по 11  
  LOCAL lnRecLength  
  lnRecLength =    ASC(FREAD(m.lnFD,1)) + ;  
          ASC(FREAD(m.lnFD,1)) * 256  
    
 * Определяю общий размер файла, через порядковый номер последнего байта  
  LOCAL lnFileSize  
  =FSEEK(m.lnFD,0,0)  
  lnFileSize = FSEEK(m.lnFD,0,2)  
    
 * Определяю значение самого последнего байта файла  
  LOCAL lnEndByte  
  =FSEEK(m.lnFD,-1,1)  
  lnEndByte = ASC(FREAD(m.lnFD,1))  
    
 * И реальное количество записей в файле  
  LOCAL lnFaktCount  
  DO CASE  
  CASE m.lnFileSize = m.lnDataStart  
     * Т.е. в таблице вообще нет информации  
      lnFaktCount = 0  
  CASE m.lnEndByte = 26  
     * Если последний байт файла имеет ASCII код 26 (0x1A),   
     * то общее число информационных байтов надо уменьшить на 1  
      lnFaktCount = (m.lnFileSize - m.lnDataStart - 1) / m.lnRecLength  
  OTHERWISE  
      lnFaktCount = (m.lnFileSize - m.lnDataStart) / m.lnRecLength  
  ENDCASE  
    
    
  LOCAL lnResult  
 * Анализ полученных результатов  
  DO CASE  
  CASE INT(m.lnFaktCount) <> m.lnFaktCount  
    
     * Есть дробная часть. Т.е. выделить целое количество записей невозможно  
     * повреждения более существенные, чем разница в количестве записей  
     * лучше ничего не трогать  
      lnResult = -1  
      =Fclose(m.lnFD)  
        
      MessageBox("Выделить целое количество записей невозможно"+Chr(13) + ;  
                  "Повреждения более существенные, чем разница в количестве записей")  
    
  CASE m.lnFaktCount <> m.lnReccount  
    
     * Записанное и фактическое количество записей отличаются  
     * корректирую записанное количество записей  
      =FSEEK(m.lnFD,4,0)  
      FOR lnI=1 TO 4  
          =FWRITE(m.lnFD,CHR(MOD(INT(m.lnFaktCount / 256**(m.lnI-1)),256)))  
      ENDFOR  
    
      lnResult = 1  
      =Fclose(m.lnFD)  
    
      MessageBox("Значение количества записей исправлено")  
    
  OTHERWISE  
    
     * Ошибки в определении количества записей не обнаружено  
      lnResult=0  
      =Fclose(m.lnFD)  
    
      MessageBox("Ошибки в количестве записей не обнаружено")  
    
  ENDCASE  
    
 * Результат возвращается на случай, если есть необходимость в подобном анализе  
  RETURN m.lnResult
   tgu82
 
21 - 05.10.20 - 11:37
вот что-то нашел
   tgu82
 
22 - 05.10.20 - 11:38
   tgu82
 
23 - 05.10.20 - 11:39
   Ёпрст
 
24 - 05.10.20 - 11:59
(0)
Запрос.Выполнить("Exec('SET TABLEVALIDATE TO 0')")
   Ёпрст
 
25 - 05.10.20 - 12:00
сделай перед инсертом
   maestro-72
 
26 - 05.10.20 - 12:01
(21) Ага, это я видел, не подходит, потому что надо чтобы было чтоб это автоматом шло из проги (23) этот тоже читал
   maestro-72
 
27 - 05.10.20 - 12:01
(24) Сейчас попробую
   maestro-72
 
28 - 05.10.20 - 12:02
Пока как вариант решения сложной проблемы. Неисправную таблицу просто копирую отдельно, делаю сжатие методом XBASE и потом все по ней отрабатывает на ура.
   maestro-72
 
29 - 05.10.20 - 12:08
(24) Отлично, жму руку! Тема закрыта, все получилось!


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.