我有一个场景,我必须从sql表中导出大约500,000条记录的数据,以便在Delphi应用程序中使用。数据将被加载到打包记录中。有没有一种方法可以使用BCP写入类似于将记录写入文件的数据文件。
截至目前,我正在使用此psudo代码加载数据。
// Assign the data file generated from BCP to the TextFile object.
AssignFile(losDataFile, loslFileName);
Reset(losDataFile);
while not EOD(losDataFile) do
begin
// Read from the data file until we encounter the End of File
ReadLn(losDataFile, loslDataString);
// Use the string list comma text to strip the fields
loclTempSlist.CommaText := loslDataString;
// Load the record from the items of the string list.
DummyRec.Name := loclTempSList[0];
DummyRec.Mapped = loclTempSList[1] = 'Y';
end;
为方便起见,我在下面列出了Dummy rec的类型
TDummyRec = packed record
Name : string[255];
Mapped : Boolean;
end;
所以,我的问题是,不是将数据导出到文本文件,而是可以将数据导出为二进制文件,以便我可以使用记录类型直接从文件中读取数据吗?
像
loclFileStream := TFileStream.Create('xxxxxx.dat', fmOpenRead or fmShareDenyNone);
while loclFileStream.Position < loclFileStream.Size do
begin
// Read from the binary file
loclFileStream.Read(losDummyData, SizeOf(TDummyRec));
//- -------- Do wat ever i want.
end;
我没有太多使用BCP的经验。请帮帮我。
由于 终止子...
答案 0 :(得分:1)
在您的记录中,string[255]
将创建固定大小的Ansi字符串(即所谓的shortstring
)。此类型明显已弃用,不应在您的代码中使用。
使用TFileStream
(即使它会起作用)直接保存它将是一个非常浪费的空间。每个记录将为每个名称存储256个字节。
使用string[255]
(即所谓的shortstring
)会对字符串进行隐藏转换,以便对其进行大多数访问。所以这不是最好的选择,恕我直言。
我的建议是使用我们的开源类use a dynamic array then serialize / unserialize it。对于您的存储,您可以使用动态数组。适用于Delphi 5至XE2。并且您将能够在记录中使用string
:
TDummyRec = packed record
Name : string; // native Delphi string (no shortstring)
Mapped : Boolean;
end;
OP评论后编辑:
BCP只是一个命令行工具,用于将导出很多行导入一个SQL表。因此,恕我直言BCP不适合您的目的。
您似乎需要从 SQL表中导入
。在这种情况下:
shortstring
在任何情况下都会浪费内存,因此与使用优质string
相比,内存更快; 答案 1 :(得分:0)
你想把一个SQL表读入一个记录,我不知道你为什么要使用古老的AssignFile。
您应该为您的数据库使用TADOQuery(或合适的变体) 在其中放置一个合理的SQL查询;类似的东西:
SELECT field1, field2, field3 FROM tablename WHERE .....
如有疑问,可以使用:
SELECT * FROM tablename
将从表格中选择所有字段。
以下代码将遍历所有记录和所有字段,并将它们保存在变体中并将其保存在FileStream中。
function NewFile(Filename: string): TFileStream;
begin
Result:= TFileStream.Create(Filename, fmOpenWrite);
end;
function SaveQueryToFileStream(AFile: TFileStream; AQuery: TADOQuery): boolean;
const
Success = true;
Failure = false;
UniqueFilePrefix = 'MyCustomFileTypeId';
BufSize = 4096;
var
Value: variant;
Writer: TWriter;
FieldCount: integer;
c: integer;
RowCount: integer;
begin
Result:= Success;
try
if not(AQuery.Active) then AQuery.Open
FieldCount:= AQuery.Fields.Count;
Writer:= TWriter.Create(AFile, BufSize);
try
Writer.WriteString(UniqueFilePrefix)
//Write the record info first
Writer.WriteInteger(FieldCount);
//Write the number of rows
RowCount:= AQuery.RecordCount;
WriteInteger(RowCount);
AQuery.First;
while not(AQuery.eof) do begin
for c:= 0 to FieldCount -1 do begin
Value:= AQuery.Fields[c].Value;
Writer.WriteVariant(Value);
end; {for c}
AQuery.Next;
end; {while}
except
Result:= failure;
end;
finally
Writer.Free;
end;
end;