SQL
SQL数据定义
- char(n) :n个长度的固定字符串
- varchar(n) :最大n个长度的可变长字符串
- int :整数
- smallint :小整数
- numeric(p,d) :这个数有p位数字,小数点后d位数字。如numeric(3,1)可以存储33.3 ,44.4
- float(n) :精度至少为n的单精度浮点数
- double :双精度浮点数
- date :日期,格式YYYY-MM-DD
- time :时间,格式HH:MM:SS
- timestamp :时间戳,格式YYYY-MM-DD HH:MM:SS
DDL
DDL是数据库定义语言,用于创建修改删除数据库的结构
创建数据库
1 | create table table_name( |
有几点需要注意:
- 主键用primary key($A_1$,$A_2$…)定义
- 候选键用unique关键字定义
- 非空约束用not null关键字定义
- 检查约束用check()定义
- 外键用foreign key($A_1$,$A_2$…) references other_table定义
- 默认值用default关键字定义
删除关系
1 | drop table table_name; # 删除表 |
修改关系
1 | alter table table_name |
DML
增删改查CRUD
查
1 | insert into table_name (id,name,address) values (1,'Alice','Beijing'); |
select
select distinct name from table;
这样查询结果中name列不会有重复值。如果不加distinct,默认name可能会有重复
select查询对象还可以进行算术运算
1 | select id, name, age + 1 as age_next_year from table_name; |
as 是起别名
where
where子句中可以使用逻辑运算符 and , or , not 来组合多个条件
1 | select * from table_name where address='Beijing' and age>20; |
where子句谓词:
- between … and … : 在某个范围内(包含边界值)
1 | select * from table_name where age between 20 and 30; |
连表查询
查询结果涉及多个表
1 | select instructor.name, teaches.course_id |
现在可以给出SQL的一般形式
-
select子句用于列出查询结果中所需要的属性
-
from子句是在查询求值中需要访问的关系列表
-
where子句是作用在from子句中的关系的属性上的谓词
一个典型的SQL查询具有如下形式:select $A_1$ ,$A_2$ ,…,$A_n$
from $r_1$,$r_2$,$r_3$…$r_m$
where P;
执行顺序是先from,再where,最后select
order by
对查询结果排序
1 | select * from table_name order by age desc; |
默认是升序asc,降序用desc
可以按多个列排序
1 | select * from table_name order by age desc, name asc; |
这样先按age降序排序,age相同的再按name升序排序
集合运算
SQL支持并,交,差三种集合运算
1 | select * from table1 |
union自动去除重复项。要想保留重复项,可以使用 union all。intersect和except也会自动去除重复项,同样后面加all解决
聚集函数
SQL提供了多种聚集函数来对一组值进行计算,常用的有:
- count() : 计数
- sum() : 求和
- avg() : 求平均值
- min() : 求最小值
- max() : 求最大值
除了count(*)之外,其他聚集函数都忽略null值
1 | select count(*), avg(age), max(salary) from table_name; |
有时count()会和distinct一起使用,计算某列不同值的个数
1 | select count(distinct name) from table_name; |
分组查询
SQL提供了group by子句来对查询结果进行分组
1 | select department, count(*) from employees |
上面查询结果会显示每个部门的员工数量
在每个分组上执行相应的操作,
要确保select子句中的非聚集函数列都出现在group by子句中
分组过滤 having
SQL提供了having子句来对分组后的结果进行过滤
1 | select department, count(*) from employees |
包含聚集、group by或having子句的查询的含义可通过下述运算序列来定义:
- 与不带聚集的查询情况类似,首先根据from子句来计算出一个关系。
- 如果出现了where子句,where子句中的谓词将应用到from子句的结果关系上。
- 如果出现了group by子句,满足where谓词的元组通过group by子句被放入分组中。如果没有group by子句,满足where谓词的整个元组集被当成一个分组。
- 如果出现了having子句,它将应用到每个分组上;不满足having子句谓词的分组将被去掉。
- select子句利用剩下的分组产生查询结果中的元组,即在每个分组上应用聚集函数来得到单个结果元组。
嵌套子查询
集合成员资格
连接词 in 用于测试某个值是否在子查询的结果集中,这个结果集就是select子句产生的一组值
1 | select name from students |
集合比较
至少比某一个大用 some>表示
1 | select name from students |
这句SQL表示查询学生中年龄大于计算机系任意一位教师年龄的学生
全部比某一个大用 all>表示
1 | select name from students |
这句SQL表示查询学生中年龄大于计算机系所有教师年龄的学生
空关系测试
存在用 exists表示
1 | select name from students |
这句SQL表示查询学生中存在计算机系教师年龄小于该学生年龄的学生
重复元组存在性测试
unique用来测试子查询结果中是否有重复元组
1 | select name from students |
这句SQL表示查询学生中其所在系只有一位教师的学生
在不使用unique的情况下,可以用count()来实现类似功能
1 | select name from students |
from子查询
from子查询用于在from子句中嵌套一个查询,作为一个临时表使用
1 | select name, age from |
这里的temp是给子查询结果起的别名
with子句
with子句提供了一种定义临时关系的方式。这个定义只对with子句的查询有效
1 | with temp(name, age) as |
标量子查询
标量子查询是返回单个值的子查询,可以在select子句或where子句中使用
1 | select name, age from students |
不带from子句的标量
1 | select (select count(*) from students) /(select count(*) from instructors) as student_instructor_ratio from dual; |
这里的dual是Oracle数据库中的一个特殊表,包含一行一列,用于执行不依赖于任何表的查询。在其他数据库中,可以省略from子句,直接使用select语句。
改
删除
1 | delete from instructor where salary < 50000; |
插入
1 | insert into instructor (name, age, salary) values ('John Doe', 35, 60000); |
如果我们想插入查询出来的一些元组
1 | insert into high_salary_instructors |
更新
1 | update instructor set salary = salary * 1.1 where department = 'CS'; |
SQL提供case结构,可以根据不同条件设置不同的值
1 | update instructor set salary = case |
连接表达式
自然连接
自然连接是最常用的连接操作,表示两个关系中所有同名属性相等的元组进行连接
1 | select * from table1 natural join table2; |
在此之前我们是这样写的
1 | select * from table1, table2 |
连接条件
on子句用于指定连接条件
1 | select * from table1 join table2 on table1.common_attr = table2.common_attr; |
外连接
外连接用于保留某个关系中的所有元组,即使它们在连接中没有匹配的元组
左外连接
左外连接保留左侧关系中的所有元组,并将右侧关系中匹配的元组连接上去
1 | select * from table1 left join table2 on table1.common_attr = table2.common_attr; |
右外连接
右外连接保留右侧关系中的所有元组,并将左侧关系中匹配的元组连接上去
1 | select * from table1 right join table2 on table1.common_attr = table2.common_attr; |
全外连接
全外连接保留两个关系中的所有元组,并将匹配的元组连接上去
1 | select * from table1 full join table2 on table1.common_attr = table2.common_attr; |
视图
视图定义
使用 create view语句定义视图
1 | create view view_name as |
