azz. Hai sfondato la dimensione della riga di buffer ...
Controlla dentro il file ZDBcCache.
TZByteArray = array[0..65535] of Byte;
...
if FColumnsSize > SizeOf(TZByteArray)-1 then
raise EZSQLException.Create(SRowBufferWidthExceeded);
Da questo controllo direi che dovresti farti 2 conticini .. le righe superano (con i varchar al massimo) i 65535 byte? Se sì, creca di usarne qualcuno meno ;)
Sicuro che ti servano tutti i 73 campi in un unica riga e che tu non possa spezzarla in "parent" e "child"?
Al massimo usi 2 tabelle, in master e slave, dove mappi meno campi per tabella.
Stilgar
Procedura CancellaTabella(Connessione : TZConnection; nomeTabella : String)
var
statement:IZPrepareStatement;
numeroRigheEliminate : integer;
begin
try
statement := Connessione.DbcConnection.PrepareStatement('delete from ?');
statement.setStringParma(1,nomeTabella);
numeroRigheEliminate:= statement.ExecuteUpdatePrepared;
except
on E : Exception do
informa(E.Message);
end;
statement := nil;
End;
Scritto di getto, non testato con il compilatore... vole essere solo una traccia ;)
procedure TConvPrismaF.Button3Click(Sender: TObject);
[...]
if TTempz.recordcount>0 then
begin
TTempz.First;
while not TTempz.EOF do
begin
TTempz.Delete;
//TTempz.ApplyUpdates;
TTempz.Next;
end;
end;
end;
[...]
ApplyUpdates a parte, questo pezzo di codice è il responsabile del problema dell'eliminazione: ti veniva cancellato 1 record si ed 1 no, nel tuo caso credo tutti i record dispari :)
Quando invochi Delete, il cursore passa automaticamente al record successivo, non serve la Next anzi è un errore richiamarla perché così ne salti uno che non verrà cancellato.
Per cancellare tutto è meglio seguire il consiglio di Stilgar (molto più veloce) però, nel caso dovessi tornare a scrivere qualcosa del genere, devi scrivere il loop in questo modo:
if TTempz.recordcount>0 then
while TTempz.recordcount>0 do
TTempz.Delete;
Edit:
anzi...
la prima riga, quella con l'if non serve neanche, basta:
while TTempz.recordcount>0 do TTempz.Delete;
di solito DisableControls serve a fare queste operazioni più velocemente
prova così:
with DataDBF do
begin
Primanota.Active:=False;
Primanota.FilePath:= perco1;
Primanota.FilePathFull:= perco1;
Primanota.Active:=True;
Primanota.DisableControls;
DataSQL.Primanota.DisableControls;
Primanota.First;
try
while not Primanota.EOF do
begin
DataSQL.Primanota.Append;
g:=0;
while (g < Primanota.FieldCount) do
begin
CampoP:= Primanota.Fields[g].FieldName;
DataSQL.Primanota.FieldValues[CampoP]:= Primanota.FieldValues[CampoP];
// ConvPrismaF.ListBox1.Items.Add(CampoP);
g:=g+1;
end;
Primanota.Next;
end;
finally
Primanota.EnableControls;
DataSQL.Primanota.EnableControls;
end;
informa('Elaborazione finita');
end;
Che si "sbianchi" durante questo tipo di operazioni è normale, il processore ha di meglio da fare che disegnare sullo schermo ;)
Per mostrare l'avanzamento dovresti usare (con parsimonia) Application.ProcessMessage che forza l'elaborazione dei messaggi in coda.
Per mostrare l'avanzamente ogni 100 record, ad esempio:
dovresti definire da qualche parte una label (se non ti piace la label puoi fare con la progressbar)
with DataDBF do
begin
Label1.Caption := 'Initializing...';
Primanota.Active:=False;
Primanota.FilePath:= perco1;
Primanota.FilePathFull:= perco1;
Primanota.Active:=True;
Primanota.DisableControls;
DataSQL.Primanota.DisableControls;
Primanota.First;
try
while not Primanota.EOF do
begin
DataSQL.Primanota.Append;
g:=0;
while (g < Primanota.FieldCount) do
begin
CampoP:= Primanota.Fields[g].FieldName;
DataSQL.Primanota.FieldValues[CampoP]:= Primanota.FieldValues[CampoP];
// ConvPrismaF.ListBox1.Items.Add(CampoP);
g:=g+1;
end;
// refresh gui ogni 100 records
if (Primanota.RecNo mod 100) = 0 then
begin
Label1.Caption := Format('Processing table %s, record %d/%d done...', ['Primanota', Primanota.RecNo, Primanota.RecordCount]);
Application.ProcessMessages;
end;
Primanota.Next;
end;
finally
Primanota.EnableControls;
DataSQL.Primanota.EnableControls;
end;
Label1.Caption := Format('Table %s done.', ['Primanota']);
informa('Elaborazione finita');
end;
Sia Application.ProcessMessages che mod rallenteranno un po' l'esecuzione, ma sparirà l'effetto "non risponde".
Per le tabella di appoggio ... usi tabelle "in memory" o tabelle su disco?
Per il fatto che vengano aggiornati 0 record, non so se questo è un problema o meno ...
il db non ha trovato nulla da aggiornare ....
per queste operazioni batch l'uso dei dataaware non so se è il massimo ... ma poi sta a te decidere, personamente elaboro decine di record senza problemi di performance.
procedure TMainModel.RicreaCodici;
var
statemnt, updateStatement: string;
stmt: IZStatement;
updStmt: IZPreparedStatement;
rs: IZResultSet;
numeroRecord: longint;
node, aNode, root: TDOMElement;
doc: TXMLDocument;
indice, indiceIdRef: longint;
rsMt: IZResultSetMetadata;
function GetElementById(root: TDOMElement; id: integer): TDOMElement;
var
idx: integer;
begin
Result := nil;
if root.GetAttribute('id') = TSystem.valueOf(id) then
Result := root
else
begin
idx := 0;
while (idx < root.ChildNodes.Count) and isNull(Result) do
Result := GetElementById(TDomElement(root.ChildNodes[postInc(idx)]), id);
end;
end;
procedure InsertTree(stmt: IZPreparedStatement; root: TDOMElement);
var
idx: integer;
begin
for idx := 0 to root.ChildNodes.Count - 1 do
begin
try
with TDOMElement(root.ChildNodes[idx]) do
begin
stmt.SetString(1, GetAttribute('id'));
stmt.SetString(2, root.GetAttribute('id'));
stmt.SetString(3, GetAttribute('codice'));
stmt.SetString(4, GetAttribute('descrizione'));
stmt.ExecutePrepared;
InsertTree(updStmt, TDOMElement(root.ChildNodes[idx]));
end;
except
end;
end;
end;
function getCodiceElemento(root: TDOMElement): string;
begin
Result := root.GetAttribute('id');
if isAssigned(root.ParentNode) then
Result := getCodiceElemento(root.ParentNode as TDOMElement) + '.' + Result;
end;
procedure RicordificaTree(root: TDOMElement);
var
idx: integer;
idx1, idx2: string;
begin
for idx := 1 to root.ChildNodes.Count do
begin
try
idx1 := root.GetAttribute('id');
if length(idx1) = 1 then
idx1 := '0' + idx1;
idx2 := TSystem.valueOf(idx);
if idx < 10 then
idx2 := '0' + idx2;
TDOMElement(root.ChildNodes[idx - 1]).SetAttribute('id',
TSystem.valueOf(TSystem.parseInt(idx1 + idx2)));
TDOMElement(root.ChildNodes[idx - 1]).SetAttribute('codice', idx1 + '.' + idx2);
TDOMElement(root.ChildNodes[idx - 1]).SetAttribute('idRef',
root.GetAttribute('id'));
RicordificaTree(TDOMElement(root.ChildNodes[idx - 1]));
except
end;
end;
end;
begin
numeroRecord := getConteggioRighe('tabella');
doc := TXMLDocument.Create;
root := doc.CreateElement('root');
root.SetAttribute('id', '0');
doc.AppendChild(root);
stmt := connessione.DbcConnection.CreateStatement;
statemnt := defaultMapper.getItem('getTabellaByIndice');
updateStatement := defaultMapper.getItem('insertRecord);
updStmt := connessione.DbcConnection.PrepareStatement(updateStatement);
try
try
rs := stmt.ExecuteQuery(statemnt);
rsMt := rs.GetMetadata;
indiceIdRef := -1;
for indice := 1 to rsMt.GetColumnCount do
begin
if rsMt.GetColumnName(indice) = 'idRef' then
indiceIdRef := indice;
end;
indice := 1;
while rs.Next do
begin
node := doc.CreateElement('CAUSALE');
node.SetAttribute('id', rs.GetStringByName('id'));
node.SetAttribute('idRef', rs.GetStringByName('idRef'));
node.SetAttribute('codice', rs.GetStringByName('codice'));
node.SetAttribute('descrizione', rs.GetStringByName('descrizione'));
aNode := GetElementById(doc.DocumentElement, rs.GetInt(indiceIdRef));
if isNull(aNode) then
begin
aNode := root;
end;
aNode.AppendChild(node);
end;
except
on e: Exception do
begin
end;
end;
finally
rs := nil;
stmt := nil;
end;
XMLWrite.WriteXMLFile(doc, 'file.xml');
doc.Free;
doc := TXMLDocument.Create;
XMLRead.ReadXMLFile(doc, 'file.xml');
try
RicordificaTree(doc.DocumentElement);
stmt.Execute('delete from tabella');
stmt.Execute('update sqlite_sequence set seq=0');
InsertTree(updStmt, doc.DocumentElement);
stmt.Execute('update sqlite_sequence set seq=10000');
XMLWrite.WriteXMLFile(doc, 'file.xml');
except
end;
tabellaAware.Refresh;
doc.Free;
end;
Questa è una mia routine che legge una tabella. La trasforma in un albero (XML per comodità di lettura su file).
Fa le trasformazioni che mi servono.
Pulisce la tabella, ripristina i contatori delle autokey e reinserisce tutto da zero.
Questo mi serve per evitare buchi logici.
Essendo un albero, quello che elaboro, c'è molta ricorsione tra i nodi.
Poi vedi tu cosa preferisci fare ;)
Stilgar