最近在做一个选课系统来练手,遇到一个问题,困扰了好几天:用Query语句来实现数据添加时,老是重复添加相同的数据,除非重新运行程序,判断语句'是否重复语句'才会执行判断功能
界面中有两个DBGrid(DBGrid1和DBGrid2),两个按钮('添加课程'和'删除课程');DBGrid1和'课程表'(对应TBClass)连接,DBGrid2用来显示'学生已选的课程'(对应TBSelClass表),通过QSelClass这个Query来实现,
QSelClass的SQL语句是:Select Class.ID,Class.Name,Class.ClassType,Class.Mark,
Class.WeekPeriod //分别表示课程ID,课程名,课程类型(选修、必修),课程的学分,课程的周学时
From Class,SelClass //Class表示课程,SelClass表示已选的课程
Where (Class.Name=SelClass.Class_Name)and(SelClass.SNo=:StuNo) //StuNo是自己定义的一个字符型参数,表示学号{其中表Class用来存储课程信息,表SelClass用来存储学生选中的课程信息,学生自己信息的话存储在表Student中,这三个表对应的DBTables分别为
TBClass,TBSelClass和TBStudent}
'添加课程'按钮对应的语句如下:procedure TStudent.Button1Click(Sender: TObject);
begin
if DataModule2.TBClass.FieldByName('SelectedNum').AsInteger
>=DataModule2.TBClass.FieldByName('Capacity').AsInteger then {字段名SelectedNum表示'这门课程已选的人数',
字段名Capacity表示'这门课程总共可容纳的学生数'}
begin
ShowMessage('人数已满!');
end
else
begin
{QuerySelected是另外一个Query,在别的程序中定义过,用来判断'课程是否重复添加':
var
QuerySelected:TQuery; //声明QuerySelected为Query procedure TStudent.FormCreate(Sender: TObject);
begin
QuerySelected:=TQuery.Create(self); //创建QuerySelected
QuerySelected.DataBaseName:='.\db'; //定义其位置
end;} QuerySelected.Close;
QuerySelected.SQL.Clear;
QuerySelected.SQL.Add('Select * from SelClass'); //表SelClass里为学生已选的课程
QuerySelected.SQL.Add('where (SNo='''+UserName+''') and (Class_Name='''+DataModule2.TBClass.FieldByName('Name').AsString+''')'); //字段SNo表示学生的学号,字段Class_Name表示对应的课程名字
//UserName是别的地方定义的一个字符串,表示Trim(Edit1.Text)
QuerySelected.Open;
if not QuerySelected.IsEmpty then //用QuerySelected.IsEmpty来判定这课程是否已选 begin
ShowMessage('此课程已选!');
DataModule2.TBClass.Next;
end
else {如果这门课没选过,就将Class(课程)的部分信息和Student(学生)的学号添加到表SelClass(已选课程)中}
begin
DataModule2.TBSelClass.Append;
DataModule2.TBSelClass.FieldByName('SNo').AsString:=UserName; //UserName是别的地方定义的一个字符串,表示Trim(Edit1.Text)
DataModule2.TBSelClass.FieldByName('Student_ID').AsInteger:=DataModule2.TBStudent.FieldByName('ID').AsInteger;
DataModule2.TBSelClass.FieldByName('Class_ID').AsInteger:=DataModule2.TBClass.FieldByName('ID').AsInteger;
DataModule2.TBSelClass.FieldByName('Class_Name').AsString:=DataModule2.TBClass.FieldByName('Name').AsString;
DataModule2.TBSelClass.Post;
{将Class中的SelectedNum加1}
DataModule2.TBClass.Edit;
DataModule2.TBClass.FieldByName('SelectedNum').AsInteger:=DataModule2.TBClass.FieldByName('SelectedNum').AsInteger+1;
DataModule2.TBClass.Post; ShowMessage('选课成功');
QuerySelected.Close;
QuerySelected.Open; //实现QuerySelected的刷新
DataModule2.QSelClass.Open;
DataModule2.QSelClass.Close; //实现QSelClass的刷新,使DBGrid2中的已选课程能及时刷新
end;
end;end;上面这语句的流程是:学生登陆后,进去选课界面,选中了'英语'这门课程,按下'添加课程'按钮,那么语句会先判断'这门课可以容纳的人数是否已满',
如果没满则判断'这门课程该学生是否已选'(通过刚定义的QuerySelected来判断),如果没选则将这门课程的信息和学生的学号添加到
表SelClass(表示已选课程)中,然后给表Class的字段名SelectedNum加1(表示这门课的已选人数),然后对两个Query语句:QuerySelected和QSelClass
分别刷新,对QSelClass刷新的目的是为了其对应的DBGrid2能显示出最新的已选课程信息,对QuerySelected刷新本来的目的是为了让其知道刚刚添加过了
'英语',所以QuerySelected.IsEmpty 应该要变成False了,免得'英语'被重复添加
现在的问题是:我添加了'英语'这门课程后,如果马上第二次添加,'英语'会被再次添加进来,除非我第一次添加'英语'后马上关闭界面重新登陆,
那么第二次添加'英语'的时候才会提示'此课程已选!'
(明明已经刷新了QuerySelected怎么还是会出现重复选课的问题,已经困扰了数天,希望大家能帮忙找找原因,感激不尽!)
界面中有两个DBGrid(DBGrid1和DBGrid2),两个按钮('添加课程'和'删除课程');DBGrid1和'课程表'(对应TBClass)连接,DBGrid2用来显示'学生已选的课程'(对应TBSelClass表),通过QSelClass这个Query来实现,
QSelClass的SQL语句是:Select Class.ID,Class.Name,Class.ClassType,Class.Mark,
Class.WeekPeriod //分别表示课程ID,课程名,课程类型(选修、必修),课程的学分,课程的周学时
From Class,SelClass //Class表示课程,SelClass表示已选的课程
Where (Class.Name=SelClass.Class_Name)and(SelClass.SNo=:StuNo) //StuNo是自己定义的一个字符型参数,表示学号{其中表Class用来存储课程信息,表SelClass用来存储学生选中的课程信息,学生自己信息的话存储在表Student中,这三个表对应的DBTables分别为
TBClass,TBSelClass和TBStudent}
'添加课程'按钮对应的语句如下:procedure TStudent.Button1Click(Sender: TObject);
begin
if DataModule2.TBClass.FieldByName('SelectedNum').AsInteger
>=DataModule2.TBClass.FieldByName('Capacity').AsInteger then {字段名SelectedNum表示'这门课程已选的人数',
字段名Capacity表示'这门课程总共可容纳的学生数'}
begin
ShowMessage('人数已满!');
end
else
begin
{QuerySelected是另外一个Query,在别的程序中定义过,用来判断'课程是否重复添加':
var
QuerySelected:TQuery; //声明QuerySelected为Query procedure TStudent.FormCreate(Sender: TObject);
begin
QuerySelected:=TQuery.Create(self); //创建QuerySelected
QuerySelected.DataBaseName:='.\db'; //定义其位置
end;} QuerySelected.Close;
QuerySelected.SQL.Clear;
QuerySelected.SQL.Add('Select * from SelClass'); //表SelClass里为学生已选的课程
QuerySelected.SQL.Add('where (SNo='''+UserName+''') and (Class_Name='''+DataModule2.TBClass.FieldByName('Name').AsString+''')'); //字段SNo表示学生的学号,字段Class_Name表示对应的课程名字
//UserName是别的地方定义的一个字符串,表示Trim(Edit1.Text)
QuerySelected.Open;
if not QuerySelected.IsEmpty then //用QuerySelected.IsEmpty来判定这课程是否已选 begin
ShowMessage('此课程已选!');
DataModule2.TBClass.Next;
end
else {如果这门课没选过,就将Class(课程)的部分信息和Student(学生)的学号添加到表SelClass(已选课程)中}
begin
DataModule2.TBSelClass.Append;
DataModule2.TBSelClass.FieldByName('SNo').AsString:=UserName; //UserName是别的地方定义的一个字符串,表示Trim(Edit1.Text)
DataModule2.TBSelClass.FieldByName('Student_ID').AsInteger:=DataModule2.TBStudent.FieldByName('ID').AsInteger;
DataModule2.TBSelClass.FieldByName('Class_ID').AsInteger:=DataModule2.TBClass.FieldByName('ID').AsInteger;
DataModule2.TBSelClass.FieldByName('Class_Name').AsString:=DataModule2.TBClass.FieldByName('Name').AsString;
DataModule2.TBSelClass.Post;
{将Class中的SelectedNum加1}
DataModule2.TBClass.Edit;
DataModule2.TBClass.FieldByName('SelectedNum').AsInteger:=DataModule2.TBClass.FieldByName('SelectedNum').AsInteger+1;
DataModule2.TBClass.Post; ShowMessage('选课成功');
QuerySelected.Close;
QuerySelected.Open; //实现QuerySelected的刷新
DataModule2.QSelClass.Open;
DataModule2.QSelClass.Close; //实现QSelClass的刷新,使DBGrid2中的已选课程能及时刷新
end;
end;end;上面这语句的流程是:学生登陆后,进去选课界面,选中了'英语'这门课程,按下'添加课程'按钮,那么语句会先判断'这门课可以容纳的人数是否已满',
如果没满则判断'这门课程该学生是否已选'(通过刚定义的QuerySelected来判断),如果没选则将这门课程的信息和学生的学号添加到
表SelClass(表示已选课程)中,然后给表Class的字段名SelectedNum加1(表示这门课的已选人数),然后对两个Query语句:QuerySelected和QSelClass
分别刷新,对QSelClass刷新的目的是为了其对应的DBGrid2能显示出最新的已选课程信息,对QuerySelected刷新本来的目的是为了让其知道刚刚添加过了
'英语',所以QuerySelected.IsEmpty 应该要变成False了,免得'英语'被重复添加
现在的问题是:我添加了'英语'这门课程后,如果马上第二次添加,'英语'会被再次添加进来,除非我第一次添加'英语'后马上关闭界面重新登陆,
那么第二次添加'英语'的时候才会提示'此课程已选!'
(明明已经刷新了QuerySelected怎么还是会出现重复选课的问题,已经困扰了数天,希望大家能帮忙找找原因,感激不尽!)
解决方案 »
- 创建窗体时TDirDialog类没有找到
- 对于阿日的那个什么常用软件的质疑,感觉甚为无聊,这里鄙视之三。
- 将数据从excel中导入stringGrid中!
- dbgrid颜色问题
- 大家看看,为什么会出错,急!!
- %%%%%%%%%%如何实现SQL表的数据上传%%%%%%%%%%%%
- 两个delphi常用到的问题,高分马上送出!
- 我想用delphi自带的Micorsoft help workshop做帮助行么,在delphi哪里呀,我没找到!
- DSPack怎样实现无黑屏连续播放多个文件?
- 一个ActiveForm的问题
- 使用FastReport其中的BarCode问题,请指点,TKS!
- rose delphi link 下载
DataModule2.QSelClass.Open;
DataModule2.QSelClass.Close; //实现QSelClass的刷新,使DBGrid2中的已选课程能及时刷新
应该是:
DataModule2.QSelClass.Close;
DataModule2.QSelClass.Open; //实现QSelClass的刷新,使DBGrid2中的已选课程能及时刷新 //语句太多,在论坛不小心敲错了,在delphi中是正确的
//希望大家能帮帮忙~
2.ShowMessage('此课程已选!'); 也应该Exit退出;
3.DataModule2.TBClass.Next; 这句有什么作用,看不明白;
你要是添加的时候提示是否存在可以用locate
3、DataModule2.TBClass.Next; 作用是:如果我添加了英语,那么添加完以后鼠标会自动移到下一门课程上,比如语文
比如登陆窗口的时候,用户名和密码一一对应,那时候用locate比较方便;
现在这里的'学号'和'课程名'可以一对多,用locate不好实现吧
TBClass,TBSelClass,TBStudent,QSelClass还有一个动态的QuerySelected共5个??
你的DBGrid1和DBGrid2又是连接的那个数据集???
TBClass,TBSelClass,TBStudent之类的只是Table了
QuerySelected.Open; //实现QuerySelected的刷新
DataModule2.QSelClass.Close;
DataModule2.QSelClass.Open; //实现QSelClass的刷新,使DBGrid2中的已选课程能及时刷新
DBGrid2连接的QSelClass,显示的是该学生所有已选的课程
当然,DBGrid和Table和Query之间还有Datasource连接
'(对应TBSelClass表)'应该改成'(对应QSelClass)',忙中出错,不好意思~
添加第一次成功后,应该能弹出ShowMessage('此课程已选');
不过没有退出语句,所以还会继续执行添加相同的记录一个字,"代码很乱很乱,很难看"
begin
if DataModule2.TBClass.FieldByName('SelectedNum').AsInteger
>=DataModule2.TBClass.FieldByName('Capacity').AsInteger then {字段名SelectedNum表示'这门课程已选的人数',
字段名Capacity表示'这门课程总共可容纳的学生数'}
begin
ShowMessage('人数已满!');
end
else
/*
begin
{QuerySelected是另外一个Query,在别的程序中定义过,用来判断'课程是否重复添加':
var
QuerySelected:TQuery; //声明QuerySelected为Query procedure TStudent.FormCreate(Sender: TObject);
begin
QuerySelected:=TQuery.Create(self); //创建QuerySelected
QuerySelected.DataBaseName:='.\db'; //定义其位置
end;} QuerySelected.Close;
QuerySelected.SQL.Clear;
QuerySelected.SQL.Add('Select * from SelClass'); //表SelClass里为学生已选的课程
QuerySelected.SQL.Add('where (SNo='''+UserName+''') and (Class_Name='''+DataModule2.TBClass.FieldByName('Name').AsString+''')'); //字段SNo表示学生的学号,字段Class_Name表示对应的课程名字
//UserName是别的地方定义的一个字符串,表示Trim(Edit1.Text)
QuerySelected.Open;
if not QuerySelected.IsEmpty then //用QuerySelected.IsEmpty来判定这课程是否已选 begin
ShowMessage('此课程已选!');
DataModule2.TBClass.Next;
end
else {如果这门课没选过,就将Class(课程)的部分信息和Student(学生)的学号添加到表SelClass(已选课程)中}
begin
DataModule2.TBSelClass.Append;
DataModule2.TBSelClass.FieldByName('SNo').AsString:=UserName; //UserName是别的地方定义的一个字符串,表示Trim(Edit1.Text)
DataModule2.TBSelClass.FieldByName('Student_ID').AsInteger:=DataModule2.TBStudent.FieldByName('ID').AsInteger;
DataModule2.TBSelClass.FieldByName('Class_ID').AsInteger:=DataModule2.TBClass.FieldByName('ID').AsInteger;
DataModule2.TBSelClass.FieldByName('Class_Name').AsString:=DataModule2.TBClass.FieldByName('Name').AsString;
DataModule2.TBSelClass.Post;
{将Class中的SelectedNum加1}
DataModule2.TBClass.Edit;
DataModule2.TBClass.FieldByName('SelectedNum').AsInteger:=DataModule2.TBClass.FieldByName('SelectedNum').AsInteger+1;
DataModule2.TBClass.Post; ShowMessage('选课成功');
QuerySelected.Close;
QuerySelected.Open; //实现QuerySelected的刷新
DataModule2.QSelClass.Open;
DataModule2.QSelClass.Close; //实现QSelClass的刷新,使DBGrid2中的已选课程能及时刷新
end;
end;
*/end; 你看一下执行了没有
DataModule2.QSelClass.Params[0].AsString:=UserName; //UserName是一个字符串变量,表示Trim(Edit.Text)
DataModule2.QSelClass.Open;
觉得如果多用with do语句的话应该能简练好多,不过这样的话自己看的时候明白点,毕竟刚学怕搞错:(
此时,要停止执行下面的代码才是,不然会再添加一次数据.
上面的ShowMessage('人数已满!')也应该一样改两处:
1. begin
ShowMessage('人数已满!');
exit;
end
else ..
2. if not QuerySelected.IsEmpty then //用QuerySelected.IsEmpty来判定这课程是否已选
begin
ShowMessage('此课程已选!');
exit;
// DataModule2.TBClass.Next; 这句在这里做什么用,还是不明白
end
else
//DataModule2.TBClass.Next; 作用是:如果我添加了英语,那么添加完以后鼠标会自动移到下一门课程上,比如语文
你看能不能把引用的数据集控件简化一下,这样代码读起来也能简单些。
2.你的问题是因为数据没有提交到数据库,虽然,当你关闭界面后才真正提交了。
建议你用事务控制,从数据完整性
在最外层包:
DataModule2.ADOConnection1.BeginTrans; //你的程序中可能用别的名字
try
{在这之间加入你的代码} {代码结整束}
DataModule2.ADOConnection1.CommitTrans;
except
DataModule2.ADOConnection1.RollbackTrans;
end;试一下吧。
不过尝试着用用,非常感谢:)
你看能不能把引用的数据集控件简化一下,这样代码读起来也能简单些。
2.你的问题是因为数据没有提交到数据库,虽然,当你关闭界面后才真正提交了。
建议你用事务控制,从数据完整性
在最外层包:
DataModule2.ADOConnection1.BeginTrans; //你的程序中可能用别的名字
try
{在这之间加入你的代码}
{代码结整束}
DataModule2.ADOConnection1.CommitTrans;
except
DataModule2.ADOConnection1.RollbackTrans;
end; 试一下吧。
程序员在深圳JAVA群4247660
程序员在深圳c++群15195967
程序员在深圳.NET群Ⅱ:12203296
程序员在深圳TCP/IP协议栈开发:16956462
程序员在深圳JS & AJAX群:12578377
程序员在深圳英语学习群:23864353
深序员在深圳VB:11055959
程序员在深圳c++Ⅱ17409451
程序员在深圳c++群15195967
程序员在深圳嵌入式开发群37489763
程序员在深圳移动开发群31501597
程序员在深圳创业群33653422不限专业分类:
高级群:17538442
第三群:2650485
第五群:29537639
第四群:28702746
第六群:10590618
第七群:10543585
第八群:12006492
第九群:19063074
第十群:2883885
第十一群:25460595
第十二群:9663807深圳程序员QQ群联盟成立两年多,拥有三十个以上的QQ群,人数达二千多人,有30%以上的成员的经验丰富的老手,包括国内外顶级大公司的成员(如微软、IBM,SUN,华为)、国内著名高校和研究院成员,和有丰富实践经验的高级程序(包括参加过上亿元的项目的架构师),有很热爱技术的成员(包括自己写过嵌入式操作系统),还有少数女程序员。现推介如下QQ群,如有兴趣速速加入:深程高级群I:17538442 深程高级群II:7120862 (深程高级群不欢迎新手,如果在深圳,月薪6K以下的别加入) c++:15195967 .NET:12203296 mobile:31501597嵌入式:37489763 JAVA:4247660
——————————————————————————————————————————
希望大家不要认为群能给你带来什么,这只是一个平台,让同等水平的程序员有个交流的机会或许能得到一点信息或许能带来一点启发。*****************************************************************************