在很多数据库应用程序中,需要通过一个关键字段找出对应的其它字段数据,并且要求查找速度快。如在大多数的监控程序中,从终端获得一个标识后,需要通过这个标识将数据表中的其它数据查询出来,并显示在程序界面上。一般的做法是直接使用SQL查询返回查询结果。其实如果这个标识是唯一有序的,并且返回的结果也是唯一的,就没必要频繁地查询数据库。应该将数据首先存入内存,当然数据行上万就有难度。我要讲的存入内存其实是采用最为简单的方式,也就是记录(结构)类型作元素的数组。
具休做法是,先定义一个记录类型,用于保存在界面中要显示的结果数据,再定义一个数组,将所有数据从数据表是查询并排序存入这个数组。在查找时使用二分法得到对应的数组元素。
具体代码如下:
unit u_MyData;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Dialogs, StdCtrls, DB;
type
PMyData = ^TMyData;
TMyData = record
CardNo: Integer;
EmpNo, EmpName, ClassName: String;
end;
TMySearch = class
private
{ Private declarations }
List: Array of TMyData;
function Search(iBegin, iEnd, ACardNo: Integer): Integer;
public
{ Public declarations }
destructor Destroy; override;
function Clear: Boolean;
function LoadValue(Items: TStrings): Boolean; overload;
function LoadValue(DataSet: TDataSet): Boolean; overload;
function SearchFor(ACardNo: Integer): TMyData; overload;
end;
var
NULL_DATA: TMyData;
implementation
{ TMySearch }
function TMySearch.Clear: Boolean;
begin
Result:= False;
try
SetLength(List, 0);
Result:= True;
except
// Can't free the element.
end;
end;
destructor TMySearch.Destroy;
begin
Clear;
inherited;
end;
function TMySearch.LoadValue(DataSet: TDataSet): Boolean;
var
i: integer;
begin
Result:= False;
try
Clear; // Clear the old value first.
with DataSet do
begin
if Active then
begin
DisableControls;
try
SetLength(List, RecordCount);
First;
for i:= 0 to RecordCount -1 do
begin
List[i].CardNo:= Fields[0].AsInteger;
List[i].EmpNo:= Fields[1].AsString;
List[i].EmpName:= Fields[2].AsString;
List[i].ClassName:= Fields[3].AsString;
Next;
end;
finally
EnableControls;
end;
end;
end;
except
// Can't load value from dataset.
end;
end;
function TMySearch.LoadValue(Items: TStrings): Boolean;
var
i: integer;
begin
Result:= False;
try
Clear; // Clear the old value first.
SetLength(List, Items.Count);
for i:= 0 to Items.Count -1 do
begin
List[i].CardNo:= StrToInt(Items[i]);
end;
Result:= True;
except
// Can't load value from strings.
end;
end;
function TMySearch.Search(iBegin, iEnd, ACardNo: Integer): Integer;
var
Mid: Integer;
begin
Result:= -1;
try
if iBegin <= iEnd then
begin
Mid:= (iBegin + iEnd) div 2;
if List[Mid].CardNo = ACardNo then
Result:= Mid
else if List[Mid].CardNo > ACardNo then
Result:= Search(iBegin, Mid -1, ACardNo)
else
Result:= Search(Mid + 1, iEnd, ACardNo);
end;
except
// Can't search the value.
end;
end;
function TMySearch.SearchFor(ACardNo: Integer): TMyData;
var
i: integer;
begin
Result:= NULL_DATA;
try
if Length(List) > 0 then
begin
i:= Search(0, Length(List) -1, ACardNo);
if (i >= 0) and (i < Length(List)) then
Result:= List[i];
end;
except
// Can't find a value.
end;
end;
end.
{ 以一个类实现 }
以上代码经测试,只是感觉上比查询数据库快,实际还得设定相同条件进行比较。