Быстрое удаление записей в БД Paradox через BDE

  • Автор темы Bazil
  • Дата начала
Статус
Закрыто для дальнейших ответов.
B

Bazil

#1
Задача:
Есть большая БД Paradox (.db) размером в 10 млн.записей. Доступ к БД осуществляется через BDE в среде C++Builder 5.0.
Нужно быстро (в течение не более 10-20 сек) удалить группу в 1 млн. записей с начала БД без использования BatchMove и промежуточных БД.

Простое решение типа
kol=1000000;
Table3->First();
while(kol>0)
{ Table3->Delete();
kol--;
}
работает очень медленно (около 2 минут)

Заранее благодарен.
 
B

Barmutik

#2
Хммм.. а как насчёт попробовать TQuery и удалить одним запросом?

Я думаю за 5 секунд отработать должно ...
 
B

Bazil

#3
Попробовал удалить записи БД в TQuery запросом "DELETE FROM ..."
Отработало за 9 сек !

БОЛЬШОЕ спасибо за подсказку. :eek:
 
B

Bazil

#5
Еще один вопросик по поводу удаления записей из БД ...
После удаления записей с помощью TQuery или Table1->Delete() записи физически не удаляются, а только помечаются к удалению и размер БД остается прежним.
Как упаковать БД через BDE или другим способом ?
 
B

Barmutik

#6
Вобщето Paradox не помечает записи для удаления а сруза их удаляет .. помечает записи дя удаления dBase.

ну можно попробовать вот так:

Код:
      GetMem( pTblDesc, SizeOf( CRTblDesc ));
     FillChar( pTblDesc^, SizeOf( CRTblDesc ), 0 );
     with pTblDesc^ do
     begin
      StrPCopy( szTblName, oTable.TableName );
      StrPCopy( szTblType, szParadox );
      bPack := True;
     end;
     iResult := DbiDoRestructure( oTable.DBHandle, 1, 
            pTblDesc, nil, nil, nil, False );
     if iResult <> DBIERR_NONE then
     begin
      DbiGetErrorString( iResult, szErrMsg );
      MessageDlg( szErrMsg, mtError, [mbOk], 0 );
     end;
     FreeMem( pTblDesc, SizeOf( CRTblDesc ));
 
B

Bazil

#7
Barmutik

За код спасибо, счас попробую ...

По поводу пометки записей для удаления наверное я неправильно выразился, но могу сказать точно только одно:
размер БД после удаления записей не уменьшается.
 
B

Bazil

#9
Код почти рабочий. Почти, потому что функция DbiDoRestructure работает только с закрытой БД, а DBHandle таблицы
можно получить только при открытой БД.
То есть, перед использованием DbiDoRestructure нужно открыть БД, запомнить DBHandle, закрыть БД, и только потом
вызывать DbiDoRestructure
У меня получилось так (в переводе на C++Builder):
Код:
#include <bde.hpp>
hDBIDb h_db;
DBIMSG s1;
int err;
...
// вызов
Table1->Open();
h_db=Table1->DBHandle;
Table1->Close();
err=PackTable(h_db,"my_db.db");
if(err != DBIERR_NONE)
{ DbiGetErrorString(err, s1 );
  ShowMessage(s1);
}


//---------
int PackTable(hDBIDb hDb,char *TblName)
{
DBIResult  rslt;
CRTblDesc  TblDesc;

memset((void *) &TblDesc, 0, sizeof(CRTblDesc));
lstrcpy(TblDesc.szTblName, TblName);
lstrcpy(TblDesc.szTblType, szPARADOX);
TblDesc.bPack = TRUE;
rslt = DbiDoRestructure(hDb, 1, &TblDesc, NULL, NULL, NULL, FALSE);
return rslt;
}
В таком виде в отдельном приложении все работает.
При встраивании в рабочую программу выдается ошибка "share violation", хотя БД закрыта и никем не используется
Изменение свойства Table1->Exclusive ничего не дает.
Перед вызовом PackTable производится удаление данных с помощью TQuery
 
B

Bazil

#10
Прошу пардону, вопрос по ошибке "share violation" закрыт, обнаружена ошибка - не был закрыт файл ...
 
Статус
Закрыто для дальнейших ответов.