连接可以替换子查询,并且⼀般比子查询的效率更快
natural join
出现在结果关系中的两个连接关系的元组在全部公共属性上取值相等,且公共属性只出现一次
natural join 关系名 using (A1,A2,...,An)
,(A1,A2,…,An)是两个连接关系的公共属性的子集,元组在(A1, A2 ,…, An)上取值相等,且(A1, A2 ,…, An)只出现一次
natural join 关系名 on <谓词P>
出现在结果关系中的两个连接关系的元组在公共属性上取值满足谓词条件P,且公共属性出现两次(但取值完全相同)
示例:只显示一次ID值和显示两次ID值的不同
/*显示两次ID*/
select *
from student join takes on student.ID=takes.ID
/*只显示一次ID*/
select student.ID as ID,name,dept_name,tot_cred,course_id,sec_id,semester,year,grade
from student join takes on student.ID=takes.ID
在from中作用于多个关系,产生一个关系作为结果
在结果关系中的两个连接关系的元组在公共属性上取值相等
结果关系中,公共属性只出现一次。顺序是先列出公共属性,然后是只出现在第一个关系中的属性,最后是那些只出现在第二个关系中的属性
按指定属性连接,不考虑未指定的共同属性
只考虑关系名2与关系名1在属性名1…属性名n上的匹配,其他的共有属性不考虑
这里的关系名可以是自然连接后的关系,即from(关系名1 join 关系名2)join 关系名3 using (属性名1,属性名2,...属性名n)
通过on <谓词>
子句决定两个关系中哪些元组相互匹配,以及连接结果中出现哪些属性
on子句特点
on条件可表示任何谓词,可表示比自然连接更丰富的连接条件
对于外连接,on条件的表现与where不同(在下文中会做出详细解释
可以用on替代where限定条件,而on和where仍可同时存在,只是限定的条件不同——在on子句中指定连接条件,在where中指定其他条件,更清晰易懂
示例:下面两个代码是等价的
select *
from student, takes
where student.ID=takes.ID
/******/
select *
from student join takes on student.ID=takes.ID
决定如何处理与连接条件不匹配的元组
inner join
内连接提供连接的列,而自然连接自动连接所有同名列,因此自然连接是内连接的一种,即natural join等价于natural inner join
outer join
通过在结果中创建包含空值元组的方式,保留那些在连接中丢失的元组
left outer join
right outer join
full outer join
示例
select *
from student left outer join takes on true
where student.ID=takes.ID
代码解释
on条件是外连接声明为true的一部分
where子句不是且会排出不符合条件的元组
此例结果中不会包含空值的元组
外连接实际产生了两个关系的笛卡尔积
简而言之,先on后where
SQL 中 on 条件与 where 条件的区别示例详解补充博客
cross join:两个关系的笛卡儿积
union join:左边关系中失配的元组+ 右边关系中失配的元组
对于外连接,连接条件是必须的
对于内连接,连接条件是可选的,没有连接条件等价于两个关系的笛卡儿积
已知关系R
A | B | C |
---|---|---|
a1 | b1 | c1 |
a2 | b2 | c2 |
a3 | b3 | c3 |
已知关系S
C | D |
---|---|
c1 | d1 |
c2 | d2 |
c4 | d3 |
内连接 R inner join S on R.C = S.C
A | B | R.C | S.C | D |
---|---|---|---|---|
a1 | b1 | c1 | c1 | d1 |
a2 | b2 | c2 | c2 | d2 |
左外连接 R left outer join S on R.C = S.C
A | B | R.C | S.C | D |
---|---|---|---|---|
a1 | b1 | c1 | c1 | d1 |
a2 | b2 | c2 | c2 | d2 |
a3 | b3 | c3 | null | null |
右外连接 R natural right outer join S
C | D | A | B |
---|---|---|---|
c1 | d1 | a1 | b1 |
c2 | d2 | a2 | b2 |
c4 | d3 | null | null |
全外连接 R full outer join S on R.C = S.C
A | B | R.C | S.C | D |
---|---|---|---|---|
a1 | b1 | c1 | c1 | d1 |
a2 | b2 | c2 | c2 | d2 |
a3 | b3 | c3 | null | null |
null | null | null | c4 | d3 |
create view
定义视图
create view 视图名<(属性名,属性名...)]>
as (查询表达式)
drop view
撤消视图
drop view 视图名
视图是基于 SQL 语句的结果集的可视化的表
作为虚关系,对用户可见的关系,本身不包含数据,也就不能对其进行索引操作
视图关系在概念上包含查询结果的元组,但并不进行预计算和存储结果元组,只存储与视图关系相关联的查询表达式。当视图关系被访问时,才计算产生查询结果元组
view和table的区别
表被创建时表的内容被加载
视图的内容总是反映着当前查询的结果
在查询中,视图名可以出现在任何关系名可以出现的地方
视图的属性名缺省为子查询结果中的属性名,也可以显式指明
视图更新最终是对所涉及的实表的更新。由视图更新导致实表更新可能带来问题,简而言之,视图更新需要条件
from 子句中只有一个数据库关系
select 中只包含关系属性名,不包含表达式、聚集、distinct声明
没有出现在select子句中的任何属性允许null的存在,出现在select子句中的(显然是主码)有非空约束
查询中不含group by 或 having 子句
视图定义时,指定with check option
,则用户通过视图进行数据修改时,结果必须为满足视图where子句条件的元组,否则拒绝更新
/*无with check option*/
create view sv1 as
select sno,sname,sage from s
where sdept = '计' and sage >= 20;
update sv1 set sage = 19 where sno = 's2';
/*可以更新,更新后元组不再出现在视图中*/
/*有with check option*/
create view sv1 as
select sno,sname,sage from s
where sdept = '计' and sage >= 20
with check option;
update sv1 set sage=19 where sno = 's2';
/*不可以更新,update语句将被DBMS拒绝*/
- 事务由查询和(或)更新语句的序列组成
- 事务开始
- 一个sql执行,隐含开始了一个事务
- 结束事务
commit work
:完成所有事务,提交事务rollback work
:不能成功完成所有任务,回滚事物
- 注:commit和rollback其后的sql属于新的事务
不能回退 select 语句,回退 select 语句也没意义;也不能回退 create 和 drop 语句
MySQL 默认是隐式提交,每执行⼀条语句就把这条语句当成⼀个事务然后进行提交。当出现 start transaction
语句时,会关闭隐式提交;当 commit 或 rollback 语句执行后,事务会自动关闭,重新恢复隐式提交
通过 set autocommit = 0
可以取消自动提交,直到 set autocommit = 1
才会提交
begin atomic ... end
start transaction
——用于标记事务的起始点。
savepoint
——用于创建保留点。
rollback to
——用于回滚到指定的保留点;如果没有设置保留点,则回退到start transaction语句处。
commit
——提交事务
指数据的正确性和相容性
主码
约束not null
unique
check (<谓词>)
alter table 关系名 add/drop/change/modify
约束条件not null
禁止对该属性插入空值,是域约束的一种unique (属性1,属性2,...,属性n)
约束在关系中没有两个元组能在所有列出的属性上取值相同check( P )
子句指定一个谓词P,关系中的每个元组都必须满足谓词P
check子句可以单独出现,也可以作为属性声明的一部分出现(对单个属性值的约束check与该属性一起列出,更复杂的check子句则在create table语句的末尾单独列出)
check语句模拟枚举类型示例
create table section
(course_id varchar(8),sec_id varchar(8),semester varchar(6),…,
primary key (course_id, sec_id, semester, year),
check(semester in ('Fall','Winter','Spring','summer')))
用create domain定义域时,可以出现check
create domain AGE_domain smallint check((value >= 15) and value <= 25))
主码约束定义形式
主码子句:primary key (属性名)
主码短语:属性名 数据类型(域值) primary key
主码值不允许空,也不允许出现重复
通过主码来唯一标识,主码非空
foreign key (外码) references 关系名(主码)
references子句作为属性定义的一部分,声明外码
foreign key子句可以指明:如果被参照关系上的删除或更新动作违反了约束,系统必须采取一些步骤通过修改参照关系中的元组来恢复完整性,而不是简单拒绝
约束赋名:统一化完整性约束
constraint 约束名 <约束条件>
create table constraint 约束名 <约束条件>
alter table 关系名 drop constraint 约束名
alter table 关系名 add constraint 约束名 <约束条件>
create domain constraint 约束名 <约束条件>
alter domain 关系名 drop constraint 约束名
alter domain 关系名 add constraint 约束名 <约束条件>
事务的中某一步骤会暂时违反完整性约束,但是后面的某一步会消除这个违反
默认约束是立即检查,但约束声明中加入initially deferred
子句,可以延迟约束检查,并在事务结束时检查。
一个约束可以被指定为deferrable可延迟的。对于可延迟的约束,执行 set constraints constrain-list deferred 命令作为事务一部分,延迟到事务结束时检查。
许多数据库实现不支持延迟约束
复杂check条件,check子句中使用子查询
全局约束涉及多个属性间的或多个关系间的联系
示例
create table SC
(Sno char(4),
Cno char(4),
GRADE smallint,
primary key (Sno, Cno),
check (Sno in (select Sno from S)),
check (Cno in (select Cno from C)))
断言是一个谓词,表达数据库总应该满足的条件
格式
建立断言:create assertion 断言名 check 条件
撤销断言:drop assertion 断言名
特点
一旦定义了断言,系统验证其有效性,并且对每个可能违反该断言的更新操作都进行检查
域约束和参照完整性约束就是断言的特殊形式
示例1:只允许女同学选修张老师课程
create assertion ASSE2
check (not exists (select *
from SC
where Cno in (select Cno
from C
where TEACHER = ‘张’) and Sno in (select Sno
from S
where SEX = ‘M’)))
示例2:每门课最多50名男同学选修
create assertion ASSE1
check (50 >= all (select count(SC.Sno)
from S, SC
where S.Sno = SC.Sno and SEX = ‘M’
group by Cno)))
date
:日历日期,包括年(4位)、月、日
time
:一天中的时间,包括时、分、秒
可用time(p)
表示秒的小数点后位数(默认0)
指定time with timezone
,可以加时区信息
timestamp
: date与time的组合可用
timestamp(p)
表示秒的小数点后位数(默认6)
指定with timezone
,可以加时区信息
例: date ‘2001-04-25’ time ‘09:30:00’ timestamp ‘2001-04-25 09:29:01.45’
字符串与日期、时间类型转换
cast string to t
从日期、时间中提取单独的域
extract (field from d)
field 可以是year,month,day,hour,minute,second ;
时区中的信息用timezone_hour,timezone_minute等
获取当前日期、时间函数
返回当前日期:current_date
返回当前时间(带时区):current_time
返回当前本地时间(不带时区):local_time
时间戳:current_timestamp,locate_timestamp
运算结果:interval类型
cast (e as t)
将表达式e的数据类型转换为类型t
示例
select name,age,country,
cast(born as date) as born
from table
where born >= "2000-01-01"
/*等价于where cast(born as date) >= 2000-01-01*/
处理空值的函数,可以用coalesce选择在查询结果中输出空值的方式
该函数接收任意数量的参数,且所有参数必须同类型(如果不同类型需要使用decode),返回第一个非空参数
示例:显示教师的ID和工资,并将空工资显示为0
select ID,coalesce(salary,0) as salary
from instructor
解码(decode)允许其属性参数不必是同一类型,在Oracle中可用
格式
decode(value,match-1,replacement-1,match-2,replacement-2...default-replacement)
示例:显示教师的ID和工资,并将空工资显示为’N/A’
select ID,decode(salary,null,'N/A',salary) as salary
from instuctor
为关系中属性指定缺省值(默认值),当一个元组被插入关系中时,如果没有给出其全部或部分属性的值 ,那么该元组在此属性上的取值为default规定的默认值,而非null
示例:tot_cred属性默认值为0
create table student
(ID varchar(5),
name varchar(20) not null,
dept_name varchar(20) ,
tot_cred numeric(3,0) default 0,
primary key (ID))
SQL提供字符数据的大对象数据类型clob和二进制数据的大对象数据类型blob
bookview clob (10KB)
image blob (10MB)
movie blob (2GB)
独特类型
格式:create type 新类型对应的名称 as 新类型的具体内容 final
示例:Dollars和Pounds为新的数据类型
create type Dollars as numeric(12,2) final;
create type Pounds as numeric(12,2) final;
类型和域的差异
在域上可以声明诸如非空那样的约束,也可以为域类型的变量定义缺省值,然而在用户自定义类型上不能声明约束或缺省值。用户自定义类型不仅被设计用来指定属性类型,而且还被用在不能施加约束的地方以对SQL进行过程扩展
域并不是强类型的。其结果是,一个域类型的值可以被赋值给另一个域类型(cast),只要它们的基本类型是相容的
结构化数据类型
create table temp_instructor like instructor
示例:
create table t1 as (select *
from instructor
where dept_name = 'Music')
with data
/*很多数据库实现在省略with data子句时,默认加载数据*/
当代数据库系统提供三层结构的关系命名机制:目录catalog 、模式schema、关系/视图对象
用户连接到数据库(验证身份)后,有一个默认的目录和模式,默认目录和默认模式可以省略
每个数据库连接会建立SQL环境:包括目录、模式和用户授权标识
大多数数据库系统,环境随用户账户创建而自动创建,此时模式名被置为用户账户名
用create schema和drop schema语句创建、删除模式
通过索引可以更加快速高效地查询关系中具有该属性指定值的元组数据
用户无法看到索引,它们只能被用来加速查询
create index 索引名 on 关系名(属性名)
创建唯⼀索引
唯⼀索引(使用unique关键字)表明此索引的每⼀个索引值只对应唯⼀的数据记录
create unique index 索引名 on 关系名(属性名)
alter table 关系名 drop index 索引名
- 注意 : 更新⼀个包含索引的表需要比更新⼀个没有索引的表花费更多的时间,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引
授权前首先要确定一个角色集,可以给角色授予权限(角色是用户的虚拟体现)
创建角色: create role 角色名
给角色授权:grant 权限列表 on 关系名/视图名 to 用户/角色名
角色可以授予用户或其他角色
示例:角色链中的权限继承
create role dean;
grant instructor to dean;
grant dean to Satoshi;
角色的权限包括
直接授予该用户/角色的所有权限
授予该用户/角色所拥有的角色的所有权限
格式
grant <权限列表> on <关系名/视图名>
to <用户/角色列表/public>
<with grant option>
权限列表包括:select, update, insert, delete, index, alter, drop, resource以及它们的总和all,其中对select、update、insert可指定(属性列表)
with grant option
表示获得权限的用户可以把权限再授予其它用户
如果在用来定义视图的关系上没有update 权限,则在视图上也没有update权限
模式的基本授权:模式的拥有者才拥有对模式的修改权限
如:增、删关系,增、删关系的属性,以及增、删索引。
references权限,允许用户在创建关系时声明外码,此权限可以授予到指定属性上(因为外码会限制其他用户对被参照关系将来的行为,所以需要授权)
示例:
grant references (dept_name) on department
to Mariano
代码解读:允许Mariano创建关系能参照department的码dept_name
格式
revoke 表级权限 on <关系名/视图名>
from <用户/角色列表/public,用户/角色列表,用户/角色列表,...>
收回权限时,若该用户已将权限授予其它用户,则也一并收回
restrict
防止级联收回如果存在任何级联收回,返回错误,不执行任何收权动作
示例
revoke
select on department
from Amit
restrict
即只回收授权选项,不真正回收权限
示例
revoke
grant option for
select on department
from Amit
(1)设置会话的当前角色为已定义角色:set role role_name
(2)由当前角色授权(角色不为空),授权语句后加:grant by current_role
grant 和 revoke 可在几个层次上控制访问权限:
整个服务器,使⽤ grant all
和 remove all
整个数据库,使⽤ on database.*
特定的表,使⽤ on database.table
特定的列
特定的存储过程。
新创建的账户没有任何权限。
账户⽤ username@host
的形式定义,username@%
使⽤的是默认主机名。
MySQL 的账户信息保存在 mysql 这个数据库中 USE mysql ; select user from user
create user 用户名 identified by '密码'
update user SET user='newuser' where user='myuser' flush privileges
drop user 用户名
show grants for 用户名
revoke 权限列表 on 关系名/视图名 from 用户/角色列表
set password for 用户名 = '密码名'