PB--学生选课系统

《数据库原理》验收项目代码。

开发环境

PowerBuilder 9.0
不做评价,学校要求使用的,下载地址,提取码:fezg

实验步骤

1.创建数据库

I. 创建ASA数据库,教程

其中”User ID”值为”dba”,”Password”值为”sql”,”Database Name”值为”student”,

II. 创建表和数据操作

分别创建三张表学生表S,课程表C,和学习表SC。这三个表的字段、主键和外键定义如下:
学生表: S(sno,sname,sex,age,sdept,logn,pswd)
主键: sno

Column Name Data Type Meaning
sno char(4) 学号
sname char(8) 姓名
sex char(2) 性别
age char(2) 年龄
sdept char(10) 所在系
logn char(20) 登录名
pswd char(20) 登录密码

数据操作结果如下:
S表字段

课程表: C(cno,cname,credit,cdept,tname)
主键: cno

Column Name Data Type Meaning
cno char(4) 课程号
cname char(8) 课程名
credit integer 学分
cdept char(10) 院系
tname char(8) 教师名

结果如下:
C表字段

学习表: SC(sno,cno,grade)
主键: (sno,cno)
外键: sno,cno

Column Name Data Type Meaning
sno char(4) 学号
cno char(4) 课程号
grade integer 成绩

注意!grade设置为可以赋空值,否则之后插入数据会报错。结果如下:
SC表字段

2.建立工作空间和应用对象

参见《数据库使用教程》P321-322或者应用对象创建

3.建立数据窗口

参见建立数据窗口教程分别建立数据窗口(d_c, d_s), 带参数数据窗口(d_select_student_course,d_select_student, d_select_student_score, d_score_input),group格式数据窗口(d_student_score_report, d_score_dis)
设置如下:
d_c
格式: Grid
选择方式: Quick Select
表: C
字段: All
可以将cdept的edit属性设置如下,按自己喜好设置。
d_c

d_s
格式: Grid
选择方式: Quick Select
表: S
字段: All
可以将sex的edit属性设置如下,按自己喜好设置。
d_s

d_select_student_course
格式: Grid
选择方式: Sql Select
表: C,SC
字段: cno,cname,credit,cdept,tname
定义获取参数: snum(Name),String(Type)
where字句: sc.cno=:snum
经过增强数据窗口功能处理以后,结果如图所示:
d_select_student_course

d_select_student
格式: Grid
选择方式: Sql Select
表: S
字段: sno,sname,age,sex,sdept
定义获取参数: snum(Name),String(Type)
where字句: s.sno=:snum
经过增强数据窗口功能处理以后,结果如图所示:
d_select_student

d_select_student_score
格式: Grid
选择方式: Sql Select
表: C,SC
字段: cno,cname,grade
定义获取参数: snum(Name),String(Type)
where字句: sc.sno=:snum and sc.grade is not null
经过增强数据窗口功能处理以后,结果如图所示:
d_select_student_score

d_score_input
格式: Grid
选择方式: Sql Select
表: SC
字段: sno,grade
定义获取参数: cnum(Name),String(Type)
where字句: sc.cno=:cnum
经过增强数据窗口功能处理以后,结果如图所示:
d_score_input

d_student_score_report
格式: Group
选择方式: Sql Select
表: S,C,SC
字段: sno,sname,cno,cname,credit,tname,grade
定义获取参数: snum(Name),String(Type)
where字句: s.sno=:snum
经过增强数据窗口功能处理以后,结果如图所示:
d_student_score_report

d_score_dis
格式: Group
选择方式: Sql Select
表: C,SC
字段: cno,cname
group字句: cno,cname拖到右端
compute字句: avg(grade)as平均成绩
经过增强数据窗口功能处理以后,结果如图所示:
w_score_dis

4.建立窗口

建立窗口之前,先添加student的open()时间脚本。

1
2
3
4
5
6
7
8
9
10
11
12
 //Profile student
SQLCA.DBMS="ODBC"
SQLCA.AutoCommit=false
SQLCA.DBParm="ConnectString='DSN=student;UID=dba;PWD=sql'"
CONNECT;
if SQLCA.SQLCODE<>0 then
messagebox("对不起!不能连接数据库!",SQLCA.SQLERRTEXT)
halt
return
else
open(w_login)
end if

分别建立窗口w_login, w_select_course, w_student_score_report, w_teacher_manage, w_student_create, w_course_create, w_course_score_dis.
w_login
窗口设计如下:
w_login

添加脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//sle_user的modified()事件脚本
if keydown(KeyEnter!) then
sle_pwd.setfocus()
end if


//sle_pwd的checkkey()事件脚本
if keydown(KeyEnter!) then
pb_login.setfocus()
end if


//pb_login的clicked()事件脚本

if sle_user.text="" then
messagebox("提醒","请输入用户名!")
sle_user.SetFocus()
return
end if
if sle_pwd.text="" then
messagebox("提醒","请输入密码!")
sle_pwd.SetFocus()
return
end if

string ls_user,ls_pwd,ls_confirm_user,ls_confirm_pwd
ls_user=upper(sle_user.text)
ls_pwd=upper(sle_pwd.text)
ls_confirm_user=""
ls_confirm_pwd=""
if(ls_user="SYSTEM" and ls_pwd="SYSTEM") then
open(w_teacher_manage)
close(parent)
else
select "s"."logn","s"."pswd","s"."sno" into :ls_confirm_user,:ls_confirm_pwd,:s_info from "s" where "s"."logn"=:ls_user;
s_info=trim(s_info)
if ls_user<>trim(ls_confirm_user) then
messagebox("警告","用户名错,重新注册",stopSign!)
sle_user.text=""
sle_pwd.text=""
sle_user.SetFocus()
elseif ls_pwd<>trim(ls_confirm_pwd) then
messagebox("警告","口令错,重新注册",stopSign!)
sle_pwd.text=""
sle_user.SetFocus()
else
open(w_select_course)
close(parent)
end if
end if


//pb_exit的clicked()事件脚本
close(parent)

w_select_course
窗口设计如下:
dw_1连接表d_select_student;
dw_2连接表d_select_student_score;
dw_3连接表d_c;
dw_4连接表d_select_student_course;
w_select_course

添加脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//窗口w_select_courese的open()事件脚本
dw_1.settransobject(sqlca)
dw_1.retrieve(s_info)
dw_1.object.datawindow.readonly="yes"

dw_2.settransobject(sqlca)
dw_2.retrieve(s_info)
dw_2.object.datawindow.readonly="yes"

dw_3.settransobject(sqlca)
dw_3.retrieve()
dw_3.object.datawindow.readonly="yes"

dw_4.settransobject(sqlca)
dw_4.retrieve(s_info)
dw_4.object.datawindow.readonly="yes"

sle_1.SetFocus()

//pb_1的clicked()事件
string ccname,ccno
c_info=upper(sle_1.text)
if c_info="" then
MessageBox("错误","请输入课程号!")
else
select c.cname into :ccname from c where c.cno=:c_info ;
if SQLCA.SQLCODE<>0 then
MessageBox("错误","此课程号不存在!")
else
select sc.cno into :ccno from sc where (sc.cno=:c_info and sc.sno=:s_info);
if SQLCA.SQLCODE=0 then
MessageBox("错误","此课程已选!")
else
insert into sc(sno,cno) values (:s_info,:c_info);
dw_4.reset()
sle_1.text=""
dw_4.settransobject(sqlca)
dw_4.retrieve(s_info)
end if
end if
end if


//pb_2的clicked()事件
string ccno,ggrade
if sle_1.text="" then
MessageBox("错误","请输入课程号!")
end if

c_info=upper(sle_1.text)
if c_info<>"" then
select c.cname into :cname_info from c where c.cno=:c_info ;
if SQLCA.SQLCODE<>0 then
MessageBox("错误","此课程号不存在!")
else
select sc.cno,sc.grade into :ccno,:ggrade from sc where (sc.cno=:c_info and sc.sno=:s_info);
if SQLCA.SQLCODE<>0 then
MessageBox("错误","此课程未选!")
else
if ggrade<>"" then
MessageBox("错误","此课程已登分!")
else
delete from sc where sno=:s_info and cno=:c_info;
dw_4.reset()
sle_1.text=""
dw_4.settransobject(sqlca)
dw_4.retrieve(s_info)
end if
end if
end if
end if

//pb_3的clicked()事件
close(parent)

//pb_4的clicked()事件
open(w_select_student_score_report)

w_student_score_report
窗口设计如下:
w_student_score_report

添加脚本

1
2
3
4
5
//窗口w_student_score_report的open()事件脚本
dw_1.settransobject(sqlca)
dw_1.retrieve(s_info)
dw_1.object.datawindow.readonly="yes"

w_teacher_manage
窗口设计如下:
w_teacher_manage

添加脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//窗口w_teacher_manage的open()事件脚本
declare cnamecursor cursor for select distinct c.cname from c,sc where c.cno=sc.cno;
open cnamecursor;

if SQLCA.SQLCODE=-1 then
messagebox("sql error",string(sqlca.sqldbcode)+":"+sqlca.sqlerrtext)
else
cname_info=""
do
if cname_info<>"" then
ddlb_cname.additem(cname_info)
end if
fetch cnamecursor into :cname_info;
loop while sqlca.sqlcode=0
if SQLCA.SQLCODE=-1 then
messagebox("sql error",string(sqlca.sqldbcode)+":"+sqlca.sqlerrtext)
end if
end if
close cnamecursor;
pb_2.enabled=false

//pb_1的clicked()事件脚本
if ddlb_cname.text="" then
messagebox("出错","请选择课名!")
else
cname_info=upper(ddlb_cname.text)
select cno,tname into :c_info,:teacher from c where cname=:cname_info;
st_5.text=ddlb_cname.text
st_6.text=teacher
dw_1.settransobject(sqlca);
dw_1.retrieve(c_info);
dw_1.object.datawindow.readonly="yes"
pb_2.enabled=true
end if

//pb_2的clicked()事件脚本
if pb_2.text="输入成绩" then
dw_1.object.datawindow.readonly="no"
dw_1.setfocus()
//dw_1.setrow(2)//切换当前行为第2行
//dw_1.setcolumn(2)//焦点移动到第2个字段
pb_2.text="保存"
pb_1.enabled=false
pb_3.enabled=false
pb_4.enabled=false
st_4.text="请输入成绩:"
else
dw_1.update()
dw_1.retrieve(c_info)
dw_1.object.datawindow.readonly="yes"
pb_2.text="输入成绩"
pb_1.enabled=true
pb_3.enabled=true
pb_4.enabled=true
st_4.text="已选修此课程的学生:"
end if

//pb_3的clicked()事件脚本
open(w_course_score_dis)

//pb_4的clicked()事件脚本
close(parent);


w_student_create
窗口设计如下:
w_student_create

添加脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//窗口w_student_create的open()事件脚本
int sum,hascol
dw_1.settransobject(sqlca);
dw_1.retrieve();
hascol=dw_1.retrieve();
pb_2.enabled=false
st_1.text=string(hascol)


//pb_1的clicked()事件脚本
long l_row
int s
s=dw_1.RowCount()
l_row=dw_1.InsertRow(s+1)
dw_1.scrolltorow(s+1)
dw_1.setfocus()
pb_1.enabled=false
pb_2.enabled=true


//pb_2的clicked()事件脚本
int s,hascol
string kk
s=dw_1.getrow();
s_info=dw_1.getitemstring(s,"sno")
select s.sno into :kk from s where (s.sno=:s_info);

if s_info=kk then
messagebox("出错","不能添加,此学号已存在!")
else
dw_1.update()
hascol=dw_1.retrieve()
st_1.text=string(hascol)
pb_1.enabled=true
pb_2.enabled=false
end if


//pb_3的clicked()事件脚本
int s,hascol
string kk
s=dw_1.getrow();
s_info=dw_1.getitemstring(s,"sno")

select sc.sno into :kk from sc where (sc.sno=:s_info);

if s_info=kk then
messagebox("出错","不能删除,此学生已选课!")
else
dw_1.DeleteRow(s);
dw_1.update();
hascol=dw_1.retrieve()
st_1.text=string(hascol)
end if
pb_1.enabled=true
pb_2.enabled=false


//pb_4的clicked()事件脚本
close(parent);

```
**w_course_create**
窗口设计如下:
![w_course_create](https://media-yuanxin.oss-cn-hangzhou.aliyuncs.com/img/w_course_create.png)

添加脚本
```bash
//窗口w_course_create的open()事件脚本
int sum,hascol
dw_1.settransobject(sqlca);
dw_1.retrieve();
hascol=dw_1.retrieve();
pb_2.enabled=false
st_1.text=string(hascol)


//pb_1的clicked()事件脚本
long l_row
int s
pb_1.enabled=false
s=dw_1.RowCount()
l_row=dw_1.InsertRow(s+1)
dw_1.scrolltorow(s+1)
dw_1.setfocus()
pb_1.enabled=false
pb_2.enabled=true


//pb_2的clicked()事件脚本
int s,hascol
string kk
s=dw_1.getrow();
c_info=dw_1.getitemstring(s,"cno")
select c.cno into :kk from c where (c.cno=:c_info);

if c_info=kk then
messagebox("出错","不能添加,此课程号已存在!")
else
dw_1.update()
hascol=dw_1.retrieve()
st_1.text=string(hascol)
pb_1.enabled=true
pb_2.enabled=false
end if


//pb_3的clicked()事件脚本
int s,hascol
string kk
s=dw_1.getrow();
c_info=dw_1.getitemstring(s,"cno")

select sc.cno into :kk from sc where (sc.cno=:c_info);

if c_info=kk then
messagebox("出错","不能删除,此课程已有学生选!")
else
dw_1.DeleteRow(s);
dw_1.update();
hascol=dw_1.retrieve()
st_1.text=string(hascol)
end if
pb_1.enabled=true
pb_2.enabled=false


//pb_4的clicked()事件脚本
close(parent);

```
**w_course_score_dis**
窗口设计如下:
![w_course_score_dis](https://media-yuanxin.oss-cn-hangzhou.aliyuncs.com/img/w_course_score_dis.png)

添加脚本
```bash
//窗口w_course_score_dis的open()事件脚本
dw_1.settransobject(sqlca)
dw_1.retrieve()
dw_1.object.datawindow.readonly="yes"

5.添加菜单

设置窗口w_techer_manage菜单m_student
m_student的设计如下图:
m_student

添加脚本

1
2
3
4
5
6
7
8
9
//m_学生表的clicked()事件
open(w_student_create)

//m_课程表的clicked()事件
open(w_course_create)

//m_关闭的clicked()事件
close(parentwindow)

将菜单添加到w_teacher_manage窗口
add_m_student

6.运行

输入用户名为”system”,密码”system”登录进入教师界面,即打开w_teacher_manage窗口。
run_system

输入用户名为学号如”s1”,密码为学号如”s1”登录进入s1学生的选课界面,即打开w_select_course窗口。
m_student

备注

该项目上传至github

打赏
  • © 2025 Aoxue
  • Hexo Theme Ayer by shenyu
    • PV:
    • UV:

请我喝杯咖啡吧~

支付宝
微信