【发布时间】:2016-02-02 10:28:41
【问题描述】:
我正在使用下面的 Delphi 代码将 Access 数据库中的表替换为 utf=8 格式的大 csv 文件。在我开始之前,数据库是 946MB。一切正常,直到我的表达到一定大小然后我得到一个错误。发生这种情况时,数据库已超过 2GB。我猜也许 Jet 引擎正在创建一个导致溢出的内部副本 - 有没有办法阻止这种情况,或者也许有人可以建议一种不同的方法来导入我的数据来避免它?
function TCSVDatabase.ADOFromCSV(ConStr: string): Boolean;
var
J, K: Integer;
S: string;
SN, DN: string;
DefDir: string;
DestDir: string;
TN: TStringList;
begin
BeginUpdate;
Result := False;
DoProgress(0, 'Initializing...');
DN := ADOSetConnectionString(ConStr);
if FileExists(DN) then
begin
DestDir := ExtractFilePath(DN);
TN := TStringList.Create;
Result := True;
try
DefDir := FDefaultPath;
FDefaultPath := DestDir;
TN.Assign(ADOGetTableNames);
for K := 0 to TN.Count - 1 do
begin
SN := DestDir + TN[K] + '.csv';
if FileExists(SN) then
begin
DoProgress(0, 'Opening "' + TN[K] + '"...');
FADOTable.Close;
while FADOTable.Active do;
FADOTable.Connection := FADOConnection;
FADOTable.TableName := TN[K];
FADOTable.Open;
if FADOTable.Active then
begin
Result := True;
ADOGetFieldNames;
FADOQuery.Connection := FADOConnection;
FADOQuery.Recordset := FADOTable.Recordset;
FADOQuery.Open;
DoProgress(0, 'Emptying "' + TN[K] + '"...');
FADOQuery.SQL.Text := 'DELETE * FROM [' + TN[K] + ']';
FADOQuery.ExecSQL;
S := ExtractFilePath(SN);
SetLength(S, Length(S) - 1);
try
DoProgress(0, 'Filling "' + TN[K] + '"...');
FADOQuery.SQL.Text := 'INSERT INTO [' + TN[K] +
'] SELECT * FROM [' + ExtractFileName(SN) + '] IN "' + S +
'" "Text;HDR=YES;FMT=Delimited(,);CharacterSet=65001;"';
FADOQuery.ExecSQL;
except
FADOQuery.Connection := nil;
FADOQuery.Close;
DoProgress(0, 'SQL error in "' + TN[K] + '"');
{$IFDEF VCL}
ShowMessage('SQL error in "' + TN[K]);
{$ENDIF}
Result := False;
Exit;
end;
FADOQuery.Connection := nil;
FADOQuery.Close;
for J := 0 to FTemp.Count - 1 do
begin
if (FTemp.Codes[J] in [FT_MEMO, FT_WIDEMEMO]) then
begin
FADOTable.First;
while (not FADOTable.EOF) do
begin
S := FADOTable.Fields[J].AsString;
if (Pos('_\', S) <> 0) then
begin
S := StringReplace(S, '_\r\n_', #13#10, [rfReplaceAll]);
S := StringReplace(S, '_\r_', #13, [rfReplaceAll]);
S := StringReplace(S, '_\n_', #10, [rfReplaceAll]);
FADOTable.Edit;
FADOTable.Fields[J].AsString := S;
FADOTable.Post;
end;
FADOTable.Next;
end;
end;
end;
end;
end;
DoProgress(0, '');
end;
finally
FADOTable.Close;
if Result then
begin
DoProgress(0, 'Compacting...');
CompactDatabase(DN, FADOConnection);
end;
FDefaultPath := DefDir;
TN.Free;
end;
end;
DoProgress(0, '');
EndUpdate;
end;
【问题讨论】:
-
什么版本的 Access?
-
切换到另一个数据库,你已经接近极限了。看看使用 ZeosLib 作为替代方案的 SQLite
-
您的问题没有说明您从 CSV 文件中读取的数据量。仅当 CSV 文件的总大小加上原始 946 MB (远)小于 2 GB 时,您对内部副本的全部猜测才有意义。否则,您只会遇到其他人回答的 2GB 限制。请edit 并添加相关信息,以便我们区分我们正在处理的两种情况中的哪一种。
-
正确,Jan - 我正在尝试添加大约 40MB,所以当它出错时它几乎是 2GB 限制的一半。
-
考虑在删除语句之后执行数据库压缩。如果您要截断整个表,您可以通过先压缩来释放 mdb 文件中的空间。