关系型数据库

选项
Oracle:甲骨文公司收费
Microsoft SQL Server:微软公司收费
MySQL 与 PostgreSQL的对比
1、开源许可
MySQL是GPL许可,使用者对代码所做的修改也必须开源
PostgreSQL是BSD许可,允许使用者对代码所做的修改进行保密
2、开发背景
MySQL的背后是一个成熟的商业公司Sun公司
PostgreSQL的背后是一个庞大的志愿开发组
3、并发模式
MySQL使用的是线程模式,线程模式对资源消耗比较少,支持更多连接
PostgreSQL使用的是进程模式,进程模式对多CPU利用率比较高

关系模型的完整性约束:实体完整性、参照完整性、用户定义的完整性
完整性:数据正确性(对象自身符合现实)和相容性(对象之间符合逻辑)
实体完整性:主键唯一且不能为空
参照完整性:外键要么为空,要么是另一张表存在的主键值
用户定义的完整性:例如非主键的非空性和唯一性

集合运算:并 U,交 n ,差 -,笛卡尔积 X
笛卡尔积:A表的行 和 B表的行,两两组合 成目标表

关系运算:选择(行过滤)、投影(列过滤)、连接(等值连接、自然连接、外连接)、除
等值连接:在A表和B表的笛卡尔积中,过滤出 A表指定属性 = B表指定属性 的行,组成目标表
自然连接:在A表和B表的笛卡尔积中,过滤出 A表和B表所有的同名属性都相等 的行,组成T表,T表去除重复属性,得到目标表
悬浮组:等值连接中,AB两表中被舍弃的行
外连接:AB表的等值连接T + AB表的悬浮组D,组成外链接。D加入T时,没有的属性,值取null
左外连接:外连接中,只保留A表悬浮组
右外连接:外连接中,只保留B表悬浮组
除:从A表中提取A表有而B表没有的列,去重作为T表;T表中的一些行与B表的笛卡尔积为A的子集,这些行组成目标表

SQL(Structured Query Language):结构化查询语言
数据字典:保存关于表、视图、索引、用户的设置
SQL操作对象:模式(表的命名空间)、表、视图、索引、断言、触发器

create schema wang authorization wang  -- 创建模式,指定授权用户
drop schema wang cascade  -- 级联删除模式,另有 restrict,只允许删除空模式
create table wang.Student             -- 创建表,指定模式
    (Sno char(9) primary key,           -- 主键
    Sname char(20) unique,             -- 唯一性约束
    Spno char(4) not null,                   -- 非空约束
    Sgrade int check(Sgrade>0),        -- 条件约束,可以是where字句能用到的所有条件
    foreign key (Spno) references Course(Cno))     -- 外键 

alter table student                                     -- 修改表
    add column Sname char(20) unique      -- 添加新列
    add unique(Sname),              -- 添加完整性约束
    alter column Ssex int             -- 修改列数据类型
    drop column Ssex cascade  -- 级联删除列,另有restrict,只允许删除未被其他对象(表,视图)引用的列

drop table student cascade  -- 级联删除表,另有restrict,只允许删除未被其他对象(表,视图)引用的表

数据类型:定长字符串char(n),不定长字符串varchar(n),2字节整数smallint,4字节整数int,8字节整数bigint,布尔值boolean,日期date,时间time,时间戳timestamp,精度为n的浮点数float(n)

搜索路径
创建表时,若不指定模式,则默认采用搜索路径里设置的模式
查看:show search_path
设置 set search_path to 模式1,模式2

索引
加快查询、分组、排序、连接速度,但需要额外占用存储空间,增删改表时需要额外时间更新索引

create index Sno on SC(Sno ASC, Cno DESC)  -- 给SC表创建索引Sno,索引属性为Sno和Cno。ASC为升序,DESC为降序
create unique index Sno on SC(Sno)  -- 唯一索引,性能更高,插入值需要唯一,但允许为空
alter index Sno rename to Cno  -- 重命名索引
drop index Sno     -- 删除索引

索引设计原则
1、一个频繁更新的表,索引数 和 索引列数 尽可能少
2、行数少表、重复值多的列 不要建索引
3、在unique列上建立unique索引
4、一个频繁排序和分组的表,对应列建立索引

数据查询

/**    列查询     **/
select distinct Sno,lower(Sname),2018-Sage birth   -- 选择列,可以进行表达式运算,可以取别名,distinct表示去重
    from Student                                                             -- 来源表
    where Sno=1                                                            -- 查询条件
    order by Sage,(case when Sage=null then 0 else 100 end) desc    -- 结果排序,这里实现了三元表达式运算,desc表示降序
/**    统计查询     **/
select count(distinct Sno)                                         --distinct表示去重    
    from Student
    order by ( case when store_id is null then 0 when store_id=25 then 1 else 2 end)  -- 自定义排序
/**          组查询           **/
select Cno,Cname, avg(Sno)          -- 这里得到一个组列表,Cno是一个组共有的,Cname不是一个组公有的,会得到一个次序在前的值,avg是对一个组进行统计
    from Student
    group by Cno
    having count(*) > 3                                              -- 组过滤

查询条件
比较:=、>、< 等
范围:between and,not between and
集合:in,not in
字符匹配:like,not like
空值:is null,is not null
多重条件:and,or,not

聚集函数
count(*)、count(distinct 列) 、count(列),max(列)、min(列)、sum(列)、avg(列)、group_concat(列)

连接查询

/**          等值连接           **/
select student.*,sc.*                         -- 取所有列
    from student,sc               
    where student.Sno = sc.Sno           -- 等值连接
/**          非等值连接           **/
select student.*,sc.*  
    from student,(select ... from ...) as sc    -- sc为派生表           
    where student.Sno > sc.Sno         -- 在笛卡尔积中过滤出符合条件的行,组成目标表
/**          自然连接           **/
select student.Sno,Sname,Ssex    -- 指定具体列,去除重复。两表中不重复的列,可以不指明表名
    from student,sc               
    where student.Sno = sc.Sno
/**          自连接           **/
select first.Sno,second.Spno          -- 指定具体列,去除重复。两表中不重复的列,可以不指明表名
    from student first,student second   -- 给表取别名,用于区分          
    where first.Sno = second.Spno
/**          外连接           **/
select student.Sno,Sname,Ssex 
    from student outer join sc on(student.Sno = sc.Sno) 
/**          左外连接           **/
select student.Sno,Sname,Ssex 
    from student left outer join sc on(student.Sno = sc.Sno) 
/**          右外连接           **/
select student.Sno,Sname,Ssex 
    from student right outer join sc on(student.Sno = sc.Sno) 
/**          多表连接           **/
select student.Sno,Sname,Ssex 
    from student,sc,course

嵌套查询

/**         不相关嵌套查询           **/
-- 先处理子查询,再处理父查询
select Sname
    from student
    where Sdept in                   -- 子查询的结果为单列集合,那么谓词为 in、>any、>all、=any、!=all等,some与any同义
        (select Sdept from ...);     -- 内层查询(子查询)
 
/**         相关嵌套查询           **/
-- 1、忽略子查询,先得到一个结果T;2、遍历T,计算出子查询,过滤出符合条件的行
select Sname
    from student x
    where Sno >=                    -- 子查询的结果为单列单行,那么谓词为>、<、=等
        (select avg(grade) from student y where y.sno = x.sno);  -- 子查询用到父查询中的表

select Sname
    from student x
    where exists                  -- 子查询的结果多列集合,那么谓词为exists、not exists
        (select * from student y where y.sno = x.sno) 

select student.*,sc.*
    from student,(select * from student)  sc   --子查询在from子句,作为一个表
    where student.Sno = sc.Sno

SELECT * from 
(SELECT *, MAX(age) AS max_age FROM student GROUP BY gender)  student  -- 子查询结果表的别名
ORDER BY max_age  -- 组函数不能被order by引用,可以改成这样的嵌套查询

select age+(SELECT MAX(score) AS maxScore FROM score) from student   -- 子查询在select子句

集合查询

select * from student
    union                                      -- 并集,另外交集intersect,差集except
    select * from student;

数据更新

insert                                  -- 插入行
    into student(Sno,Sname)   -- 未指定值的列,默认为null
    values('2000','hogen'), ('300','alina');  

insert
    into student(Sno,Sname) 
    子查询;                               -- 以子查询为输入

update student                 -- 更新行
    set Sage=Sage+2
    where Sno='3333'             -- 可以是子查询

delete                               -- 删除行
    from student
    where Sno='33333'           -- 可以是子查询

视图
一个或几个表导出的虚表,数据库只保存视图的定义,不保存视图对应的数据
视图消解:查询视图时,结合用户查询和视图定义,最终形成对表的查询
视图的作用:简化SQL语句,隐匿原表数据;不能提升查询性能

/**     单表视图     **/
create view  student_view(Sno,Sname,Sbirth)  -- 保留主键的视图称为行列子集视图
    as
    select Sno,Sname,2018-Sage       -- Sbirth为派生属性(虚拟属性,表达式属性),表只保存最简属性,视图提供派生属性
    where Sage > 30
    with check option                  -- 视图消解时,遇到不符合 where 字句的操作,拒绝执行

/**     多表视图      **/
create view  student_view(Sno,Sname)
多表查询

drop view student_view cascade  -- 级联删除

权限

/**  授权  **/
grant update(Sno),select      -- 操作另有insert、delete、references、all privileges,可以指定列也可以不指定
    on table student                    
    to user1                               -- 另有public,表示所有用户
    with grant option;                 -- 允许转授权(传播权限)

/**  回收权限  **/
revoke select
    on table student
    from user1;

/**  创建用户,指定系统角色  **/
create user hogen with dba;   -- 没有指定系统角色的话,默认为connect

/**  自定义角色   **/
create role role1;                   -- 创建角色

grant select
    on table student                    -- 另有 view
    to role1;                                 --  给角色授权

grant role1                
    to role2,hogen                      --  把角色的权限授予用户或其他角色
    with admin option;                -- 允许转授权给其他角色

revoke select
    on table student
    from role1;                           -- 回收角色权限

系统角色
dba:超级管理员,拥有包括创建用户、创建模式的所有权限
resource:有创建表、操作表的权限
connect:只有操作表的权限

断言

create assertion ass                          -- 创建断言
    check (60>=(                                 -- 拒绝插入第61条,即拒绝将导致断言为否的操作
        select count(*) from Student) 
    );

drop assertion ass;                           -- 删除断言

触发器

create trigger trigger1                      -- 触发器的命名空间也是模式
    after update on table1                 -- 触发器只能定义在表上。after 另有 before,update 另有delete、insert
    referencing
        oldrow as oldStudent              -- 行数据别名
        newrow as newStudent
    for each row                                   -- 行级触发器,另有语句级触发器 for each statement,执行一条语句只触发一次
    when(newStudent.Sage > oldStudent.Sage)    -- 触发条件
        begin
            insert into ... ;                                                -- 触发动作
        end

drop trigger trigger1 on table1;           -- 删除触发器

关系规范化
码:由一个或多个属性组成
超码:能唯一确定一行的码
候选码:最小范围的超码,即只保留超码中的必要属性
主码:从多个候选码中选一个为主码
主属性:任一候选码包含的属性
非主属性:非码属性,即主属性以外的属性
外码:另一个关系的候选码
完全函数依赖:非主属性 完全函数依赖于 候选码,即确定的候选码 能确定 所有非主属性
部分函数依赖:非主属性 部分函数依赖于 超码,即部分确定的候选码 就能确定 所有非主属性
第一范式 1NF:一个属性不可拆分,多个属性之间不能重复
第二范式 2NF:任一非主属性完全函数依赖于任一候选码
第三范式 3NF:任一非主属性只函数依赖于候选码
第三范式修正BCNF:任一主属性 完全函数依赖且只函数依赖于 其他候选码

E-R图(Entity Relationship Diagram,实体-联系图)
矩形框:实体
椭圆框:属性
菱形框:联系,与实体连接,标明(1:1,1:m,n:m)

事务
ACID特性
原子性(Atomicity):事务不可拆分
一致性(Consistency):事务执行前后,数据库保持一致性(正确性)状态
隔离性(Isolation):事务与事务之间互相隔离
持续性(Durability):永久性,事务一旦提交,永久改变

begin transaction;        -- 开始定义事务
sql语句
commit;                        -- 提交事务
rollback;                       -- 某种情况下,显式撤销事务

封锁
排他锁(X锁):写锁,独占锁,独享锁,互斥锁
共享锁(S锁):读锁
一级封锁协议:事务在修改数据之前加X锁,事务结束时释放锁
二级封锁协议:在一级封锁协议的基础上,事务在读取数据之前加S锁,读取结束时释放锁
三级封锁协议:在一级封锁协议的基础上,事务在读取数据之前加S锁,事务结束时释放锁
活锁:在没有事务排队机制的系统上,一个事务请求加锁,可能长时间被插队,导致这个事务没法完成
死锁:两个事务互相依赖于被对方加锁的数据,导致两个事务都无法完成
预防死锁
一次封锁法:一次性把所需数据全部加锁,用完释放;缺点:降低了系统并发能力
顺序封锁法:预先规定一个加锁顺序,所有事务都遵循该顺序;缺点:顺序难以维护,不能处理动态选择的封锁对象
死锁诊断
超时判定:事务等待超过时限,判定事务遇到死锁;缺点:容易误判
等待图分析:数据库管理系统能获取到事务等待图,判断有没有循环等待
死锁解除
数据库管理系统撤销一个事务,释放其持有的锁

事务加锁规则
可串行性:给定一个初始状态;1、多个事务依次启动,并行执行;2、同样的几个事务依次串行执行;如果12两种方式的结果无差异,则称这几个事务可串行化(具有可串行性)
两段锁协议(2PL):第一阶段(扩展阶段),读写数据前加锁,不解锁;第二阶段(收缩阶段),只解锁,不加锁
所有事务都遵循两段锁协议 是 这些事务可串行化 的充分条件

显式封锁:本对象被加锁
隐式封锁:本对象的父对象被加锁
封锁冲突:一个对象只能有一个显式锁 或者 一个隐式锁,因此给对象加锁时系统需要检查它是否已经有显式锁、隐式锁,还要检查子对象有没有显式锁
意向锁:给一个对象加锁时,同时给他的所有父对象加意向锁,使得其他事物给父对象加锁时,不用向下检查
意向共享锁:IS锁
意向排他锁:IX锁

数据库优化
1、建立合适的索引
2、sql 语句优化
3、创建冗余字段,用来存储(查询、排序、分组用到的)需要大量计算得来的数值,用触发器更新该字段
4、去除多余字段,多余关联,杜绝一个接口服务多个场景导致的字段多余
5、利用elastic search 实现模糊搜索

SQL案例

1、每组取 最小计算值 所在的那条记录
难点:计算值可以被order by,但是group by时 所取的行,不是order by的第一行

select o.*, abs(score - 50) as minscore from student o,  # abs(score - 50) 即为本例针对的计算值
(SELECT name, min(abs(score - 50)) as minscore FROM student group by name) t  # 找到name和最小计算值的对应关系,作为临时表
where o.name=t.name and abs(score - 50)=t.minscore  # 等值连接

2、不存在才插入

INSERT INTO student(name) SELECT '张三' FROM DUAL    -- DUAL为mysql的一个辅助表
WHERE NOT EXISTS(SELECT id FROM student WHERE name='张三')  -- 此语句用于防止重复插入

3、更新 或 插入

REPLACE INTO student(id, num, name) VALUES(3, 5, '张山')  -- 主建或 唯一键 存在则更新,不存在则插入
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容