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