【3.69】将一个新学生元组插入到Student表中。
INSERT
INTO Student(Sno,Sname,Ssex,Sdept,Sage)
VALUES('20121520','星河','男','IS',18);
INTO中指出表名Student以及要增加的元组的属性。
【3.70】
INSERT
INTO Student
VALUES('20121521','张程敏','男',18,'CS');
INTO后只是指出了表名,没有属性列,这表示将在这个表的所有属性列上赋值,顺序与表中列的顺序一致,要保证插入数据与表的属性列一一对应。
【3.71】插入一条选课记录
INSERT
INTO SC(Sno,Cno)
VALUES('20121521','1');
--或者
INSERT
INTO SC
VALUES('20121521','1',NULL);
第一种未说明Grade属性列及值,则自动赋空值。
第二种只是指出表名,这时候VALUES后的值要包含表的所有属性列的值,是空值就NULL。
【3.72】 对每一个系,求学生的平均年龄,并把结果存入数据库
--建表
CREATE TABLE Dept_age
(Sdept CHAR(15),
Avg_age SMALLINT);
--插入数据
INSERT
INTO Dept_age(Sdept,Avg_age)
SELECT Sdept,AVG(Sage)
FROM Student
GROUP BY Sdept;
INTO后面是一个子查询。可以一次插入多个元组。
执行插入语句会自动检查完整性规则。
子查询SELECT子句目标列必须与INTO子句匹配。
【3.73】将学生201215121的年龄改为22岁。
UPDATE Student
SET Sage=22
WHERE Sno=' 201215121 ';
修改一个元组的值。将Student表中满足WHERE子句条件的元组中Sage的值改为22。
【3.74】将所有学生的年龄增加1岁。
UPDATE Student
SET Sage= Sage+1;
如果没有WHERE子句,表示要修改表中所有元组。
【3.75】将计算机科学系全体学生的成绩置零
UPDATE SC
SET Grade=0
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept= 'CS' );
带有子查询的修改语句。子查询查询计算机科学系学生的学号,将学号是子查询条件的课程表中的元组成绩置零。
RDBMS在执行修改语句时会检查修改操作是否破坏表上已定义的完整性规则。
实体完整性:主码不能为空;
主码不允许修改(?):
在SQLserver中主键是可以进行修改的。但是有约束的主键是不可以修改的。
我选取的是学生表中学号201215121,对它进行修改时,它提醒我不可以,因为在SC表中有关于201215121这个学号的记录。只能修改那些没有在SC中出现的学号。
UPDATE Student
SET SNO=NULL
WHERE SNO='201215121';
--不能将值 NULL 插入列 'Sno',表 'master.dbo.Student';列不允许有 Null 值。UPDATE 失败。
UPDATE Student
SET SNO='201215151'
WHERE SNO='201215121';
--UPDATE 语句与 REFERENCE 约束"FK__SC__Sno__3E723F9C"冲突。该冲突发生于数据库"master",表"dbo.SC", column 'Sno'。
UPDATE Student
SET SNO='201215150'
WHERE SNO='201215121';
--违反了 PRIMARY KEY 约束“PK__Student__CA1FE464BB4C272A”。不能在对象“dbo.Student”中插入重复键。重复键值为 (201215150)。
【3.76】
DELETE
FROM Student
WHERE Sno= 201215128 ';
删除学号为201215128的学生记录;删除Student表中满足WHERE子句条件的元组。
【3.77】删除课程表所有选课记录。
DELETE
FROM SC;
没有WHERE时表示删除表中所有元组。但是表还在,只剩一个表了。
【3.78】删除计算机科学系所有学生的选课记录。
DELETE
FROM SC
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept= 'CS') ;
带子查询的删除语句。
【3.79】向SC表中插入一个元组,学生号是”201215126”,课程号是”1”,成绩为空
INSERT
INTO SC(Sno,Cno,Grade)
VALUES('201215126 ','1',NULL);
--或者
INSERT
INTO SC(Sno,Cno)
VALUES('201215126','1');
空值是一个很特殊的值,含有不确定性。如果输入的信息是空时,可以直接赋值NULL,也可以忽略空值所在的属性列,那就自动赋值NULL了。
【3.80】将Student表中学生号为”201215200”的学生所属的系改为空值。
UPDATE Student
SET Sdept = NULL
WHERE Sno='201215200';
【3.81】从Student表中找出漏填了数据的学生信息
SELECT *
FROM Student
WHERE Sname IS NULL
OR Ssex IS NULL
OR Sage IS NULL
OR Sdept IS NULL;
判断一个属性的值是否为空值,用IS NULL或IS NOT NULL来表示。
不可以用等号代替IS。
【3.82】找出选修1号课程的不及格的学生。
SELECT Sno
FROM SC
WHERE Grade < 60 AND Cno='1';
查询结果不包括Grade值为null的学生(缺考)。
【3.83】选出选修1号课程的不及格的学生以及缺考的学生。
SELECT Sno
FROM SC
WHERE Grade < 60 AND Cno='1'
UNION
SELECT Sno
FROM SC
WHERE Grade IS NULL AND Cno='1'
--或者
SELECT Sno
FROM SC
WHERE Cno='1' AND (Grade<60 OR Grade IS NULL);
上一个例子无法查询缺考的学生,第一种方法将不及格学生与缺考学生合并。第二种加个查询条件。
UNION:将多个查询结果合并不保留重复元组;
【3.84】建立信息系学生的视图。
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS';
建立视图,CREATE VIEW <视图名> [(<列名> [,<列名>]…)],例子中的属性列名全部省略,则它的属性列由子查询中SELECT目标列中的诸字段组成。
【3.85】建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生 。
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS'
WITH CHECK OPTION;
多了一行 WITH CHECK OPTION,对该视图进行插入、修改和删除操作时,会自动加上Sdept='IS’的条件。
【3.86】建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)。
CREATE VIEW IS_S1(Sno,Sname,Grade)
AS
SELECT Student.Sno,Sname,Grade
FROM Student,SC
WHERE Sdept= 'IS'
AND Student.Sno=SC.Sno
AND SC.Cno= '1';
视图IS_SI的属性列中包含了Student表和SC表的同名列Sno,所以要在视图后面明确说明视图的各个属性列名。
【3.87】建立信息系选修了1号课程且成绩在90分以上的学生的视图。
CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade
FROM IS_S1
WHERE Grade>=90;
视图不仅可以建立在一个或者多个基本表上,也可以建立在一个或多个已经定义号的视图上,或建立在基本表与视图上。
视图IS_S2就是建立在视图IS_S1上的。
【3.88】 定义一个反映学生出生年份的视图。
CREATE VIEW BT_S(Sno,Sname,Sbirth)
AS
SELECT Sno,Sname,2014-Sage
FROM Student;
视图BT_S是一个带表达式的视图。出生年份是通过表达式计算得到的。
【3.89】
CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
带有聚集函数和GROUP BY 子句的查询来定义视图,这种视图成为分组视图。
AS子句中SELECT语句中平均成绩列是通过作用聚集函数来得到的,没有它自己的列名,所以定义视图时必须定义各属性列名。
【3.90】将Student表中所有女生记录定义为一个视图。
CREATE VIEW F_Student(F_Sno,name,sex,age,dept)
AS
SELECT *
FROM Student
WHERE Ssex='女';
SELECT *没有指定属性列,这时F_Student中的属性列必须和Student中的属性列一一对应,否则会报错。
CREATE VIEW F_Student(F_Sno,name,age,dept)
AS
SELECT *
FROM Student
WHERE Ssex='女';
--'F_Student' 中的列多于列列表中指定的列。
【3.91】删除视图BT_S和IS_S1。
DROP VIEW BT_S; /*成功执行*/
DROP VIEW IS_S1; /*成功执行*/
标准SQL中,IS_S1是无法删除的,因为IS_S2建立在它上面,要想删除就必须使用CASCADE。
但是在serverSQL中,是可以删除的,在尝试打开IS_S2,打开就会有问题。
【3.92】在信息系学生的视图中找出年龄小于20岁的学生。
SELECT Sno,Sage
FROM IS_Student
WHERE Sage<20;
查询视图时,先检查查询中设计的表、视图是否存在。如果存在,在数据字典中取出视图的定义,将定义中的子查询和用户的查询结合,转换成等价的对基本表的查询,然后执行这个查询。这个转换过程叫做视图消解。
转换后的查询语句为:
SELECT Sno,Sage
FROM Student
WHERE Sdept= 'IS' AND Sage<20;
【3.93】查询选修了1号课程的学生
SELECT IS_Student.Sno,Sname
FROM IS_Student,SC
WHERE IS_Student.Sno=SC.Sno
AND SC.Cno='1';
涉及视图和基本表SC。
【3.94】在S_G视图中查询平均成绩在90分以上的学生学号和平均成绩
SELECT *
FROM S_G
WHERE Gavg>=90;
--S_G视图定义为
CREATE VIEW S_G (Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
转换后:
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade)>=90;
--错误的转换:
SELECT Sno,AVG(Grade)
FROM SC
WHERE AVG(Grade)>=90
GROUP BY Sno;
WHERE之后是不可以跟聚集函数的。
HAVING 是作用于组上,记录有多少个组。它要跟着GROUP BY。
--用SQL语句
SELECT *
FROM (SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno)
AS S_G(Sno,Gavg)
WHERE Gavg>=90;
也可以使用基于派生表的查询方式。但是这样查询过程中的派生表是临时定义的,语句执行过后会即被删除。定义视图却是永久性的。
【3.95】 将信息系学生视图IS_Student中学号”201215122”的学生姓名改为”刘辰”。
UPDATE IS_Student
SET Sname= '刘辰'
WHERE Sno= '201215122';
转换后的语句:
UPDATE Student
SET Sname= '刘辰'
WHERE Sno= '201215122'
AND Sdept= 'IS';
更新视图,实际上是更新基本表。
【3.96】
INSERT
INTO IS_Student
VALUES('201215129','赵新',20);
--试图进行的插入或更新已失败,原因是目标视图或者目标视图所跨越的某一视图指定了 WITH CHECK OPTION,而该操作的一个或多个结果行又不符合 CHECK OPTION 约束。
建立视图IS_Student时由WITH CHECK OPTION约束,插入时如果要求必须Sdept=‘IS’.
IS_Student只有三列Sno,Sname,Ssex,通过上述语句在视图中插入数据时,它的属性列就这三点,这种情况下,不管输入什么数据,都没办法达到Sdept=‘IS’的条件,通过这种方式压根就不能设置Sdept的值,我觉得这样插入不了数据,大概。
找到的能插入数据的方式就是,在原表Student中插入满足Sdept='IS’的数据,重新打开视图,就发现这个数据已经躺在视图里了。
INSERT
INTO IS_Studen
VALUES('201215129','赵新',20);
我建立了一个和IS_Student相同但是没有WITH CHECK OPTION约束的视图IS_Student,插入就没有问题。
但是我打开视图IS_Student之后,却并没有显示我插入了数据。
我打开原表Student,原表中却显示添加了赵新这个数据。
我在原表里又添加了符合视图条件(Sdept=‘IS’)的元组,IS_Studen中就多出了一条符合条件的元组。
表中数据改变,依它建立的视图也变化。但对视图使用SQL语句修改时,视图不变化,原表变。
【3.97】删除信息系学生视图IS_Student中学号为”201215129”的记录
DELETE
FROM IS_Student
WHERE Sno= ' 201215129 ';
转换后:
DELETE
FROM Student
WHERE Sno= '201215129' AND Sdept= 'IS';
第三章总结:
数据定义:
1、模式定义与删除:
(1)定义模式:CREATE SCHEMA <模式名>AUTHORIZATION<用户名>;
(2)删除模式:DROP SCHEMA<模式名>;
2、基本表的定义、删除与修改:
--定义
CREATE TABLE<表名>(<列名><数据类型>[列级完整性约束条件]
[,<列名><数据类型>[列级完整性约束条件]]
…
[,表列级完整性约束条件>]);
--修改
ALTER TABLE<表名>
[ADD[COLUMN]<新列名><数据类型>[完整性约束]]
[ADD<标记完整性约束>]
[DROP[COLUMN]<列名>[CASCADE|RESTRICT]]
[DROP CONSTRAINT<完整性约束名>[RESTRICT|CASCADE]]
[ALTER COLUMN<列名><数据类型>];
--删除
DROP TABLE<表名>;
3、索引(INDEX)的建立与删除:
(1)建立:
CREATE [UNIQUE] [CLUSTER] INDEX <索引名>
ON <表名>(<列名>[<次序>][,<列名>[<次序>] ]…);
--次序:ASC,DESC;
--UNIQUE:此索引的每一个索引值只对应唯一的数据记录
(2)修改:
EXEC sp_rename '表名.旧索引名', '新索引名', 'index' (SQLServer中适用)
--
ALTER INDEX <旧索引名> RENAME TO <新索引名>(标准SQL)
(3)删除索引:
DROP INDEX <索引名> on <表名>;(SQLServer)
DROP INDEX <索引名>;(标准SQL)
数据查询:
1、单表查询
(1) SELECT FROM WHERE 是基本形式;
(2)LIKE 与 = 等价,NOT LIKE就是不等于;
(3)模糊查询:
①% (百分号):代表了任意长度(可以是零)的字符串;
②_ (下横线) :代表任意单个字符或者单个汉字(本机如此);
(4)换码字符:要查询的字符串中本身就有_或者%,为了把他们区分开,就要用ESCAPE ‘ <换码字符>’ 对通配符进行转义,表示紧跟在\后面的字符只是普通字符;
(5)IS NULL, IS NOT NULL(“ IS 不能写为 = ”);
(6)AND ,与,用于连接多个查询条件。OR ,或(IN其实是多个OR的运算符的缩写);
(7) ORDER BY:将查找出的数据按照一个属性进行排序。ASC为升序,DESC为降序,没有说明则为ASC。当ORDER BY 后面有两个属性列时,指的是先按第一个属性列进行排序,第一个属性值相同的元组们再按照第二个属性列进行排序,将结果显示出来;
(8)聚集函数(不能跟在where后):
①COUNT(*)是指查询有多少元组(行);
②COUNT(DISTINCT 列名),统计一列中值的个数,这里是不重复的值的个数;
③AVG(列名)计算一列值的平均值;
④MAX(列名)计算一列中的最大值;
⑤SUM(列名),计算一列值的总和;
⑥MIN(列名),计算一列中的最小值;
(9)GROUP BY:按照GROUP BY 后面的列名进行分组,值相等的分成一组。
(10)HAVING :作用于组上,记录有多少个组。它要跟着GROUP BY。
**2、连接查询:**同时涉及两个以上的表的查询
(1)等值与非等值连接查询 :
等值连接:连接运算符为=;
自然连接;
(2)自身连接:一个表与其自己进行连接;
(3)外连接:不仅可以输出满足查询条件的元组,也可以输出不满足条件的元组。 左外连接是列出左边关系中所有的元组 ,右外连接是列出右边关系中所有的元组 ;
(4)多表连接:两个以上的表进行连接。可以对多张表进行操作;
3、嵌套查询:
相关子查询:子查询的查询条件依赖于父查询;(子查询不能使用ORDER BY子句)
不相关子查询:子查询的查询条件不依赖于父查询;
(1)带有IN谓词的子查询;
(2)带有比较运算符的子查询:当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或< >);
(3)带有ANY(SOME)或ALL谓词的子查询;
ANY 大于子查询结果中的某个值
ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
= ANY 大于等于子查询结果中的某个值
= ALL 大于等于子查询结果中的所有值
!=(<>) ANY 不等于查询结果中的某个值
!=(<>) ALL 不等于查询结果中的任何一个值
(4)带有EXISTS谓词的子查询:带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”;全称量词和逻辑蕴涵可用EXIST表示;
**4、集合查询:**并-UNION;交-INTERSECT;差-EXCEPT;
5、基于派生表的查询:
子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表成为主查询的查询对象。如果子查询中没有聚集函数,派生表可以不指定属性列,子查询SELECT子句后面的列名为其缺省属性。
数据更新:
1、插入数据:
(1)插入元组:
INSERT
INTO<表名>[<属性列1><属性列2>...]
VALUES(<常量1>,<常量2>,...)
(2)插入子查询结果(子查询SELECT子句目标列必须与INTO子句匹配)
INSERT
INTO <表名> [(<属性列1> [,<属性列2>… )]
子查询;
2、修改数据:
UPDATE <表名>
SET <列名>=<表达式>[,<列名>=<表达式>]…
[WHERE <条件>];
(1)修改某一个元组的值;
(2)修改多个元组的值;
没有WHERE就可以删除整个表的数据;
(3)带子查询的修改语句;
3、删除数据:
DELETE
FROM <表名>
[WHERE <条件>];
(1)删除某一个元组的值;
(2)删除多个元组的值;
没有WHERE就可以删除整个表的数据;
(3)带子查询的删除语句;
空值的处理
1、空值产生
2、空值判断:IS NULL或IS NOT NULL来判断(IS不能换成=)
3、空值的约束条件:
(1)有NOT NULL约束条件的不能取空值;
(2)加了UNIQUE限制的属性不能取空值;
(3)码属性不能取空值;
视图
特点:
(1)视图是一个虚表,是从一个或几个基本表(或视图)导出的表;
(2)只存放视图的定义,不存放视图对应的数据;
(3)基表中的数据发生变化,从视图中查询出的数据也随之改变;
1、定义、删除视图:
CREATE VIEW
<视图名> [(<列名> [,<列名>]…)]
AS <子查询>
[WITH CHECK OPTION]; --对视图进行更新操作时自动添加子查询中的条件
DROP VIEW <视图名>;
2、查询视图;
3、更新视图;