增:INSERT
INSERT语句常用的格式有三种:
语法格式一:
INSERT [INTO] table_name VALUES(constant1,constant2,…)...
该语句的功能是向由table_name指定的表中插入由VALUES指定的各列值的行。
VALUES中给出的数据顺序和数据类型必须与表中列的顺序和数据类型一致,而且不可以省略部分列。
允许为空的列的值可以为null。
identity列不能赋值。自动计算列不能赋值。
有默认值的列必须赋值。不允许为空的列必须赋值。
如:
语法格式二:
INSERT [INTO] table_name(column_1,column_2,...column_n) VALUES(constant_1,constant_2,…constant_n)...
如:
insert XSDA(学号,性别) values('123412','男')
说明:
table_name后面出现的列,VALUES里面要有数据一一对应。
语法格式三:
INSERT [INTO] table_name[(column_list)] derived_table
说明:
功能:将一个查询的结果集插入到另一个表中。
table_name:要插入数据的表名。必须已存在。
column_list:要在其中插入数据的一列或多列的列表。可省略,则由derived_table中的列依次赋值。
derived_table:任何有效的 SELECT 语句。
结果集的列数、列的次序、数据类型要和column_list中一致。
如:
Student (Sno, Sname, Sage) S1(姓名, 年龄)
INSERT INTO S1(姓名, 年龄)
SELECT Sname,Sage FROM Student
WHERE Sage = 20;
使用SELECT INTO:插入数据/保存查询结果
使用select into语句允许用户定义一个新表,同时也会将select的结果数据插入到新表中。
前面三种方法的共同点就是表在输入数据之前已经存在。使用select inot方法是在插入数据的过程中创建新表,其语法形式如下:
SELECT select-list INTO new_table_name FROM table_list WHERE search_conditions
如:
SELECT Sno , Sname
INTO S_Math
FROM Student
WHERE Sdept = 'Math';
结果:得到一个新表:S_Math(Sno , Sname)
日期的插入:
insert into test (date1) values ( '2017-10-01 ') /*日期需要放在引号里*/
删:DELETE
如:
删除200502学生的学生信息。
delete from XSDA where 学号='200502'
改:UPDATE
如:
把所有成绩置空。
update sc set 成绩=NULL
修改课程507的学分为4、学时为64。
update KCXX set 学分='4',学时='64' where 课程编号='507'
查:SELECT
SELECT子句实现列查询
SELECT 列名1 【,…列名n】
1.选取表中指定的列
例:
查询全体学生的学号与姓名。
SELECT Sno,Sname FROM Student;
SELECT Sname,Sno,Sdept FROM Student;
查询全部列:选出所有属性列。
1、在SELECT关键字后面列出所有列名
2、将<目标列表达式>指定为 *
查询全体学生的详细记录。
SELECT Sno, Sname, Ssex , Sage, Sdept FROM Student;
SELECT * FROM Student;
2.修改查询结果中的列标题
当希望查询结果中的某些列不显示表结构中规定的列标题,而使用用户自己另外选择的列标题时,可以在列名之后使用AS子句来更改查询结果中的列标题名。
例:查询KCXX表中所有课程的课程编号、课程名称,查询结果中要求各列的标题分别指定为course_num和course_name。
SELECT 课程编号 AS course_num,课程名称 AS course_name FROM KCXX /*AS可省略*/
3.计算列值
使用SELECT语句对列进行查询时,在结果中可以输出对列值计算后的值,即SELECT子句可使用表达式作为查询结果。格式为:
SELECT expression 【 , expression 】
例:设XSCJ表中的成绩为考试成绩,要求按照公式(期末成绩=成绩*0.8)换算成期末成绩显示出来。
SELECT 学号, 课程编号, 期末成绩=成绩*0.8 FROM XSCJ
SELECT 学号, 课程编号, 成绩*0.8 期末成绩 FROM XSCJ
查询全体学生的姓名、出生年份和所在系,要求用小写字母表示所在系名,且出生年份前有提示信息' Year of Birth: '(不是列名,而是一个常量) 。
SELECT Sname,‘Year of Birth: ' ,2018-Sage,LOWER(Sdept) FROM Student;
极端情况
SELECT '123', 8-2, 课程名称 FROM KCXX
4.消除结果集中的重复行
对表只选择某些列时,可能会出现重复行,例如,若对XSDA表只选择系名,则会出现多行重复的情况。可以使用DISTINCT关键字消除结果集中的重复行。
语法格式:
SELECT DISTINCT column_name【,column_name…】
说明:关键字DISTINCT的含义是对结果集中的重复行只选择一个,保证行的唯一性。
例:查询XSDA表中所有的系名,消除结果集中的重复行。
SELECT DISTINCT 系名 FROM XSDA
注:当DISTINCT后面有多列时,DISTINCT指的是整行值不重复。
与DISTINCT相反,当使用关键字ALL时,将保留结果集中的所有行。当SELECT语句中省略ALL与DISTINCT时,默认值为ALL。
例:
SELECT ALL 系名 FROM XSDA
5.限制结果集返回行数
如果SELECT语句返回的结果集中的行数特别多,不利于信息的整理和统计,可以使用TOP选项限制其返回的行数。
TOP选项的基本格式为:
TOP n 【PERCENT】
其中n是一个正整数,表示返回查询结果集的前n行。若带PERCENT关键字,则表示返回结果集的前n%行。
例:查询XSCJ表中所有学生的学号、课程编号和成绩,只返回结果集的前10行。
SELECT TOP 10 学号,课程编号,成绩 FROM XSCJ
对 KCXX表查询输出课程名称,学分,只返回结果集的前30%行。
select top 30 percent 课程名称,学分 from KCXX
WHERE子句实现条件查询
**1. 比较表达式作查询条件
- 逻辑表达式作查询条件
- 模式匹配:like
- 范围比较:between...and、in
- 空值比较: IS [NOT] NULL**
比较大小
查询CS系全体学生的姓名。
SELECT Sname FROM Student WHERE Sdept=‘CS’;
查询所有年龄在20岁以下的学生姓名及其年龄。
SELECT Sname,Sage FROM Student WHERE Sage < 20;
查询考试成绩有不及格的学生的学号。
SELECT DISTINCT Sno FROM SC WHERE Grade<60;
确定范围
谓词: BETWEEN … AND …;NOT BETWEEN … AND …
查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄。
SELECT Sname,Sdept,Sage FROM Student WHERE Sage BETWEEN 20 AND 23;
SELECT Sname,Sdept,Sage FROM Student WHERE Sage>=20 AND Sage<=23;
查询年龄不在20~23岁之间的学生姓名、系别和年龄。
SELECT Sname,Sdept,Sage FROM Student WHERE Sage NOT BETWEEN 20 AND 23;
SELECT Sname,Sdept,Sage FROM Student WHERE Sage<20 OR Sage>23;
确定集合
谓词:IN <值表>, NOT IN <值表>
查询IS系、MA系和CS系学生的姓名和性别。
SELECT Sname,Ssex FROM Student
WHERE Sdept IN ( 'IS','MA','CS' );
查询既不是IS系、MA系也不是CS系的学生的姓名和性别。
SELECT Sname,Ssex FROM Student
WHERE Sdept NOT IN ( 'IS','MA','CS' );
字符匹配
谓词: [NOT] LIKE ‘<匹配串>’ [ESCAPE ‘ <换码字符>’]
匹配串为固定字符串
查询学号为200215121的学生的情况。
SELECT * FROM Student
WHERE Sno = ' 200215121 ' ;
SELECT * FROM Student
WHERE Sno LIKE ‘200215121';
匹配串为含通配符的字符串
%:任意长的任意字符串;
_: 任意一个字符。
查询所有姓王的学生的姓名、学号和性别。
SELECT Sname,Sno,Ssex FROM Student
WHERE Sname LIKE ‘王%’;
查询姓"欧阳"且全名为三个汉字的学生的姓名。
SELECT Sname FROM Student
WHERE Sname LIKE '欧阳_ _';
注:ASCII码:一个汉字占两个字符。GBK:一个汉字占一个字符。
使用换码字符将通配符转义为普通字符
查询名为DB_Design的课程的课程号和学分。
SELECT Cno,Ccredit FROM Course
WHERE Cname LIKE 'DB\_Design' ESCAPE '\'
由于是一个通配符,表示任一字符,因此, 如果想把DB_Design中的作为一个普通字符,必须在它之前使用转意符\,使其不再具有通配符含义。
NULL含义为空、空值,表示不确定、不存在
谓词: IS NULL 或 IS NOT NULL
“IS” 不能用 “=” 代替
查询缺少成绩的学生的学号和相应的课程号(某些学生选修课程后没有参加考试,所以有选课记录但没有考试成绩)
SELECT Sno,C FROM SC
WHERE Grade IS NULL
查询所有有成绩的学生学号和课程号
SELECT Sno,Cno FROM SC
WHERE Grade IS NOT NULL
逻辑运算符:AND和 OR来联结多个查询条件
AND的优先级高于OR
可以用括号改变优先级
查询CS系年龄在20岁以下的学生姓名
SELECT Sname
FROM Student
WHERE Sdept= 'CS' AND Sage<20;
分类汇总
使用聚合函数
使用SELECT语句进行分组筛选和汇总计算
聚合函数
查询学生200215012的总分数
SELECT SUM(Grade) FROM SC WHERE Sno='200215012';
查询1号课程的最高分数
SELECT MAX(Grade) FROM SC WHERE Cno= '1' ;
查询学生总人数
SELECT COUNT(*) FROM Student;
查询选了课的学生人数
SELECT COUNT(DISTINCT Sno) FROM SC;
GROUP BY分组筛选数据
【GROUP BY group_by_expression【,…n】】
说明:group_by_expression是用于分组的表达式,其中通常包含字段名。SELECT子句的列表中只能包含子句GROUP BY中指出的列或在聚合函数中指定的列。
简单分组
求XSDA表中各系的男、女生各自的人数。
SELECT 性别, COUNT(*) AS '人数'
FROM XSDA
GROUP BY 性别
求XSDA表中各系的男、女生各自的总学分的平均值。
SELECT 系名, 性别, AVG(总学分) AS '总学分的平均值'
FROM XSDA
GROUP BY 系名, 性别
使用HAVING筛选结果
使用GROUP BY子句和聚合函数对数据进行分组后,还可以使用HAVING子句对分组数据进一步筛选。
语法格式:
【HAVING <search_condition>】
说明:search_condition为查询条件,与WHERE子句的查询条件类似,并且可以使用聚合函数。
例:查找XSCJ表中平均成绩在90分以上的学生的学号和平均分。
SELECT 学号, AVG(成绩) AS '平均分'
FROM XSCJ
GROUP BY 学号
HAVING AVG(成绩)>=90
注意:在SELECT语句中,当WHERE、GROUP BY与HAVING子句同时被使用时,要注意它们的作用和执行顺序:
WHERE用于筛选由FROM指定的数据对象,即从FROM指定的基表或视图中检索满足条件的记录;
GROUP BY用于对WHERE的筛选结果进行分组;
HAVING则是对使用GROUP BY分组以后的数据进行过滤。
查找选修课程超过3门,并且成绩都在90分以上的学生的学号。
SELECT 学号
FROM XSCJ
WHERE 成绩>=90
GROUP BY 学号
HAVING COUNT(学号)>3
ORDER BY子句:对查询结果进行排序
ORDER BY子句
- 使查询结果可以按一个或多个属性列排序
- 升序:ASC;降序:DESC;缺省值为升序
当排序列含空值时 - ASC:排序列为空值的元组最后显示
- DESC:排序列为空值的元组最先显示
查询选修了3号课程的学生的学号及其成绩,结果按分数降序排列
SELECT Sno,Grade FROM SC
WHERE Cno= ' 3 '
ORDER BY Grade DESC;
查询全体学生,结果按系号升序排列,同一系学生按年龄降序排列
SELECT * FROM Student
ORDER BY Sdept,Sage DESC;
连接查询
使用连接查询实现多表查询
在SQL Server中,连接查询分为:
内连接、外连接、交叉连接、自连接
内连接
FROM <table_source> 【INNER】 JOIN <table_source> ON <search_condition>
<table_source>为需要连接的表,ON用于指定连接条件,
<search_condition>为连接条件。INNER表示内连接。
例:查找XS数据库中每个学生的情况以及修课情况。
SELECT *
FROM XSDA INNER JOIN XSCJ
ON XSDA.学号=XSCJ.学号
SELECT XSDA .* , XSCJ.*
FROM XSDA INNER JOIN XSCJ
ON XSDA.学号=XSCJ.学号
内连接是系统默认的,可以省略INNER关键字。使用内连接后仍可使用WHERE子句指定条件。
例:查找选修了202号课程并且成绩优秀的学生的姓名及成绩。
SELECT 姓名, 成绩
FROM XSDA JOIN XSCJ ON XSDA.学号=XSCJ.学号
WHERE 课程编号='202' AND 成绩>=90
内连接还可以使用以下连接谓词的形式实现,执行结果相同:
SELECT 姓名, 成绩
FROM XSDA, XSCJ
WHERE XSDA.学号=XSCJ.学号 AND 课程编号='202' AND 成绩>=90
连接操作中,对于出现在两个及以上表中的列,必须在列名前用.运算表达其所属表。对于只出现在一个表中的列名不要求,但可以书写。
外连接
外连接的结果表中不但包含满足连接条件的行,还包括相应表中的所有行。外连接包括以下3种。
1.左外连接
左外连接的结果表中除了包括满足连接条件的行外,还包括左表的所有行。
语法格式:
FROM <table_source> LEFT 【OUTER】 JOIN <table_source> ON <search_condition>
例:查找所有考生的录取情况(未被录取的考生也要显示其考号和姓名,并在LQXX表的相应列中显示NULL)。
SELECT KSMD.* , LQXX.*
FROM KSMD LEFT JOIN LQXX ON KSMD.考号=LQXX.考号
2. 右外连接
右外连接的结果表中除了包括满足连接条件的行外,还包括右表的所有行。
语法格式:
FROM <table_source> RIGHT 【OUTER】 JOIN <table_source> ON <search_condition>
例:查找所有大学的录取情况
SELECT考号,校名
FROM LQXX RIGHT JOIN XXMDON LQXx.录取学校=XXMD.校名
order by考号
3.完全外连接
完全外连接的结果表中除了包括满足连接条件的行外,还包括两个表的所有行。
语法格式:
FROM <table_source> FULL 【OUTER】 JOIN <table_source> ON <search_condition>
说明:外连接只能对两个表进行,其中的OUTER关键字均可以省略
例:查找所有考生及所有学校的情况。
SELECT KSMD.* , LQXX.*
FROM KSMD FULL JOIN LQXX
ON KSMD.考号=LQXX.考号
4. 交叉连接
交叉连接实际上是将两个表进行笛卡儿积运算,结果表是由第一个表的每行与第二个表的每一行拼接后形成的表,因此结果表的行数等于两个表行数之积。
语法格式:
FROM <table_source> CROSS JOIN <table_source>
SELECT KSMD.*,LQXX.*
FROM KSMD CROSS JOIN LQXX
5. 自连接
连接操作不仅可以在不同的表上进行,也可以在同一张表内进行自身连接,即将同一个表的不同行连接起来。
若要在一个表中查找具有相同列值的行,则可以使用自连接。
自连接可以看作一张表的两个副本之间的连接。
使用自连接时需要为表指定两个别名,使之在逻辑上成为两张表。对所有列的引用均要用别名限定。
连接操作中,对于出现在两个及以上表中的列,需要在列名前用.运算表达其所属表。对于只出现在一个表中的列名不要求。
例:在XSDA表中查找同名学生的学号、姓名。即学号、姓名、以及同名者的学号。
SELECT XSDA1.学号,xSDA1.姓名, XSDA2.学号
FROM XSDA AS xSDA1 , XSDA AS xSDA2
WHERE XSDA1.姓名=XSDA2.姓名
and XSDA1.学号<>XSDA2.学号
order by xSDA1.学号
子查询和保存结果集
IN子查询
IN子查询用于进行一个给定值是否在子查询结果集中的判断。
语法格式:
expression 【NOT】 IN (subquery)
说明:subquery是子查询。当表达式expression与子查询subquery的结果表中的某个值相等时,IN谓词返回TRUE,否则返回FALSE;若使用了NOT,则返回的值刚好相反。
例:查找选修了108号课程的学生的学号、姓名、性别、系名。
SELECT 学号,姓名,性别,系名 FROM XSDA
WHERE 学号 IN
(SELECT 学号 FROM XSCJ
WHERE 课程编号='108')
- IN和NOT IN 子查询只能返回一列数据。
- 对于较复杂的查询,可以使用嵌套的子查询。
比较子查询
比较子查询可以认为是IN子查询的扩展,它使表达式的值与子查询的结果进行比较运算。
语法格式:
expression{<|<=|=|>|>=|!=|<>||!<|!>}{ALL|SOME|ANY}(subquery)
说明:expression为要进行比较的表达式,subquery是子查询。
ALL指定表达式要与子查询结果集中的每个值都进行比较,当表达式与每个值都满足比较的关系时,才返回TRUE,否则返回FALSE。
SOME或ANY表示表达式只要与子查询结果集中的某个值满足比较的关系时,就返回TRUE,否则返回FALSE。
例:查找高于所有女生的总学分的学生的情况。
SELECT *
FROM XSDA
WHERE 总学分 >ALL
(SELECT 总学分
FROM XSDA
WHERE 性别='女')
例:查找高于所有女生的总学分的学生的学号、姓名、总学分。
SELECT学号,姓名,总学分
FROM xSDA
wHERE 总学分>
(SELECT max(总学分)
FROM XSDA
WHERE性别='女')
例:查找202号课程的成绩不是最后一名的所有学生的学号。
SELECT 学号,成绩
FROM xscJ
WHERE 课程编号='202'
AND 成绩>any
( SELECT 成绩
FROM xScJ
wHERE课程编号='202')
order by 成绩 desc
保存查询结果
SELECT语句提供了两个子句来保存、处理查询结果,分别是INTO子句和UNION子句。
INTO子句
使用INTO子句可以将SELECT查询所得的结果保存到一 个新建的表中。
语法格式:
【INTO new_table】
说明:new_table是要创建的新表名。包含INTO子句的SELECT语句执行后所创建的表的结构由SELECT所选择的列决定。新创建的表中的记录由SELECT的查询结果决定。
若SELECT的查询结果为空,则创建一个只有结构而没有记录的空表。
例:由XSDA表创建“信息系学生表”,包括学号、姓名、系名、总学分。
SELECT 学号,姓名,系名,总学分
INTO 信息系学生表
FROM XSDA WHERE 系名='信息'
UNION子句
使用UNION子句可以将两个或多个SELECT查询的结果合并成一个结果集。
语法格式:
SELECT语句 UNION 【ALL】 SELECT语句
说明:
关键字ALL表示合并的结果中包括所有行,不去除重复行,不使用ALL则在合并的结果中去除重复行。
如果要保存结果,需要在第一个SELECT语句中使用INTO子句。
例:假设在XS数据库中已经建立了两个表:电气系学生表、轨道系学生表,表结构与XSDA表相同,这两个表分别存储电气系和轨道系的学生档案情况,要求将这两个表的数据与XSDA的数据合并。
SELECT * FROM XSDA
UNION ALL
SELECT * FROM 电气系学生表
UNION ALL
SELECT * FROM 轨道系学生表
(1)联合查询是将两个表(结果集)顺序连接。
(2)UNION中的每一个查询所涉及到的列必须具有相同的列数、相同位置的列的数据类型要相同。若长度不同,以最长的字段作为输出字段的长度。
(3)最后结果集中的列名来自第一个SELECT语句。
(4)最后一个SELECT查询可以带ORDER BY子句,对整个UNION操作结果集起作用。且只能用第一个SELECT查询中的字段作排序列。
(5)系统自动删除结果集中重复的记录,除非使用ALL关键字。