我需要在MS Access表中插入800000条记录.我正在使用Delphi 2007和TAdoXxxx组件.该表包含一些整数字段,一个浮点字段和一个只有一个字符的文本字段.其中一个整数字段(不是autoinc)上有一个主键,另一个整数和float字段上有两个索引.
使用AdoTable.AppendRecord(...)> 10分钟插入数据是不可接受的,因为每次用户开始在程序中使用新数据库时都会这样做.我无法预先填充表格,因为数据来自另一个数据库(无法访问ADO).
通过将记录写入制表符分隔的文本文件并使用tAdoCommand对象执行,我设法将时间缩短到大约1分钟
insert into table (...) select * from [filename.txt] in "c:\somedir" "Text;HDR=Yes"
Run Code Online (Sandbox Code Playgroud)
但我不喜欢这个的开销.
我想,必须有更好的方法.
编辑:
一些其他信息:
编辑:
从我到目前为止得到的所有答案来看,似乎我已经有了将这么多数据插入Access表的最快方法.感谢大家,感谢您的帮助.
我在程序中加载了一个 dll,它可以读取其设置并将其写入注册表(hkcu)。我的程序在加载 dll 之前更改了这些设置,因此它使用我的程序希望它使用的设置,效果很好。
不幸的是,我需要使用不同的 dll 设置来运行程序的多个实例。现在,我迄今为止使用的方法不再可靠地工作,因为程序的一个实例可能会在 dll 有机会读取它们之前覆盖另一个实例刚刚写入的设置。
我没有得到相关 dll 的来源,也无法要求编写它的程序员更改它。
我的一个想法是挂钩注册表访问函数并将它们重定向到特定于我的程序实例的注册表的不同分支(例如,使用进程 ID 作为路径的一部分)。我认为这应该可行,但也许你有一个不同的/更优雅的。
以防万一:我的程序使用 Delphi 2007,该 dll 可能是用 C 或 C++ 编写的。
我使用以下代码创建了MS Access表:
tbl := Database.CreateTableDef('English', 0, '', '');
try
fld := tbl.CreateField('ID', dbLong, 0);
fld.Attributes := dbAutoIncrField + dbFixedField;
tbl.Fields.Append(fld);
fld := tbl.CreateField('Content', dbText, 255);
fld.Required := true;
fld.AllowZeroLength := false;
tbl.Fields.Append(fld);
Database.TableDefs.Append(tbl);
idx := tbl.CreateIndex('PrimaryKey');
idx.Fields.Append(idx.CreateField('ID', EmptyParam, EmptyParam));
idx.Primary := True;
idx.Unique := true;
tbl.Indexes.Append(idx);
idx := tbl.CreateIndex('IX_Content');
idx.Fields.Append(idx.CreateField('Content', EmptyParam, EmptyParam));
idx.Primary := false;
idx.Unique := true;
tbl.Indexes.Append(idx);
finally
tbl := nil;
end;
Run Code Online (Sandbox Code Playgroud)
这工作正常,直到我尝试将两个字符串'字段类型'和'字段类型'插入此表.我收到一个错误,告诉我唯一的索引限制我这样做.正如您所看到的,它们仅在第二个单词的情况下有所不同.由于我没有明确地使索引不敏感(我甚至不知道如何做),我不太明白为什么会发生这种情况.文本字段中的索引在MS Access中是否始终不区分大小写?如果没有,我做错了什么?
给出以下代码段:
procedure TPicture.PaintLine(_Canvas: TCanvas; _Left, _Top, _Right, _Bottom: Integer);
begin
IntersectClipRect(_Canvas.Handle, _Left, _Top, _Right, _Bottom);
try
_Canvas.MoveTo(_Left - 10, _Top - 10);
_Canvas.LineTo(_Right + 10, _Bottom + 10);
// (This is an example only, the actual drawing is much more complex.)
finally
SelectClipRgn(_Canvas.Handle, 0); // This does too much
end;
end;
Run Code Online (Sandbox Code Playgroud)
我想撤消通过调用IntersectClipRect实现的剪辑,以便先前激活的剪辑再次变为活动状态.在上面的代码中,这是由SelectClipRgn(...,0)完成的,它完全关闭了裁剪.这种方法很有效,但之后没有裁剪活动,因此在上面执行之后执行的某些绘图将绘制到不应绘制的区域.
那么,只撤消IntersectClipRect效果的正确方法是什么?
编辑:在我理解了Sertac的评论之后删除了不必要的CreateRectRgn和DeleteObject代码,以使其他人可以在以后偶然发现这个问题时更具可读性.
在Delphi 2007中,我可以使用以下ToolsAPI调用轻松获取当前项目的版本信息:
procedure Test;
var
ProjectOptions: IOTAProjectOptions;
Project: IOTAProject;
Major: Variant;
Minor: Variant;
Release: Variant;
Build: Variant;
begin
// GxOtaGetCurrentProject is a function in GExpert's GX_OTAUtils unit that returns the current IOTAProject
Project := GxOtaGetCurrentProject;
if Assigned(Project) then begin
ProjectOptions := Project.ProjectOptions;
if Assigned(ProjectOptions) then begin
Major := ProjectOptions.Values['MajorVersion'];
Minor := ProjectOptions.Values['MinorVersion'];
Release := ProjectOptions.Values['Release'];
Build := ProjectOptions.Values['Build'];
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
在Delphi 10.2.3中,无论实际版本号如何,它都将始终返回版本1.0.0.0.这是"简单"的案例:VCL应用程序.
我还尝试了"Keys"值,它返回一个TStrings指针.在那里我也得到了FileVersion字符串,但它总是"1.0.0.0".
我想这与各种平台和配置的支持有关,但我找不到任何关于它现在应该如何工作的文档.我还搜索了ToolsAPI.pas中的"版本"和"发布",但没有出现任何可疑的内容.
有关如何在Delphi 10.2中获取版本信息的任何提示?
调用程序结束后是否可以延迟启动程序?
procedure StartLoop;
begin
DoSomething;
end;
procedure FormCreate(...);
begin
if ParamStr(1)='start' then StartLoop;
end;
Run Code Online (Sandbox Code Playgroud)
StartLoop将被称为内 FORMCREATE,和FORMCREATE将等待,并阻止进一步的执行不仅FORMCREATE本身的,而且之后(FormShow等)执行进一步的程序,并形成将不会显示,直到StartLoop将结束.
我需要等到FormCreate结束,然后运行StartLoop(不使用线程).
给定一个缓冲区及其大小(以字节为单位),有没有办法将其转换为 TBytes 而不复制它?
例子:
procedure HandleBuffer(_Buffer: PByte; _BufSize: integer);
var
Arr: TBytes;
i: Integer;
begin
// some clever code here to get contents of the buffer into the Array
for i := 0 to Length(Arr)-1 do begin
HandleByte(Arr[i]);
end;
end;
Run Code Online (Sandbox Code Playgroud)
我当然可以复制数据:
procedure HandleBuffer(_Buffer: PByte; _BufSize: integer);
var
Arr: TBytes;
i: Integer;
begin
// this works but is very inefficient
SetLength(Arr, _BufSize);
Move(PByte(_Buffer)^, Arr[0], _BufSize);
//
for i := 0 to Length(Arr)-1 do begin
HandleByte(Arr[i]);
end;
end;
Run Code Online (Sandbox Code Playgroud)
但是对于一个大缓冲区(大约一百兆字节),这意味着我的内存需求增加了一倍,并且还花费了大量时间来不必要地复制数据。
我知道我可以简单地使用 PByte 来处理缓冲区中的每个字节,我只对使用 …
我刚刚从我的SA订阅中下载了Delphi 2010 iso,除了在我的笔记本电脑上安装其他Delphi之外,还想安装它.不幸的是,它拒绝安装,因为该机器运行的是Windows 2000.
有可能以某种方式安装它吗?或者是否存在技术原因导致它可能不起作用,即使它已安装?
编辑:
更多信息:
我现在正在寻找的是:
Delphi以各种语言本地化(我认为英语,日语,德语,法语).命令行编译器(dcc32)也已本地化,因此德语版本向控制台写入"Fehler"而不是"Error"和"Warnung"而不是"Warning".
我编写了一个解析此输出的程序,并且(作为其功能之一)计算错误和警告.这与本地化字符串失败.
我可以调整程序以检测本地化的文本,但感觉不对.我宁愿强迫编译器使用英语作为输出.是否有命令行开关或任何其他选项来做到这一点?
我想支持使用msbuild的所有Delphi版本,即> = 2007.
编辑:
至于读取错误代码而不是消息,请考虑以下错误:
C:\[...]\Borland.Delphi.Targets(113,3): error : blub.pas(56) Error: E2029 ',' expected but identifier 'bla' found
Run Code Online (Sandbox Code Playgroud)
错误代码是E2029,但程序很难检测到它.检测文本"错误:"更简单,更不容易出错.
我有几个预编译(第 3 方)库需要在我的项目中使用。
我可以得到它来建立,如果我把foo.a在我的项目文件夹的根,但是,我有一个32位版本和库的64位版本,我不希望有换出foo.a与foo.32.a和foo.64.a每我构建应用程序的每个版本的时间。
在这种特殊情况下,我将它们放入:
[myroot]\iOSDevice32\Debug\foo.a
[myroot]\iOSDevice32\Release\foo.a
Run Code Online (Sandbox Code Playgroud)
和
[myroot]\iOSDevice64\Debug\foo.a
[myroot]\iOSDevice64\Release\foo.a
Run Code Online (Sandbox Code Playgroud)
我可以把它放在库路径中(工具 -> 选项 -> Delphi 选项 -> 库 -> 库路径);但是,我希望它特定于项目并相对于项目文件夹的根目录(而不是硬编码到所有项目的一个位置)。
我如何告诉 Delphi/Embarcadero RAD Studio 在哪里可以找到这些库?
delphi ×10
ms-access ×2
ado ×1
clipping ×1
dcc32 ×1
delphi-2007 ×1
delphi-2010 ×1
delphi-xe8 ×1
gdi ×1
hook ×1
indexing ×1
otapi ×1
registry ×1
toolsapi ×1
windows ×1