写在前面:本篇博客大部分内容参考数据库系统概念(本科教学版)第三章(第三章部分的多表操作没有在此处讲,准备挪到第四章再一起讨论)
SELECT * 与 SELECT 全字段 的执 行效率是有差别的
- 数据库在具体执行 SELECT * 的时候可以这样理解:首先把 * 替换成对应表的全字段序列,再执行。故在执行的的时候 SELECT * 的效率是会更低的
- 事实上 SELECT * 也是典型的低效语句
- 故在实际应用过程中应该尽量避免使用 SELECT *
where子句 and、or、not的优先级顺序
or < and < not (not的优先级最高)
- 例如:我们要实现“年龄小于16或大于18,并且分数不小于60的所有学生”
于是写出了
1
2
3where age > 18
or age < 16
and not score < 60上面的语句实际表示的是: 分数不小于60并且年龄小于16,或者年龄大于18
- 实际使用的时候不要依赖于它们的优先级顺序!!
- 上面的需求可用下面的语句实现:
1
2where (age > 18 or age < 16)
and score >= 60
- 上面的需求可用下面的语句实现:
SQL 附加的基本运算
更名运算 as
首先存在如上表结构 - 需要事先申明的是,这里所说的更名并不是实际更改数据库中的表结构,更改只是在执行查询操作的过程中得到的结果视图
as 关键字可用于SELECT语句中给字段更名
执行如下语句:
1
2SELECT stu_name as student_name, age, score
FROM Student得到如下结果
as 关键字可用于FROM语句中给表更名
- as可以把一个长的关系名替换成短的,这样在查询语句的其他地方用到这个关系名的时候就会方便不少
执行如下语句
1
2
3
4
5
6
7-- 下面两个语句实现的效果是一样的,但是显然第二种比较简洁
SELECT Student.stu_name, Student.age
FROM Student
SELECT S.stu_name, S.age
FROM Student as S还有一种情况需要用as修改表名,就是需要比较同一个关系中的元组的时候,必须要用别名,要不然无法区分
现在表中有如上数据 - 我们需要查询表中所有比Jane的成绩高的学生的名字
则可以用下面的语句实现:
1
2
3SELECT T.stu_name
FROM Student as T, Student as S
WHERE T.score > S.score and S.stu_name = 'Jane'得到以下结果
大多数数据库中可以用空格替代as
1
2
3
4
5
6
7
8-- 下面两个语句是等价的(在Mysql数据库上测试)
SELECT T.stu_name
FROM Student as T, Student as S
WHERE T.score > S.score and S.stu_name = 'Jane'
SELECT T.stu_name
FROM Student T, Student S
WHERE T.score > S.score and S.stu_name = 'Jane'注意:Oracle数据库更改表的别名不能用 as(但是改字段的别名是可以用as的), 只能用空格,要不然会报错(比如上面的两个语句在大多数数据库执行都是可以通过而且结果一致的,但是在Oracle数据库第一条语句就不会过)**
如果别名中带空格,则别名需要用双引号引起来(因为空格也是可以替代as的,所以如果别名中含有空格而不做处理,可能会导致数据库无法解析这条语句)
首先看下面这条语句
1
2
3-- 下面这条语句想给Student表起一个别名,叫做 Student Info, 执行是会失败的
SELECT Student Info.stu_name
FROM Student as Student Info正确的操作应该是这样的
1
2SELECT "Student Info".stu_name
FROM Student as "Student Info"
字符串的拼接运算
不用数据库采用不同的运算符,常见的有 || 和 +
现在表中有如上数据 执行下面的语句(笔者是在Mysql下测试的,Mysql的字符串拼接是用connect函数实现的,所以略有不同)
1
2SELECT S.stu_name, concat('name: ', S.stu_name) as info
FROM Student as S得到如下结果
对于null值的处理,不同的数据库采取的处理不同
- Oracle会直接忽略空值,而DB2会使整体为null
下面在Mysql中测试与空值拼接,结果是会使整体为null
执行以下语句
1
2SELECT S.stu_name, concat('name: ', S.stu_name, NULL ) as info
FROM Student as S结果如下
可以与字符串常量拼接
- sql里面就用一对单引号包含一个字符串表示字符串常量,如’name: ‘
- 上面的例子里面就用到了与字符串常量拼接,这里就不再赘述了
如果字符串常量里面需要包含单引号,可以用另一个单引号来转义
比如执行下面的语句
1
2
3# 下面的字符串常量中出现了四个单引号,其中首位两个是用来标示这个是一个字符串常量,第二个单引号是用来转义第三个单引号
SELECT S.stu_name, concat('I''m ', S.stu_name) as info
FROM Student as S结果如下:
函数
- 其实函数每个数据库都有各自的实现,种类和功能不尽相同
- 比如上面的connect函数是Mysql中的一个函数
- upper(s)和lower(s)函数是用来将字符串全部变成大写/小写的函数
模糊匹配(like)
通配符(具体到某个具体的数据库可能还会有功能更强大的通配符,这里只讨论比较通用的两个)
- % ==>匹配任意长度的字符串(字符串的长度也可以是0)
- _ ==>匹配一个字符
- 举个栗子:
1
2
3
4
5-- 下面的语句标示查询条件是第三个字符是A的stu_name
WHERE stu_name LIKE '__A%'
-- 下面的语句标示查询条件是第三个字符是A,且长度至少为4的stu_name
WHERE stu_name LIKE '__A_%'
现在表中还是有如上数据 执行下面操作
1
2
3
4-- 下面的语句用来查询表中stu_name的值为Ja开头,且至少长度为三的所有学生名字
SELECT stu_name
FROM Student
WHERE stu_name LIKE 'Ja_%'得到如下结果
如果模式串(我们这里称like后面的串为模式串)中需要包含‘_’或者‘%’等通配符关键字,就需要用到转义,SQL里面用escape来指定转义字符
- 举个栗子:
1
2
3-- 下面的语句在最后面定义‘\’为转义字符
-- 所以实际的效果是匹配所有以 Ja_ 开头的 stu_name
WHERE stu_name LIKE 'Ja\_%' escape '\'
- 举个栗子:
排序(order by)
- 如果没有显示指定升序还是降序,则默认是采用升序的
null 值的处理(不同的数据库采取的处理不同)
- Oracle 将null值当做最大
- SQL Server 将null值当做最小
接下来来去测测Mysql数据库
首先表中的数据是上面酱紫的
然后执行下面操作
1
2
3
4
5-- 下面的语句查询学生表中的所有数据,并按成绩排序(因为没有指定
-- 升序还是降序,所以默认是升序的)
SELECT *
FROM Student
ORDER BY score;结果如下(可以看出,Mysql是将null值当做最小值)
在排序的时候可以用desc显示指定降序,asc显示指定升序
举个栗子
1
2-- 下面的排序条件标示先按score降序排序,如果遇到score相同的,则按age升序排序
ORDER BY score desc, age ascorder by 后面所跟字段,以在前面的字段为主进行排序
- desc、asc 更在字段名或表达式后面,并且只能影响其前面的一个字段
- 举个栗子
1
2
3-- 下面的排序条件表示,先以score进行升序排序(因为未指定的话默认是升序的),
-- 如果遇到score相同的再按age进行降序排序
order by score, age desc
- 举个栗子
order by 后面可跟别名,字段名,表达式,字段的顺序号
- 别名、字段名
表达式
- 举个栗子
1
2-- 下面排序条件标示把sal*12后按结果降序排序
order by 12 * sal desc
- 举个栗子
字段的顺序号:
- 举个栗子
1
2
3
4-- 下面这条语句标示查询Sudent表中的所有数据,并按age和score进行升序排序(默认是升序排序)
SELECT student_name, age, score
FROM Student
ORDER BY 2, 3
- 举个栗子
如果要查询的结果集是很大的,排序是很耗时的,会影响性能
where子句beween…and、in
- between…and(表示一个连续的范围)
- between a and b <==> a <= x <= b
- not between a and b <==> x > b | x < a
- 写的时候,小数写在前面,大数写在后面
- in(表示离散的范围)
- 举个栗子
1
2
3
4# 下面的语句表示查询分数为98、99或者100的学生的信息
SELECT student_name, age, score
FROM Student
where score in (98, 99, 100)
- 举个栗子
- between…and(表示一个连续的范围)