数据库的多线程问题???急急急!!!请各位高手指点!!!205分送上!!!(205分)

7

777

Unregistered / Unconfirmed
GUEST, unregistred user!
我用多线程对一表进行检索,开始只用一个线程如果表中记录数大于500则
加一线程,大于1000再加一线程,最多开1000个线程。反之记录数小于1000
减一线程,小于500只用一个线程。
不知怎样动态增加减少线程???并在减少线程时释放内存???
我是动态创建的query,如果开多个线程用一执行函数,一个query可以吗??
还是需每个线程用一个query???

我的程序是从表中读用户email信息,并接收邮件。
小弟没用过多线程,请各位高手指点!!!

原码如下,
unit button;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
SakMsg, SakPOP3, Db, DBTables, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
q: TQuery;
base: TDatabase;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses pop3th;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);

begin
t.Create(false);
end;

end.

多线程单元:
unit pop3th;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
SakMsg, SakPOP3, Db, DBTables;

type
t = class(TThread)
private
pop:Tsakpop;
list:Tsakmsglist;
query:Tquery;
query1:Tquery;
protected
procedure Execute; override;
end;

implementation



procedure t.Execute;
var
y:integer;//无限循环变量
new:integer; //新邮件数
mailcount:integer;//邮件总数
c:integer;//mailcount-new的值
s:integer;//新邮件数循环变量
i:integer;//1 到记录总数循环变量
bit:string;//表popbit字段值
msg:Tsakmsg;
userid,from1,subject1,date1,text1,file1:string;//输出参数
user,mail:string;//mail为email地址 , user为email用户名
p:integer; //取@前的用户名
po:integer;//取日期格式
str,s1,s2,s3,s4:string;//取日期格式
begin

pop:=Tsakpop.Create(nil);
list:=Tsakmsglist.Create(nil);
query:=Tquery.Create(nil);
query1:=Tquery.Create(nil);
query1.DatabaseName:='delphi';
query.DatabaseName:='delphi';
//无限循环
y:=1;
while y<2 do
with query1 do
begin
close;
sql.Clear ;
sql.text:='select * from popinput';
open;
end;
for i:=1 to query1.RecordCount do
begin
bit:=query1.fieldbyname('popbit').asstring;
mail:=query1.fieldbyname('email').asstring;
userid:=query1.fieldbyname('userid').asstring;
if bit='1' then
begin
with query do
begin
close;
sql.Clear ;
sql.text:='update popinput set popbit=0 where email='+''''+mail+'''';
execsql;
end;
user:=mail;
p:=pos('@',user);
user:=copy(user,1,p-1);
try
pop.Host:=query1.fieldbyname('pophost').asstring;
pop.UserId:=user;
pop.UserPasswd:=query1.fieldbyname('poppw').asstring;
pop.Connect ;
pop.Login ;
pop.Init ;
new:=pop.NewMsgsCount ;
mailcount:=pop.MsgsCount ;
pop.RetrieveAllMessages(list);
pop.Quit ;

c:=mailcount-new;
if new>0 then
begin
for s:=c to mailcount-1 do
begin
msg:=list.Items[c];
from1:=msg.From;
subject1:=msg.Subject ;
str:=msg.Date ;
text1:=msg.Text.Text ;
file1:='';
po:=pos(' ',str);
str:=copy(str,po+1,length(str)-po);
po:=pos(' ',str);
s1:=copy(str,1,po-1);
po:=pos(' ',str);
str:=copy(str,po+1,length(str)-po);
s2:=copy(str,1,3);
if s2='Jan' then
s2:=inttostr(1);
if s2='Feb' then
s2:=inttostr(2);
if s2='Mar' then
s2:=inttostr(3);
if s2='Apr' then
s2:=inttostr(4);
if s2='May' then
s2:=inttostr(5);
if s2='Jun' then
s2:=inttostr(6);
if s2='Jul' then
s2:=inttostr(7);
if s2='Aug' then
s2:=inttostr(8);
if s2='Sep' then
s2:=inttostr(9);
if s2='Oct' then
s2:=inttostr(10);
if s2='Nov' then
s2:=inttostr(11);
if s2='Dec' then
s2:=inttostr(12);
str:=copy(str,5,length(str)-4);
s3:=copy(str,1,4);
po:=pos(' ',str);
str:=copy(str,po+1,length(str)-po);
po:=pos(' ',str);
s4:=copy(str,1,po-1);
str:=s3+'/'+s2+'/'+s1+'/'+s4;
date1:=str;
with query do
begin
close;
sql.clear;
sql.Text:='insert into popoutput values(';
sql.add(''''+userid+''''+',');
if from1<>'' then
sql.Add(''''+from1+''''+',')
else
sql.Add('null,');
if subject1<>'' then
sql.add(''''+subject1+''''+',')
else
sql.add('null,');
if date1<>'' then
sql.add(''''+date1+''''+',')
else
sql.add('null,');
if text1<>'' then
sql.add(''''+text1+''''+',')
else
sql.add('null,');
if file1<>'' then
sql.add(''''+file1+'''')
else
sql.add('null');
sql.add(')');
execsql;
end;
c:=c+1;
end;
end;

query1.Next ;

except
query1.Next ;
end;

with query do
begin
close;
sql.Clear ;
sql.text:='update popinput set popbit=1 where email='+''''+mail+'''';
execsql;
end;
//query1.Next ;
end
else
query1.Next ;
end;
end;//无限循环
end;

end.
 
定义线程Tmythread
可以对recordcount判断,如iCount:=(recordcount div 1000)+1
for i:=0 to iCount-1 do
Tmythread.create(yourparam1,yourparam2,...)
就可以。
每个线程都要独立的query.
 
adoquery.ExecuteOptions:=eoAsyncExecute表示异步操作,多个异步操作中的query是不
是类似于多线程?
 
这个功能除了对sql server有点用处之外,别的数据库好像不行。
 
这样写可以吗:

调用时根据表中记录数动态创建线程,记录每超过500加一线程。
我在 procedure t.Execute;中加入freeonterminate:=true;用于线程终止时释放内存。
不知这样可否在每次循环结束后终止线程并释放内存?
下次循环看表中记录数量动态创建线程,并在线程结束后释放。依次循环。
不知这样可以吗???
调用时:
procedure TForm1.Button1Click(Sender: TObject);
var
x,y:integer;//y表中记录总数,x每线程负责量
my:array[1..1000] of t;
I:integer;//线程数
m:integer;//无限循环变量
begin
m:=1;
while m>2 do
begin
I:=1;
x:=500;
my:=t.Create(false);

with q do
begin
close;
sql.Clear ;
sql.text:='select * from popinput';
open;
end;

y:=q.RecordCount ;

if y>x then
begin
I:=I+1;
my:=t.Create(false);
x:=x+500;
end;
end;
 
我的多线程为什么不能动态创建??
我调用时这么写怎么出错??
var
I:integer;
my:array[1..10] of t;
begin
for I:=1 to 10 do
my:=t.create(false);
end;

改为下面的代码也不行,不知为什么不能动态创建多个线程???请各位高手指点!!!
unit pop1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
SakMsg, SakPOP3, Db, DBTables, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
tt=class(TThread)
private
database1:Tdatabase;
query2:Tquery;
protected
procedure Execute; override;
end;
var
Form1: TForm1;

implementation

uses pop2;



{$R *.DFM}
procedure tt.Execute;
var
x,y:integer;//y表中记录总数,x每线程负责量
my:array[1..1000] of t;
m:integer;//无限循环变量
h:integer;//线程数
b:integer;//动态创建线程变量
begin
m:=1;
while m<2 do
begin
freeonterminate:=true;
database1:=Tdatabase.Create(nil);
query2:=Tquery.Create(nil);
database1.Params.Values['user name']:='sa';
database1.Params.Values['password']:='sa';
database1.LoginPrompt:=false;
database1.AliasName:='unissage';
database1.DatabaseName:='un';
database1.Connected:=true;
query2.DatabaseName:='un';

h:=1;
x:=500;

with query2 do
begin
close;
sql.Clear ;
sql.text:='select * from useremail';
open;
end;
y:=query2.RecordCount ;

if y>x then
begin
h:=h+1;
//create
x:=x+500;
end;

for b:=1 to h do
begin
my:=t.Create(false);
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);

begin
tt.Create(false);
end;

end.

unit pop2;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
SakMsg, SakPOP3, Db, DBTables;

type
t = class(TThread)
private
database:Tdatabase;
pop:Tsakpop;
list:Tsakmsglist;
query:Tquery;
query1:Tquery;
protected
procedure Execute; override;
end;

implementation



procedure t.Execute;
var
//w:integer;//无限循环变量
new:integer; //新邮件数
mailcount:integer;//邮件总数
c:integer;//mailcount-new的值
s:integer;//新邮件数循环变量
i:integer;//1 到记录总数循环变量
bit:string;//表popbit字段值
msg:Tsakmsg;
userid,from1,subject1,date1,text1,file1:string;//输出参数
user,mail:string;//mail为email地址 , user为email用户名
p:integer; //取@前的用户名
po:integer;//取日期格式
str,s1,s2,s3,s4:string;//取日期格式
st:string; // 取日期为附件名变量
t1,t2,t3,t4,t5,t6:string; // 取日期为附件名变量
r:integer; // 取日期为附件名变量
ii:integer;//附件数循环变量
aname:string;//加入表中的附件名和
begin
freeonterminate:=true;
database:=Tdatabase.Create(nil);
pop:=Tsakpop.Create(nil);
list:=Tsakmsglist.Create(nil);
query:=Tquery.Create(nil);
query1:=Tquery.Create(nil);
database.Params.Values['user name']:='sa';
database.Params.Values['password']:='sa';
database.LoginPrompt:=false;
database.AliasName:='unissage';
database.DatabaseName:='n';
database.Connected:=true;
query1.DatabaseName:='n';
query.DatabaseName:='n';
//无限循环
//w:=1;
//while w<2 do
with query1 do
begin
close;
sql.Clear ;
sql.text:='select * from useremail';
open;
end;
for i:=1 to query1.RecordCount do
begin
bit:=query1.fieldbyname('decide').asstring;
mail:=query1.fieldbyname('mail').asstring;
userid:=query1.fieldbyname('usercode').asstring;
if bit='1' then
begin
with query do
begin
close;
sql.Clear ;
sql.text:='update useremail set decide=0 where mail='+''''+mail+'''';
execsql;
end;
user:=mail;
p:=pos('@',user);
user:=copy(user,1,p-1);
try
pop.Host:=query1.fieldbyname('pop').asstring;
pop.UserId:=user;
pop.UserPasswd:=query1.fieldbyname('mailpwd').asstring;
pop.Connect ;
pop.Login ;
pop.Init ;
new:=pop.NewMsgsCount ;
mailcount:=pop.MsgsCount ;
pop.RetrieveAllMessages(list);
pop.Quit ;

c:=mailcount-new;
if new>0 then
begin
for s:=c to mailcount-1 do
begin
msg:=list.Items[c];
from1:=msg.From;
subject1:=msg.Subject ;
str:=msg.Date ;
text1:=msg.Text.Text ;

po:=pos(' ',str);
str:=copy(str,po+1,length(str)-po);
po:=pos(' ',str);
s1:=copy(str,1,po-1);
po:=pos(' ',str);
str:=copy(str,po+1,length(str)-po);
s2:=copy(str,1,3);
if s2='Jan' then
s2:=inttostr(1);
if s2='Feb' then
s2:=inttostr(2);
if s2='Mar' then
s2:=inttostr(3);
if s2='Apr' then
s2:=inttostr(4);
if s2='May' then
s2:=inttostr(5);
if s2='Jun' then
s2:=inttostr(6);
if s2='Jul' then
s2:=inttostr(7);
if s2='Aug' then
s2:=inttostr(8);
if s2='Sep' then
s2:=inttostr(9);
if s2='Oct' then
s2:=inttostr(10);
if s2='Nov' then
s2:=inttostr(11);
if s2='Dec' then
s2:=inttostr(12);
str:=copy(str,5,length(str)-4);
s3:=copy(str,1,4);
po:=pos(' ',str);
str:=copy(str,po+1,length(str)-po);
po:=pos(' ',str);
s4:=copy(str,1,po-1);
str:=s3+'/'+s2+'/'+s1+'/'+s4;
date1:=str;

//取日期为附件名
st:=str+'/';
r:=pos('/',st);
t1:=copy(st,1,r-1);
st:=copy(st,r+1,length(st)-r);
r:=pos('/',st);
t2:=copy(st,1,r-1);
st:=copy(st,r+1,length(st)-r);
r:=pos('/',st);
t3:=copy(st,1,r-1);
st:=copy(st,r+1,length(st)-r);
r:=pos(':',st);
t4:=copy(st,1,r-1);
st:=copy(st,r+1,length(st)-r);
r:=pos(':',st);
t5:=copy(st,1,r-1);
st:=copy(st,r+1,length(st)-r);
r:=pos('/',st);
t6:=copy(st,1,r-1);
st:=t1+t2+t3+t4+t5+t6;

file1:='';
aname:='';

if msg.AttachedFiles.Count>0 then
begin
for ii:=0 to msg.AttachedFiles.Count-1 do
begin
aname:=aname+msg.AttachedFiles[ii].FileName+'/' ;
//aname加入表中的附件名和
msg.AttachedFiles.Items[ii].SaveToFile('e:/'+st+
msg.AttachedFiles[ii].FileName );
//把附件加日期重命名后,保存到硬盘
end;
end;

with query do
begin
close;
sql.clear;
sql.Text:='insert into usermaillist values(';
sql.add(''''+userid+''''+',');
if subject1<>'' then
sql.Add(''''+subject1+''''+',')
else
sql.Add('null,');
if text1<>'' then
sql.add(''''+text1+''''+',')
else
sql.add('null,');
if aname<>'' then
sql.add(''''+aname+''''+',')
else
sql.add('null,');
if date1<>'' then
sql.add(''''+date1+''''+',')
else
sql.add('null,');
if from1<>'' then
sql.add(''''+from1+'''')
else
sql.add('null');
sql.add(')');
execsql;
end;
c:=c+1;
end;
end;

query1.Next ;

except
query1.Next ;
end;

with query do
begin
close;
sql.Clear ;
sql.text:='update useremail set decide=1 where mail='+''''+mail+'''';
execsql;
end;
//query1.Next ;
end
else
query1.Next ;
end;
//end;无限循环
query.Free;
query1.Free;
pop.Free;
list.Free;
//释放动态创建的控件
end;

end.
 
To 777:
不要再这样使用线程了。
 
BaKuBaKu——》为什么?
777——》》不要在这样贴了,你不知道我这里连大富翁多难:(
 
呵呵, 777 和我用 Email 交流的,问题应该已经解决了。可能忘了结束贴子。
 
777:问题解决了应该给人家分。
 
我的程序是从表中读用户Email信息并收取Email,如是新邮件则加如到另一表中。
因表中记录可能会很多,所以要做成多线程。表中记录每增加500创建一个视图,
并创建一线程对本视图操作。
(及500为单位,1-500为视图1,500-1000为视图2,1000-1500为视图3。......)


我现在的程序可实现:如表中有500以内的记录创建一视图和一线程,如记录大于500,
小于1000时,创建第2个视图和线程。......(不加Synchronize()时可以,加了Synchronize()
只对后一个线程操作,不对第一个线程操作???)

问题在于如表中记录开始就为1000,则创建两个视图和两个线程,Synchronize(fsy)
同步这个过程时只执行后一线程,不执行第一个创建的线程???
(线程同时创建时不用Synchronize不行,用Synchronize只对后一线程操作,
线程一个一个创建的不用Synchronize可以,用Synchronize也只对后一线程操作???)
程序开始没问题,记录一条条的增加线程也一个一个的创建。但如重起计算机并重新运行程序
记录假设为1000时,创建2个线程,则只对后一个线程操作???问题就出在这里???

我做过简单的同步一过程的例子可以对两个表同时操作,可我的程序格式也一样,怎么
只对后一线程操作,不操作第一个创建的线程???????

(因调程序方便我把500记录为单位改为1条记录为单位,及一条记录创建一视图和线程。......)
unit popunit;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
SakMsg, SakPOP3, Db, DBTables, StdCtrls, Menus, CoolTrayIcon;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
PopupMenu1: TPopupMenu;
CoolTrayIcon1: TCoolTrayIcon;
start1: TMenuItem;
close1: TMenuItem;
procedure Button1Click(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
end;
type
popthread = class(TThread)
private

database:Tdatabase;
pop:Tsakpop;
list:Tsakmsglist;
aquery:Tquery;
bquery:Tquery;
cquery:Tquery;

new:integer; //新邮件数
mailcount:integer;//邮件总数
c:integer;//mailcount-new的值
// bit:string;//表popbit字段值
msg:Tsakmsg;
userid,from1,subject1,date1,text1,file1:string;//输出参数
user,mail:string;//mail为email地址 , user为email用户名
p:integer; //取@前的用户名
po:integer;//取日期格式
str,s1,s2,s3,s4:string;//取日期格式
st:string; // 取日期为附件名变量
t1,t2,t3,t4,t5,t6:string; // 取日期为附件名变量
r:integer; // 取日期为附件名变量
aname:string;//加入表中的附件名和
xx:integer;
protected
procedure Execute; override;
procedure fsy;
public
constructor create(pdatabase:Tdatabase;ppop:Tsakpop;plist:Tsakmsglist;
paquery:Tquery;pbquery:Tquery;pcquery:Tquery;pxx:integer);
end;

type
thread = class(TThread)
private

database:array[1..1000] of Tdatabase;
pop:array[1..1000] of Tsakpop;
list:array[1..1000] of Tsakmsglist;
aquery:array[1..1000] of Tquery;
bquery:array[1..1000] of Tquery;
cquery:array[1..1000] of Tquery;

my:array[1..1000] of popthread;

query1:Tquery;
query2:Tquery;
database1:Tdatabase;

protected
procedure Execute; override;

end;

var
Form1: TForm1;
yes:Thread;
x:integer;//区分动态创建控件名
w:integer;//无限循环变量
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
yes:=thread.Create(false);
end;
procedure thread.Execute ;
var
recordi:integer;//记录数
fi:integer; //500记录为单位
begin
freeonterminate:=true;
x:=0;//区分动态创建控件名
fi:=0;
query1:=Tquery.Create(nil);
query2:=Tquery.Create(nil);
database1:=Tdatabase.Create(nil);
database1.Params.Values['user name']:='sa';
database1.Params.Values['password']:='sa';
database1.LoginPrompt:=false;
database1.HandleShared:=true;
database1.AliasName:='unissage';
database1.DatabaseName:='um';
database1.Connected:=true;
query1.DatabaseName:='um';
query2.DatabaseName:='um';
w:=1;
while w<2 do
begin
with query1 do
begin
close;
sql.Clear ;
sql.text:='select count(*) as sum2 from useremail';
open ;
end;
recordi:=query1.fieldbyname('sum2').asinteger;
//求出记录数
if recordi>fi then
begin
x:=x+1;
with query2 do
begin
close;
sql.Clear ;
sql.text:='create view pop'+inttostr(x);
sql.add('as select usercode,mail,mailpwd,pop from useremail');
sql.add('where id>'+inttostr(fi)+' and '+'id<='+inttostr(fi+1));
execsql;
end;

database[x]:=Tdatabase.Create(nil);
pop[x]:=Tsakpop.Create(nil);
list[x]:=Tsakmsglist.Create(nil);
aquery[x]:=Tquery.Create(nil);
bquery[x]:=Tquery.Create(nil);
cquery[x]:=Tquery.Create(nil);

my[x]:=popthread.Create(database[x],pop[x],list[x],aquery[x],
bquery[x],cquery[x],x);
//动态创建线程
fi:=fi+1;
end;

end;
if Terminated then
exit;
//如过掉用Terminate方法,线程退出
end;
constructor popthread.create(pdatabase:Tdatabase;ppop:Tsakpop;plist:Tsakmsglist;
paquery:Tquery;pbquery:Tquery;pcquery:Tquery;pxx:integer);
begin
inherited create(false);
database:=pdatabase;
pop:=ppop;
list:=plist;
aquery:=paquery;
bquery:=pbquery;
cquery:=pcquery;
xx:=pxx;
freeonterminate:=true;
end;
procedure popthread.Execute ;
begin

fsy; //过程fsy

if Terminated then
exit;
end;

procedure popthread.fsy ;
var

i:integer;//1 到记录总数循环变量
s:integer;//新邮件数循环变量
ii:integer;//附件数循环变量
k:integer;//记录数
begin
database.Params.Values['user name']:='sa';
database.Params.Values['password']:='sa';
database.LoginPrompt:=false;
database.HandleShared:=true;
database.AliasName:='unissage';
database.DatabaseName:='n';
database.Connected:=true;
bquery.DatabaseName:='n';
aquery.DatabaseName:='n';
cquery.DatabaseName:='n';

w:=1;

while w<2 do
begin
//无限循环

with bquery do //查出表中所有记录
begin
close;
sql.Clear ;
sql.text:='select * from pop'+inttostr(xx);
open;
end;

with cquery do //求出记录数
begin
close;
sql.Clear ;
sql.text:='select count(*) as sum1 from pop'+inttostr(xx);
open ;
end;
k:=cquery.fieldbyname('sum1').asinteger;

for i:=1 to k do //记录从第一条到最后一条循环时
begin
// bit:=query1.fieldbyname('decide').asstring;
mail:=bquery.fieldbyname('mail').asstring;
//用户email地址
userid:=bquery.fieldbyname('usercode').asstring;
//用户在系统的id
user:=mail;
p:=pos('@',user);
user:=copy(user,1,p-1);
//分析email地址,求出email用户名
try
pop.Host:=bquery.fieldbyname('pop').asstring;
//pop3服务器地址
pop.UserId:=user;
//email用户名
pop.UserPasswd:=bquery.fieldbyname('mailpwd').asstring;
//email密码
pop.Connect ;
//连接
pop.Login ;
//登陆
pop.Init ;
new:=pop.NewMsgsCount ;
//新邮件数
mailcount:=pop.MsgsCount ;
//邮件总数
pop.RetrieveAllMessages(list);
//接收邮件
pop.Quit ;

c:=mailcount-new;
//求出第几封到第几封为新邮件
if new>0 then
//如果新邮件大于0,接收新邮件信息,并存如库中
begin
for s:=c to mailcount-1 do
//第一封新邮件到最后一封新邮件循环时
begin
msg:=list.Items[c];
//c 为第几封新邮件
from1:=msg.From;
//发件人地址
subject1:=msg.Subject ;
//邮件主题
date1:=msg.Date ;
//邮件日期
text1:=msg.Text.Text ;
//邮件正文
aname:='';
//aname加入表中的附件名和
if msg.AttachedFiles.Count>0 then
//如果附件数大于0
begin
for ii:=0 to msg.AttachedFiles.Count-1 do
begin
//从第一封附件到最后一封附件循环时
aname:=aname+msg.AttachedFiles[ii].FileName+'/' ;
//aname为加入表中的附件名和
end;
end;

with aquery do
//把邮件信息加入usermaillist表中
begin
close;
sql.clear;
sql.Text:='insert into usermaillist values(';
sql.add(''''+userid+''''+',');
if subject1<>'' then
sql.Add(''''+subject1+''''+',')
else
sql.Add('null,');
if text1<>'' then
sql.add(''''+text1+''''+',')
else
sql.add('null,');
if aname<>'' then
sql.add(''''+aname+''''+',')
else
sql.add('null,');
if date1<>'' then
sql.add(''''+date1+''''+',')
else
sql.add('null,');
if from1<>'' then
sql.add(''''+from1+'''')
else
sql.add('null');
sql.add(')');
execsql;
end;

c:=c+1;
//下一封附件
end;
end;
bquery.Next ;
except
//出错跳到下一记录
bquery.Next ;
end;
end;
end; // 无限循环
end;
end.
 
多人接受答案了。
 
顶部