完整性约束数据库
定义主码约束数据结构
Sno char(10) PRIMARY KEY; // 或者是在表的最后 PRIMARY KEY (Sno);
定义外码约束函数
FOREIGN KEY (Sno) REFERENCES student (Sno), FOREIGN KEY (Cno) REFERENCES course (Cno)
删除表spa
DROP TABLE student;
修改表的定义code
>1 ALTER TABLE student >2 ALTER COLUMN Sno varchar(20); // 修改列定义 >1 ALTER TABLE student >2 ADD job varchar(20) NULL; // 添加列 >1 ALTER TABLE student >2 DROP COLUMN job; // 删除列 >1 ALTER TABLE student >2 ADD constraint CK_stuAge CHECK(Sage between 15 and 40) // 增长约束 >1 ALTER TABLE student >2 DROP contstraint CK_stuAge; // 删除约束
创表完成以后的约束补充和修改排序
假设如今有了work雇员表和job工做表。图片
// 建立 1> CREATE TABLE work ( 2> workerid char(7) NOT NULL, 3> workername char(10) , 4> worknum char(8), 5> money int, 6> phone char(11) NOT NULL 7> ); 8> go 1> CREATE TABLE job( 2> worknum char(8), 3> mixmoney int, 4> maxmoney int, 5> ); 6> go
而后为其补充一些必要的约束字符串
主码约束
// 为work表添加主码约束 1> ALTER TABLE work 2> ADD CONSTRAINT M_PK // M_PK是本身起的约束名 3> PRIMARY KEY(workerid); 4> go
// 为job表添加主码约束 // 可是以前没有为该列加 NOT NULL ,因此先添加一个NOT NULL的约束 1> ALTER TABLE job 2> ALTER COLUMN worknum char(8) NOT NULL; 3> go // 在为job表添加主码约束 1> ALTER TABLE job 2> ADD CONSTRAINT PK_JOB 3> PRIMARY KEY (worknum); 4> go 1>
UNIQUE 约束
// 为雇员表worker的 phone 添加UNIQUE约束,使得其值不能有重复 1> ALTER TABLE work 2> ADD CONSTRAINT WORK_UK 3> UNIQUE (phone); 4> go 1>
外码约束
// 为雇员表work 的 工做编号worknum 添加外码约束 1> ALTER TABLE work 2> ADD CONSTRAINT FK_JOBID 3> FOREIGN KEY (worknum) REFERENCES job (worknum); 4> go 1>
DEFAULT 约束
// 为雇员的工资提默认值 1> ALTER TABLE work 2> ADD CONSTRAINT DF_work 3> DEFAULT 1000 FOR money; 4> go 1>
CHECK 约束
// 雇员工资表的工资最低是1000 1> ALTER TABLE work 2> ADD CONSTRAINT CHK_money 3> CHECK (money>=1000); 4> go 1> // 最低工资 < 最高工资 1> ALTER TABLE job 2> ADD CONSTRAINT CHK_job 3> CHECK (mixmoney<=maxmoney); 4> go 1>
插入数据
// 先往job表中插入一条数据 1> INSERT INTO job VALUES ('1',1000,1900); 2> go (1 行受影响) // 在往work中插入几条数据 1> INSERT INTO work VALUES ('1','张锦杰','1',1400,'13752127826'); 2> go (1 行受影响)
数据查询SELECT
查询表的所有数学
// 查询work表所有信息 1> SELECT * FROM work; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 (1 行受影响)
// 查询job表所有信息 1> SELECT * FROM job; 2> go worknum Dmixmoney Dmaxmoney --------D-----------D----------- 1 D 1000D 1900 (1 行受影响)
为了配如下的操做,须要多添加几条信息it
// 查询以下 1> SELECT * FROM work; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 2 D长官 D1 D 1600D1224123314 3 D妹妹 D1 D 1300D122432414 4 D妹ds妹 D1 D 1700D12223323414 5 D撒爱 D1 D 1900D1223414 6 D张爱爱 D1 D 1100D1324977734 (6 行受影响)
查询某几列
1> SELECT workerid,workername FROM work; 2> go workeridDworkername --------D---------- 1 D张锦杰 2 D长官 3 D妹妹 4 D妹ds妹 5 D撒爱 6 D张爱爱 (6 行受影响)
查询出通过计算的列
1> SELECT workerid, money+1000 FROM work; 2> go workeridD --------D----------- 1 D 2400 2 D 2600 3 D 2300 4 D 2700 5 D 2900 6 D 2100 (6 行受影响) // 会产生一个无名的列
常量列
1> SELECT workerid, '我是常量列成员', money+1000 FROM work; 2> go workeridD D --------D--------------D----------- 1 D我是常量列成员 D 2400 2 D我是常量列成员 D 2600 3 D我是常量列成员 D 2300 4 D我是常量列成员 D 2700 5 D我是常量列成员 D 2900 6 D我是常量列成员 D 2100 (6 行受影响) // 产生两个无名列
为无名列指定名字
1> SELECT workerid AS 主键, '我是常量内容' AS 常量 , money+1000 AS 总金额 FROM work; 2> go 主键 D常量 D总金额 -------D------------D----------- 1 D我是常量内容 D 2400 2 D我是常量内容 D 2600 3 D我是常量内容 D 2300 4 D我是常量内容 D 2700 5 D我是常量内容 D 2900 6 D我是常量内容 D 2100 (6 行受影响)
去除掉取值相同的行
>1 SELECT DISTINCT Sno FROM SC; >2 go // 去除掉重复的行,使用了关键字DISTINCT
查询知足条件的元组
查询条件 | 谓词 |
---|---|
比较 | = > < <= >= != 以及 NOT+前面的比较用算符 |
肯定范围 | BETWEEN AND , NOT BETWEEN AND |
肯定集合 | IN , NOTIN |
字符匹配 | LIKE, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重条件 | AND, OR |
1> SELECT * FROM work WHERE money=1400; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 (1 行受影响) // 取反操做:NOT money < 1200 // 正向操做:money >= 1200 // 须要注意的:取反操做比正向操做执行效率低,由于取反先是执行正向操做,而后从全体数据中排除这部分。所以取反操做须要通过两个步骤。
1> SELECT * FROM work WHERE money BETWEEN 1200 AND 1700; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 2 D长官 D1 D 1600D1224123314 3 D妹妹 D1 D 1300D122432414 4 D妹ds妹 D1 D 1700D12223323414 (4 行受影响) // BETWEEN 1200 AND 1700; 至关因而 同时知足 >=1200 <=1700 // 相反操做 1> SELECT * FROM work WHERE money NOT BETWEEN 1200 AND 1700; 2> GO workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 5 D撒爱 D1 D 1900D1223414 6 D张爱爱 D1 D 1100D1324977734 (2 行受影响)
对于日期的比较:
SELECT * FROM books WHERE time BETWEEN '2009/3/12' AND '2010/4/23'; // 对于日期类型的常量,须要用单引号引发来,而且年月日之间要用 '/' '-' 分割符来分割
1> SELECT * FROM work WHERE money IN ('1400','1500','1700'); 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 4 D妹ds妹 D1 D 1700D12223323414 (2 行受影响)
// 可使用LIKE进行模糊查找
// 匹配姓张的人 1> SELECT * FROM work WHERE workername LIKE '张%'; 4> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 6 D张爱爱 D1 D 1100D1324977734 (2 行受影响)
//匹配姓张、李、撒的人 1> SELECT * FROM work WHERE workername LIKE '[张李撒]%'; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 5 D撒爱 D1 D 1900D1223414 6 D张爱爱 D1 D 1100D1324977734 (3 行受影响)
// 不姓张也不姓王的 1> SELECT * FROM work WHERE workername NOT LIKE '[张王]%'; 2> go 或者 1> SELECT * FROM work WHERE workername LIKE '[^张王]%'; 2> go
1> SELECT * FROM work WHERE workername LIKE '[张_]'; // 姓张且是两个字 2> go
// 去掉指定列的尾随的空格 1> SELECT * FROM work WHERE workername LIKE '[张__]'; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- (0 行受影响) // 为何是无呢? // 由于咱们实际数据库的时候,给workername是char定长类型的,所以,若是不够定长,就用空格填充了,这就使得匹配没法成功。 如何解决呢? SQL Server 提供了 rtrim(列名) 来去掉尾随的空格 1> SELECT * FROM work WHERE rtrim(workername) LIKE '[张_]%'; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 6 D张爱爱 D1 D 1100D1324977734 (2 行受影响)
// 查询最后一位不是 2.3.5 1> SELECT * FROM work WHERE workername LIKE '%[^235]'; 2> go
// 转义字符 ESCAPE 关键字 1> SELECT * FROM work WHERE workername LIKE '%30!%%' ESCAPE '!'; 2> go // 以!转义% 意思是查找包含30%的字符串 1> SELECT * FROM work WHERE workername LIKE '%!_%' ESCAPE '!'; 2> go // 以!转义_ 意思是查找包含30%的字符串
// SELECT * FROM SC WHERE grade IS NOT NULL; SELECT * FROM SC WHERE grade IS NULL;
就是 AND
和 OR
SELECT Sname FROM Student WHERE Sdep = '计算机' AND Sage < 20 // AND 的 优先级比 OR 高,所以须要使用括号 SELECT Sname FROM Student WHERE ( Sdep = '计算机' OR Sdep = '信息') AND Sage < 20
排序
1> SELECT * FROM work ORDER BY money ASC; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 6 D张爱爱 D1 D 1100D1324977734 3 D妹妹 D1 D 1300D122432414 1 D张锦杰 D1 D 1400D13752127826 2 D长官 D1 D 1600D1224123314 4 D妹ds妹 D1 D 1700D12223323414 5 D撒爱 D1 D 1900D1223414 (6 行受影响)
1> SELECT * FROM work ORDER BY money DESC; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 5 D撒爱 D1 D 1900D1223414 4 D妹ds妹 D1 D 1700D12223323414 2 D长官 D1 D 1600D1224123314 1 D张锦杰 D1 D 1400D13752127826 3 D妹妹 D1 D 1300D122432414 6 D张爱爱 D1 D 1100D1324977734 (6 行受影响)
使用聚合函数来汇总数据
SQL提供的聚合函数有:
// 元组总个数 1> SELECT COUNT(*) FROM work; 2> go ----------- 6 (1 行受影响) // 统计本列非空值个数 1> SELECT COUNT(DISTINCT money) FROM work; 2> go ----------- 6 (1 行受影响) // 设置列名 1> SELECT COUNT(*) AS 工人数 , AVG(money) AS 平均收入 FROM work; 2> go 工人数 D平均收入 -----------D----------- 6D 1500 (1 行受影响) // 使用MAX 和 MIN 1> SELECT MAX(money) AS '最高收入' , MIN(money) AS '最低收入' FROM work; 2> go 最高收入 D最低收入 -----------D----------- 1900D 1100 (1 行受影响)
对查询结果进行分组统计
// 如今work表是这个样子 1> SELECT * FROM work; 2> go workeridDworkernameDworknum Dmoney Dphone --------D----------D--------D-----------D----------- 1 D张锦杰 D1 D 1400D13752127826 2 D长官 D1 D 1600D1224123314 3 D妹妹 D1 D 1300D122432414 4 D妹ds妹 D1 D 1700D12223323414 5 D撒爱 D1 D 1900D1223414 6 D张爱爱 D1 D 1100D1324977734 7 D大苏打 D2 D 1500D341212312 8 D阿斯顿 D2 D 1600D3123123 9 D误区二 D2 D 1700D32424 // 首先对员工表进行按照职位分组,分为两组,而后统计每组的数据 1> SELECT COUNT(*) AS 职位员工数 ,AVG(money) 平均收入 2> FROM work GROUP BY worknum; 3> go 职位员工数 D平均收入 -----------D----------- 6D 1500 3D 1600 (2 行受影响) 1> // 再来一次 1> SELECT worknum, COUNT(*) AS 职位员工数 ,AVG(money) 平均收入 2> FROM work GROUP BY worknum; 3> go worknum D职位员工数 D平均收入 --------D-----------D----------- 1 D 6D 1500 2 D 3D 1600 (2 行受影响) // 选择每一个系的女生的人数 // 再来一个小李子 SELECT Sdept, Count(*) 女生人数 FROM student WHERE Sex = '女' GROUP BY Sdep;
使用HAVING子句
HAVING 语句对分组后的数据在进行筛选,可使用统计函数,可是在WHERE 语句中是没法使用统计函数的。
// 拿书上的例子来讲 SELECT Sno , COUNT(*) AS 选课门数 FROM SC GROUP BY Sno HAVING COUNT(*) >3; // 查询选修了三门以上的学生的学号和选课数
多表链接查询
链接查询包括内链接、外链接、交叉链接,在这里咱们只涉及内链接、 和外链接
// 这里咱们须要建立三张表 // 学生表 1> CREATE TABLE student( 2> Sno varchar(8) PRIMARY KEY, 3> Sname varchar(10) NOT NULL, 4> Sage tinyint, 5> Ssex char(2), 6> Sdept char(20) 7> ); 8> go 1>var // 课程表 1> CREATE TABLE course( 2> Cno varchar(6) PRIMARY KEY, 3> Cname varchar(10) NOT NULL, 4> Credit tinyint, 5> Semester tinyint, 6> ); 7> go // 选课表 1> CREATE TABLE SC( 2> Sno varchar(8) NOT NULL, 3> Cno varchar(6) NOT NULL, 4> grade tinyint , 5> PRIMARY KEY(Sno, Cno), 6> FOREIGN KEY(Sno) REFERENCES student (Sno), 7> FOREIGN KEY(Cno) REFERENCES course (Cno) 8> ); 9> go 1> // 而后小编在数据库中添加了几条数据
// 将student 和 SC 链接 1> SELECT * FROM student INNER JOIN SC 2> ON student.Sno = SC.Sno; 3> go Sno DSname DSageDSsexDSdept DSno DCno Dgrade --------D----------D----D----D--------------------D--------D------D----- 13212311D张海 D 22D男 D数学系 D13212311Dc02 D NULL 13212311D张海 D 22D男 D数学系 D13212311Dc04 D 89 16101132D李勇 D 19D男 D计算机系 D16101132Dc01 D 43 16101132D李勇 D 19D男 D计算机系 D16101132Dc02 D NULL 16101132D李勇 D 19D男 D计算机系 D16101132Dc03 D 78 16101321D张锦杰 D 20D男 D计算机系 D16101321Dc01 D 90 16101321D张锦杰 D 20D男 D计算机系 D16101321Dc03 D 78 16101321D张锦杰 D 20D男 D计算机系 D16101321Dc04 D 78 16123211D吴斌 D 22D男 D信息系 D16123211Dc02 D 23 16123211D吴斌 D 22D男 D信息系 D16123211Dc03 D 65 16123211D吴斌 D 22D男 D信息系 D16123211Dc05 D 78 // 去掉重复的列 1> SELECT student.Sno, Sname, Sage, Ssex,Cno,grade FROM student 2> INNER JOIN SC 3> ON student.Sno = SC.Sno; 4> GO Sno DSname DSageDSsexDCno Dgrade --------D----------D----D----D------D----- 13212311D张海 D 22D男 Dc02 D NULL 13212311D张海 D 22D男 Dc04 D 89 16101132D李勇 D 19D男 Dc01 D 43 16101132D李勇 D 19D男 Dc02 D NULL 16101132D李勇 D 19D男 Dc03 D 78 16101321D张锦杰 D 20D男 Dc01 D 90 16101321D张锦杰 D 20D男 Dc03 D 78 16101321D张锦杰 D 20D男 Dc04 D 78 16123211D吴斌 D 22D男 Dc02 D 23 16123211D吴斌 D 22D男 Dc03 D 65 16123211D吴斌 D 22D男 Dc05 D 78 // 查询计算机系的学生的选修状况 1> SELECT Sname, Cno, grade FROM student INNER JOIN SC 2> ON student.Sno = SC.Sno 3> WHERE Sdept = "计算机系"; 4> go Sname DCno Dgrade ----------D------D----- 李勇 Dc01 D 43 李勇 Dc02 D NULL 李勇 Dc03 D 78 张锦杰 Dc01 D 90 张锦杰 Dc03 D 78 张锦杰 Dc04 D 78 (6 行受影响) // 查找计算机系中选修了VB的学生信息 1> SELECT Sname, Cname, grade FROM student JOIN SC ON student.Sno = SC.Sno 2> JOIN course ON course.Cno = SC.Cno 3> WHERE Sdept ="计算机系" 4> AND Cname = "VB"; 5> go Sname DCname Dgrade ----------D----------D----- 李勇 DVB D NULL (1 行受影响) // 统计每一个系的学生考试平均成绩 1> SELECT Sdept , AVG(grade) as "平均成绩" 2> FROM student JOIN SC ON student.Sno = SC.Sno 3> GROUP BY Sdept; 4> GO Sdept D平均成绩 --------------------D----------- 计算机系 D 73 数学系 D 89 信息系 D 55 // 1> SELECT Cno , COUNT(*) AS Total, AVG (grade), MAX(grade), MIN(grade) FROM student JOIN SC ON student.Sno = SC.Sno 2> WHERE Sdept ="计算机系" 3> GROUP BY Cno; 4> go Cno DTotal D D D ------D-----------D-----------D---D--- c01 D 2D 66D 90D 43 c02 D 1D NULLDNULDNUL c03 D 2D 78D 78D 78 c04 D 1D 78D 78D 78 (4 行受影响)
// 自链接 // 选择跟李勇是一个系的其他同窗 1> SELECT s2.Sname, s2.Sdept FROM student s1 JOIN student s2 2> ON s1.Sdept = s2.Sdept 3> WHERE s1.Sname ="李勇" 4> AND s2.Sname!= "李勇"; 5> go Sname DSdept ----------D-------------------- 张锦杰 D计算机系
// 外链接 只限制一张表符合链接条件就行,不必定两张表都知足 // 查询学生的选课状况,包括选课的和没有选的(左内链接) 1> SELECT student.Sno, Sname, Cno, grade 2> FROM student LEFT OUTER JOIN SC 3> ON student.Sno = SC.Sno; 4> go Sno DSname DCno Dgrade --------D----------D------D----- 12122312D王大力 DNULL D NULL 13212311D张海 Dc01 D 89 13212311D张海 Dc02 D NULL 13212311D张海 Dc04 D 89 16101132D李勇 Dc01 D 43 16101132D李勇 Dc02 D NULL 16101132D李勇 Dc03 D 78 16101321D张锦杰 Dc01 D 90 16101321D张锦杰 Dc03 D 78 16101321D张锦杰 Dc04 D 78 16123211D吴斌 Dc01 D 12 16123211D吴斌 Dc02 D 23 16123211D吴斌 Dc03 D 65 16123211D吴斌 Dc05 D 78 16213322D王明 DNULL D NULL // 右链接 1> SELECT student.Sno, Sname, Cno, grade 2> FROM student RIGHT OUTER JOIN SC 3> ON student.Sno = SC.Sno; 4> go Sno DSname DCno Dgrade --------D----------D------D----- 13212311D张海 Dc01 D 89 13212311D张海 Dc02 D NULL 13212311D张海 Dc04 D 89 16101132D李勇 Dc01 D 43 16101132D李勇 Dc02 D NULL 16101132D李勇 Dc03 D 78 16101321D张锦杰 Dc01 D 90 16101321D张锦杰 Dc03 D 78 16101321D张锦杰 Dc04 D 78 16123211D吴斌 Dc01 D 12 16123211D吴斌 Dc02 D 23 16123211D吴斌 Dc03 D 65 16123211D吴斌 Dc05 D 78 (13 行受影响) // 查询那些课程没有被选 1> SELECT Cname FROM course C LEFT JOIN SC 2> ON c.Cno = SC.Cno 3> WHERE SC.Cno IS NULL; 4> GO Cname ---------- 数据结构 (1 行受影响) // 查询并统计选课门数 1> SELECT S.Sno AS 学号 , COUNT(SC.Cno) AS 选课门数 2> FROM student S LEFT OUTER JOIN SC ON S.Sno = SC.Sno 3> GROUP BY S.Sno 4> ORDER BY COUNT(SC.Cno) DESC; 5> go 学号 D选课门数 --------D----------- 16123211D 4 13212311D 3 16101132D 3 16101321D 3 16213322D 0 12122312D 0
使用TOP限制结果集
// 倒叙显示 前三个 1> SELECT TOP 3 Sname , Sage, Sdept 2> FROM student 3> ORDER BY Sage DESC; 4> GO Sname DSageDSdept ----------D----D-------------------- 张海 D 22D数学系 吴斌 D 22D信息系 王大力 D 21D数学系 // 包含并列 1> SELECT TOP 3 WITH TIES Sname, Sdept 2> FROM student 3> ORDER BY Sage DESC; 4> go Sname DSdept ----------D-------------------- 张海 D数学系 吴斌 D信息系 王明 D信息系 王大力 D数学系 (4 行受影响) // TOP 谓词最好是于ORDER BY 配合使用 查询选课人数最少的两门课程(不包含没有选课的人) 1> SELECT TOP 2 WITH TIES Cno, COUNT(*) 选课人数 2> FROM SC 3> GROUP BY Cno 4> ORDER BY COUNT(*) ASC; 5> GO Cno D选课人数 ------D----------- c05 D 1 c04 D 2
未完待续,小编正在急稿中~~