Имя: Пароль:
1C
1C 7.7
v7: Доступ через vfpoledb.1 к таблице DBF
0 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) ")";
Попытка
ЗапросСКЛ.Выполнить(Запрос);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

Какие то таблицы норм, а на каких то вылетает с верхней ошибкой. Прошу помощи
1 Mikeware
 
05.10.20
09:54
а что поправляет вьюер в "битых" таблицах?
2 Mikeware
 
05.10.20
09:54
Да, и работу даже через xbase можно сильно ускорить, используя индексы.
3 maestro-72
 
05.10.20
10:00
Я не знаю, в индексе нет требуемого выражения, а запрос прекрасно справляется с таблицами без индекса. У некоторых таблиц нет индекса вообще (типа справочники)
4 Mikeware
 
05.10.20
10:01
(3) ну так сделай индекс, какой нужно.
5 maestro-72
 
05.10.20
10:02
(1) Не знаю что поправляет, но после открытия в DBFWiever таблица прекрасно обрабатывается запросом. А вот фокс ее не открывает (туже ошибку выдает
6 maestro-72
 
05.10.20
10:06
(4) Все равно это построчное чтение и запись, скорости далеки от Insert
7 Mikeware
 
05.10.20
10:09
(5) ну так посмотри. сделай копию, сравни после открытия сравнивалкой бинарников
8 Злопчинский
 
05.10.20
10:09
(5) ну так сравни до и после проблемный дбф.
9 Mikeware
 
05.10.20
10:09
(6) а инсерт не построчно делает? :-)
10 Андроны едут
 
05.10.20
10:12
(5) что мешает поправить файлы открытием в дбвивере с помощью обработки или батника.
11 maestro-72
 
05.10.20
10:15
(9) Построчно, только 1с это делает на порядок медленнее. Я сравнивал скорости чтения при работе в Delphi с DBF и XBASE так вот ощущение, что в XBASE мы в Москву через Пекин добираемся
12 maestro-72
 
05.10.20
10:16
(10) Да, хочу консольное приложение блабла.EXE таблица.DBF поправил и запрос к ней сделал, не нашел нигде, везде либо виверы либо надо через приложение открывать таблицу интерактивно
13 maestro-72
 
05.10.20
10:17
Как то прям грустно, механизм есть, а такой капризный к таблицам и путей обхода не наблюдается
14 Злопчинский
 
05.10.20
10:19
Не суетись.
все получится.
15 tgu82
 
05.10.20
10:28
(0) Когда-т о на турбопаскале писал программку которая записывала реальное количество строк в заголовлк ДБФ. Интересно что Clipper чихл на эти ошибки с высокой колокольни а вот фохпро ругался
16 maestro-72
 
05.10.20
10:34
(15) Вот! Проблема Clipper. Не сохранилось ничего из наработок
17 maestro-72
 
05.10.20
10:47
А 1с77 как то с  битами и байтами работает, я подумал может просто через XBASE запросить количество строк в таблице, и поправить в заголовке. Ну может через ADODB.Streem... ?
18 Злопчинский
 
05.10.20
11:22
(17) внешними способами через FSO и прочие объекты ОС
19 maestro-72
 
05.10.20
11:29
(18) Поискал, но чет не нашел примеров для замены байта. не соображу никак
20 tgu82
 
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
21 tgu82
 
05.10.20
11:37
вот что-то нашел
22 tgu82
 
05.10.20
11:38
23 tgu82
 
05.10.20
11:39
24 Ёпрст
 
гуру
05.10.20
11:59
(0)
Запрос.Выполнить("Exec('SET TABLEVALIDATE TO 0')")
25 Ёпрст
 
гуру
05.10.20
12:00
сделай перед инсертом
26 maestro-72
 
05.10.20
12:01
(21) Ага, это я видел, не подходит, потому что надо чтобы было чтоб это автоматом шло из проги (23) этот тоже читал
27 maestro-72
 
05.10.20
12:01
(24) Сейчас попробую
28 maestro-72
 
05.10.20
12:02
Пока как вариант решения сложной проблемы. Неисправную таблицу просто копирую отдельно, делаю сжатие методом XBASE и потом все по ней отрабатывает на ура.
29 maestro-72
 
05.10.20
12:08
(24) Отлично, жму руку! Тема закрыта, все получилось!