阅读前注意:
1. 本实验报告配套《数据库系统原理及应用教程》(苗雪兰等,第五版) 实验五:数据库的组合查询和统计查询实验(书上10.4节以及第六章部分内容),书本中采用Microsoft SQL Server Management Studio 2008,实验报告中采用Microsoft SQL Server Management Studio 2019和Microsoft Visual Studio 2017(用于C#的编写)。
2. 如果你的数据库课程选用的书目是这本书的话,那么大概率这会是你的实验作业。建议先自己独立完成后再作参考,数据库这门课是需要自己动手的。
3. 实验报告中可能增加了一些书中没有的附加内容,读者可以有兴趣自行完成。
4. 实验报告仅供初学者参考。
5. 请谅解实验报告中可能存在的问题或错误,欢迎指出,欢迎交流讨论。
一、实验目的
本实验的目的是使学生熟练掌握SQL Server查询分析器的使用方法,加深对SQL和Transact-SQL语言查询语句的理解。熟练掌握数据查询中的分组、统计、计算和组合的操作方法。
二、实验内容
1.基本内容
按照书上P296 10.4.5 要求完成基本操作实验内容(分组查询、使用函数查询、组合查询、计算和分组计算查询),熟练掌握SQL SERVER QUERY ANZLYZER的使用方法,熟练掌握数据查询实验中分组、统计、计算和组合的操作方法。
2.扩展内容
利用C#的数据库组件设计一个小型数据库应用系统基本要求:
1、自行设计一个数据库。(可选用前面实验设计的数据库)
2、利用DBGrid组件浏览数据库的内容。
3、能通过界面输入、修改和删除数据库中的内容
三、实验过程
1.基本内容
按照书上P296 10.4.5 要求完成基本操作实验内容(分组查询、使用函数查询、组合查询、计算和分组计算查询),熟练掌握SQL SERVER QUERY ANZLYZER的使用方法,熟练掌握数据查询实验中分组、统计、计算和组合的操作方法。
按照书上的要求修改图书读者数据库。代码如下:
USE Library_Reader
TRUNCATE TABLE Reader
INSERT INTO Reader
VALUES ('10000001','李小明','计算机系','M','13874635478'),
('10000002','王红','计算机系','M','13798394252'),
('10000003','李和平','计算机系','F','17757382635'),
('10000004','刘宏亮','计算机系','M','12775641098'),
('10000006','刘宏亮','计算机系','M','15678469943'),
('10000005','王小红','数学系','F','16734581230'),
('10000007','吴小','数学系','M','13894467236'),
('10000008','丁玉应','数学系','M','18976509554'),
('10000009','赵名','数学系','F','13567675319'),
('10000010','张共可','计算机系','M','13588730978')
UPDATE Book
SET b_writer='吴非'
WHERE b_number='2000000007'
SELECT * FROM Reader
SELECT * FROM Book
SELECT * FROM Loan
执行结果如下:
检验与书上内容一致。
(1)按照下列要求在图书读者数据库中查询。
注意!!Microsoft SQL Server 2012版本及之后不再使用COMPUTE命令。用GROUP BY命令一样能达成效果。
1)查找图书种类,要求类别中最高图书定价不低于全部按类分组的平均定价的2倍。
代码如下:
SELECT B1.b_type FROM Book B1
GROUP BY B1.b_type HAVING MAX(B1.b_price)>=ALL(
SELECT (2*AVG(B2.b_price)) FROM Book B2
GROUP BY B2.b_type)
查询结果:
注意:书中代码有错,原因是现在版本中如果有GROUP BY,则SELECT中只能有GROUP BY中包含的列。因此“*”应修改为“b_type”。
2)求机械工业出版社出版的各类图书的平均定价,用GROUP BY表示。
代码如下:
SELECT b_type, AVG(b_price) Average FROM Book
WHERE b_concern='机械工业出版社'
GROUP BY b_type ORDER BY b_type ASC
查询结果:
3)列出计算机类图书的书号、名称及价格,最后求出册数和总价格。
代码如下:
SELECT b_number, b_name, b_price FROM Book
WHERE b_type='计算机'
ORDER BY b_type ASC
SELECT COUNT(*), SUM(b_price) FROM Book
WHERE b_type='计算机'
查询结果:
注意:由于COMPUTE已被移除,因此列出图书书号名称价格需要与列出册数和总价格的查询需要分开。最后得到的结果是两个表。
4)列出计算机类图书的书号、名称与价格,并求各出版社这类图书的总价格,最后求出全部册数和总价格。
代码如下:
SELECT b_number, b_name, b_price FROM Book
WHERE b_type='计算机' ORDER BY b_concern
SELECT COUNT(*), SUM(b_price) FROM Book
WHERE b_type='计算机' GROUP BY b_concern
查询结果:
5)查询计算机类和机械工业出版社的图书。
代码如下:
SELECT * FROM Book
WHERE b_type='计算机'
UNION ALL
SELECT * FROM Book
WHERE b_concern='机械工业出版社'
查询结果:
(2)按下列要求在学生课程数据库中查询。
1)求学生总人数。
代码如下:
USE Student_Class
SELECT COUNT(*) FROM Student
查询结果:
2)求选修了课程的总人数。
代码如下:
SELECT COUNT(DISTINCT s_number) FROM Select_Course
查询结果:
3)求课程和选修该课程的总人数。
代码如下:
SELECT c_number, COUNT(s_number) FROM Select_Course
GROUP BY c_number
查询结果:
4)求选修了超过3门课的学生学号。
代码如下:
SELECT s_number FROM Select_Course
GROUP BY s_number HAVING COUNT(*)>3
查询结果:
2.扩展内容
利用C#的数据库组件设计一个小型数据库应用系统基本要求:
1、自行设计一个数据库。(可选用前面实验设计的数据库)
2、利用DBGrid组件浏览数据库的内容。
3、能通过界面输入、修改和删除数据库中的内容
首先在Microsoft SQL Server中创建一个数据库。
--图书读者数据库表结构为:
--图书(书号,类别,出版社,作者,书名,定价);
--读者(编号,姓名,单位,性别,电话);
--借阅(书号,读者编号,借阅日期);
USE Library_Reader
CREATE TABLE Book
(
b_number CHAR(10) NOT NULL,
b_type VARCHAR(12),
b_concern VARCHAR(30),
b_writer VARCHAR(20) NOT NULL,
b_name VARCHAR(50) NOT NULL,
b_price MONEY ,
PRIMARY KEY(b_number)--主码
)
CREATE TABLE Reader
(
r_number CHAR(8) NOT NULL,
r_name VARCHAR(8) NOT NULL,
r_workplace VARCHAR(30),
r_sex CHAR(1) NOT NULL,
r_tel CHAR(11),
CHECK(r_sex IN('M', 'F')),
PRIMARY KEY(r_number)
)
CREATE TABLE Loan
(
b_number CHAR(10) NOT NULL,
r_number CHAR(8) NOT NULL,
l_date DATETIME NOT NULL,
PRIMARY KEY(b_number, r_number),
)
INSERT INTO Book
VALUES (1000000001,'计算机','机械工业出版社','李明','计算机引论',18.00),
(1000000002,'计算机','机械工业出版社','王小红','数据结构',22.00),
(1000000003,'计算机','机械工业出版社','李和明','C语言编程',25.50),
(1000000004,'计算机','电子工业出版社','刘宏亮','操作系统',49.80),
(1000000006,'计算机','机械工业出版社','刘宏亮','数据结构',21.60),
(1000000005,'计算机','电子工业出版社','王小红','计算机文化',20.00),
(2000000007,'数学','机械工业出版社','吴非','高等数学',18.00),
(2000000008,'数学','机械工业出版社','丁玉应','概率统计',22.30),
(2000000009,'数学','电子工业出版社','赵名','线性代数',15.00),
(3000000010,'物理','电子工业出版社','张共可','力学',19.80)
INSERT INTO Reader
VALUES ('10000001','李小明','计算机系','M','13874635478'),
('10000002','王红','计算机系','M','13798394252'),
('10000003','李和平','计算机系','F','17757382635'),
('10000004','刘宏亮','计算机系','M','12775641098'),
('10000006','刘宏亮','计算机系','M','15678469943'),
('10000005','王小红','数学系','F','16734581230'),
('10000007','吴小','数学系','M','13894467236'),
('10000008','丁玉应','数学系','M','18976509554'),
('10000009','赵名','数学系','F','13567675319'),
('10000010','张共可','计算机系','M','13588730978')
INSERT INTO Loan
VALUES (1000000001,10000001,'1998-11-25'),
(1000000002,10000002,'1998-12-20'),
(1000000003,10000003,'1999-6-5'),
(1000000004,10000004,'2006-11-25'),
(1000000005,10000001,'2006-11-25'),
(1000000006,10000001,'2006-11-25'),
(2000000007,10000001,'2006-11-25'),
(2000000008,10000003,'2006-11-25'),
(2000000009,10000004,'2006-11-25'),
(3000000010,10000001,'2006-11-25')
SELECT * FROM Book
SELECT * FROM Reader
SELECT * FROM Loan
其执行结果如下:
接着,在Microsoft Visual Studio 2017中新建一个Visual C#项目,使用button、textBox设计好查询窗口的界面(对于textBox,通过小三角按钮点击Multiline即可将其扩充至多行。button、textBox的设计与调整详见上一个实验),其设计代码及详细的注释如下(包括数据库连接的代码注释):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//查询按钮
private void button1_Click(object sender, EventArgs e)
{
textBox5.Text = textBox5.Text + "书号";
textBox6.Text = textBox6.Text + "所属院系";
textBox7.Text = textBox7.Text + "出版社";
//“server”中填写服务器名称,“database”中填写数据库名称,采用可信连接Trusted_Connection以便访问数据库
//用户ID填写sa,密码为空
string str = @"server=DESKTOP-OO8LP6J;database=Library_Reader;Trusted_Connection=True;user id=sa; pwd=NULL;";
//新建数据库连接。
SqlConnection con = new SqlConnection(str);//此段代码数据库还没有实现连接,需要采用Open函数
con.Open(); //con.Open();
//进行查询
string sql = "SELECT * FROM Book";//输入SQL代码
SqlDataAdapter data = new SqlDataAdapter(sql, con);//对DataSet和SQL Server进行桥接
DataSet ds = new DataSet();
data.Fill(ds);//调用fill,在数据库Library_Reader中查找数据并把它填入ds中
//获取数据集中的表
DataTable tab1 = ds.Tables[0];//ds中只有一张表,所以取第0个
for(int i=0;i<tab1.Rows.Count;i++)//保证取到所有行,tab1.Rows.Count是指表中最大的行数
{
DataRow rows = tab1.Rows[i];
textBox1.Text = textBox1.Text + rows[0].ToString() + " \n";//取出第一列,放入对应的textBox中
textBox4.Text = textBox4.Text + "序号 " + (i + 1).ToString();//顺便加一个序号的标注
}
DataTable tab2 = ds.Tables[0];
for (int i = 0; i < tab2.Rows.Count; i++)
{
DataRow rows = tab2.Rows[i];
textBox2.Text = textBox2.Text + rows[1].ToString() + " \n";//取出第二列,放入对应的textBox中
}
DataTable tab3 = ds.Tables[0];
for (int i = 0; i < tab3.Rows.Count; i++)
{
DataRow rows = tab3.Rows[i];
textBox3.Text = textBox3.Text + rows[2].ToString() + " \n";//取出第三列,放入对应的textBox中
}
con.Close();// 关闭连接
}
private void textBox1_TextChanged_1(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
private void textBox4_TextChanged(object sender, EventArgs e)
{
}
private void textBox5_TextChanged(object sender, EventArgs e)
{
}
private void textBox6_TextChanged(object sender, EventArgs e)
{
}
private void textBox7_TextChanged(object sender, EventArgs e)
{
}
}
}
代码执行结果如下:
点击查询后:
至此,一个简单的小型数据库应用设计完成。设计的核心是如何将C#代码联系数据库。如果编写C++或其它语言,其与数据库的连接也是核心问题之一,原理与此代码的实现原理一致。鼓励读者多去尝试,在解决连接数据库问题的基础上向外拓展,完成一个自己的数据库应用。