![]() |
|
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
|
https://yandex.ru/search/?text=восстановить%20заголовок%20dbf%20файла&lr=10&src=suggest_T
Вот такой адрес поискового запроса |
|||
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) Отлично, жму руку! Тема закрыта, все получилось!
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |