數據庫 - 實現數據持久化以及數據管理
- 持久化 將數據保存到(在掉電情況下)能夠長久保存數據的存儲介質中
數據庫的分類
關系型數據庫(SQL) 、非關系型數據庫(NoSQL)
關系型數據庫概述
- 關系型數據庫發展史: 網狀數據庫、層次數據庫、關系數據庫
1970年,IBM的研究員E.F.Codd在Communication of the ACM上發表了名為A Relational Model of Data for Large Shared Data Banks的論文,提出了關系模型的概念,奠定了關系模型的理論基礎。后來Codd又陸續發表多篇文章,論述了范式理論和衡量關系系統的12條標準,用數學理論奠定了關系數據庫的基礎。
理論基礎:關系代數和集合論
-
關系型數據庫產品:
- Oracle (甲骨文公司) 目前世界上使用最為廣泛的數據庫管理系統,作為一個通用的數據庫系統,它具有完整的數據管理功能;作為一個關系數據庫,它是一個完備關系的產品;作為分布式數據庫,它實現了分布式處理的功能。在Oracle最新的12c版本中,還引入了多承租方架構,使用該架構可輕松部署和管理數據庫云。
- DB2 (IBM) 主要運行于Unix(包括IBM自家的AIX)、Linux、以及Windows服務器版等系統的關系數據庫產品。DB2歷史悠久且被認為是最早使用SQL的數據庫產品,它擁有較為強大的商業智能功能。
- SQLServer (Microsoft)最初適用于中小企業的數據管理,但是近年來它的應用范圍有所擴展,部分大企業甚至是跨國公司也開始基于它來構建自己的數據管理系統。
- MySQL MySQL是開放源代碼的,任何人都可以在GPL(General Public License)的許可下下載并根據個性化的需要對其進行修改。MySQL因為其速度、可靠性和適應性而備受關注。
- Sybase
- PostgreSQL 在BSD許可證下發行的開發源代碼的關系數據庫產品。
-
具體表象:用二維表來保存數據
- 行(記錄)
- 列(字段)
- 主鍵列:能夠唯一標識一條記錄的列,例如:學生學號
-
編程語言:SQL - 結構化查詢語言
- DDL 數據定義語言 create / drop / alter
- DML 數據操作語言 insert / delete / update / select
- DCL 數據控制語言 grant / revoke
ER圖(實體關系圖/概念模型圖)
矩形框:實體
橢圓框:實體的屬性
菱形框:實體之間的關系
關系的重數:一對一/一對多/多對多
畫圖工具:PowerDesigner
linux環境下啟動Mariadb
啟動和查看程序進程
啟動 ——> 查看是否有進程(4個方法)
方法4. systemctl status mariadb
image.png
- 查看數據庫版本
image.png
連接navicat可視化界面
image.png
-
==第一步==:連接
image.png
密碼是:該用戶登錄的密碼
點擊連接測試 ——> 成功后點擊連接
-
==第二步==:授予root所有權限
image.png
SQL結構化查詢語言(Mysql)
注意:
- 給數據庫和表命名時盡量使用小寫;
- 作為篩選條件的字符串是否區分大小,看校對規則(collate utf8_general_ci ci——> case insensitive)
- 數據庫中的對象通常會用前綴加以區分
數據庫增刪以及表格增刪改
-- 如果存在名為school的數據庫就刪除它
drop database if exists school;
-- 創建名為school的數據庫并設置默認的字符集和排序方式
create database school default charset utf8 collate utf8_bin_ci;
-- 切換到school數據庫上下文環境
use school;
-- 創建學院表
create table tb_college
(
collid int not null auto_increment comment '編號',
collname varchar(50) not null comment '名稱',
collmaster varchar(20) not null comment '院長',
collweb varchar(511) default '' comment '網站',
primary key (collid)
);
-- 創建學生表
create table tb_student
(
stuid int not null comment '學號',
stuname varchar(20) not null comment '姓名',
stusex bit default 1 comment '性別',
stubirth date not null comment '出生日期',
stuaddr varchar(255) default '' comment '籍貫',
collid int not null comment '所屬學院',
primary key (stuid),
foreign key (collid) references tb_college (collid)
);
-- alter table tb_student add constraint fk_student_collid foreign key (collid) references tb_college (collid);
-- 創建教師表
create table tb_teacher
(
teaid int not null comment '工號',
teaname varchar(20) not null comment '姓名',
teatitle varchar(10) default '助教' comment '職稱',
collid int not null comment '所屬學院',
primary key (teaid),
foreign key (collid) references tb_college (collid)
);
-- 創建課程表
create table tb_course
(
couid int not null comment '編號',
couname varchar(50) not null comment '名稱',
coucredit int not null comment '學分',
teaid int not null comment '授課老師',
primary key (couid),
foreign key (teaid) references tb_teacher (teaid)
);
-- 創建選課記錄表
create table tb_score
(
scid int auto_increment comment '選課記錄編號',
stuid int not null comment '選課學生',
couid int not null comment '所選課程',
scdate datetime comment '選課時間日期',
scmark decimal(4,1) comment '考試成績',
primary key (scid),
foreign key (stuid) references tb_student (stuid),
foreign key (couid) references tb_course (couid)
);
-- 添加唯一性約束(一個學生選某個課程只能選一次)
alter table tb_score add constraint uni_score_stuid_couid unique (stuid, couid);
-- 插入學院數據
insert into tb_college (collname, collmaster, collweb) values
('計算機學院', '左冷禪', 'http://www.abc.com'),
('外國語學院', '岳不群', 'http://www.xyz.com'),
('經濟管理學院', '風清揚', 'http://www.foo.com');
-- 插入學生數據
insert into tb_student (stuid, stuname, stusex, stubirth, stuaddr, collid) values
(1001, '楊逍', 1, '1990-3-4', '四川成都', 1),
(1002, '任我行', 1, '1992-2-2', '湖南長沙', 1),
(1033, '王語嫣', 0, '1989-12-3', '四川成都', 1),
(1572, '岳不群', 1, '1993-7-19', '陜西咸陽', 1),
(1378, '紀嫣然', 0, '1995-8-12', '四川綿陽', 1),
(1954, '林平之', 1, '1994-9-20', '福建莆田', 1),
(2035, '東方不敗', 1, '1988-6-30', null, 2),
(3011, '林震南', 1, '1985-12-12', '福建莆田', 3),
(3755, '項少龍', 1, '1993-1-25', null, 3),
(3923, '楊不悔', 0, '1985-4-17', '四川成都', 3);
-- 插入老師數據
insert into tb_teacher (teaid, teaname, teatitle, collid) values
(1122, '張三豐', '教授', 1),
(1133, '宋遠橋', '副教授', 1),
(1144, '楊逍', '副教授', 1),
(2255, '范遙', '副教授', 2),
(3366, '韋一笑', '講師', 3);
-- 插入課程數據
insert into tb_course (couid, couname, coucredit, teaid) values
(1111, 'Python程序設計', 3, 1122),
(2222, 'Web前端開發', 2, 1122),
(3333, '操作系統', 4, 1122),
(4444, '計算機網絡', 2, 1133),
(5555, '編譯原理', 4, 1144),
(6666, '算法和數據結構', 3, 1144),
(7777, '經貿法語', 3, 2255),
(8888, '成本會計', 2, 3366),
(9999, '審計學', 3, 3366);
-- 插入選課數據
insert into tb_score (stuid, couid, scdate, scmark) values
(1001, 1111, '2017-09-01', 95),
(1001, 2222, '2017-09-01', 87.5),
(1001, 3333, '2017-09-01', 100),
(1001, 4444, '2018-09-03', null),
(1001, 6666, '2017-09-02', 100),
(1002, 1111, '2017-09-03', 65),
(1002, 5555, '2017-09-01', 42),
(1033, 1111, '2017-09-03', 92.5),
(1033, 4444, '2017-09-01', 78),
(1033, 5555, '2017-09-01', 82.5),
(1572, 1111, '2017-09-02', 78),
(1378, 1111, '2017-09-05', 82),
(1378, 7777, '2017-09-02', 65.5),
(2035, 7777, '2018-09-03', 88),
(2035, 9999, curdate(), null),
(3755, 1111, date(now()), null),
(3755, 8888, date(now()), null),
(3755, 9999, '2017-09-01', 92);
-- 添加主鍵約束(如果創建表時沒有添加)
alter table tb_teacher add constraint pk_teacher_teaid primary key(tea_id);
-- 添加外鍵約束(如果創建表時沒有添加)
alter table tb_teacher add constraint fk_teacher_deptid foreign key(dept_id) references tb_department(dept_id);
如果外鍵編號不存在,會報錯
image.png
表格查詢語句
- 查詢所有學生信息
select * from tb_student;
- 查詢所有課程名稱及學分(投影和別名)
select couname as 課程名稱, coucredit as 學分 from tb_course;
select stuname as 姓名, case stusex when 1 then '男' else '女' end as '性別'
from tb_student;
select stuname as 姓名, if(stusex, '男', '女') as 性別
from tb_student; -- 僅適用于mysql
- 查詢所有女學生的姓名和出生日期(篩選)
select stuname as 學生姓名 , stubirth as 出生日期 from tb_student
where stusex = 0;
- 查詢所有80后學生的姓名、性別和出生日期(篩選)
select stuname, stusex, stubirth from tb_student
where stubirth between '1980-1-1' and '1989-12-31';
select stuname, stusex, stubirth from tb_student
where stubirth>'1980-1-1' and stubirth<'1989-12-31';
- 查詢姓”楊“的學生姓名和性別(模糊)
select stuname, stusex from tb_student
where stuname like '林%'
- 查詢姓”楊“名字兩個字的學生姓名和性別(模糊)
select stuname, stusex from tb_student
where stuname like '楊_'
- 查詢姓”楊“名字三個字的學生姓名和性別(模糊)
select stuname,stusex from tb_student
where stuname like '楊__'
- 查詢名字中有”不“字或“嫣”字的學生的姓名(模糊)
select stuname from tb_student
where stuname like '%不%' or '%嫣%';
- 查詢沒有錄入家庭住址的學生姓名(空值)
select stuname from tb_student where stuaddr is null;
- 查詢錄入了家庭住址的學生姓名(空值)
select stuname from tb_student where stuaddr is not null;
- 查詢學生選課的所有日期(去重)
select distinct scdate from tb_score;
- 查詢學生的家庭住址(去重)
select distinct stuaddr from tb_student;
- 查詢男學生的姓名和生日按年齡從大到小排列(排序)
select stuname, stubirth from tb_student
where stusex = 1
order by stubirth asc;
select stuname, stubirth from tb_student
where stusex = 1
order by stubirth desc;
select stuname, year(now())-year(stubirth) as 年齡 from tb_student
where stusex = 1
order by 年齡 desc, stuid;
- 查詢年齡最大的學生的出生日期(聚合函數)
select min(stubirth) from tb_student;
- 查詢年齡最小的學生的出生日期(聚合函數)
select max(stubirth) from tb_student;
- 查詢男女學生的人數(分組和聚合函數)
select stusex,count(*) from tb_student
group by stusex;
select stusex, min(stubirth) from tb_student
group by stusex;
- 查詢課程編號為1111的課程的平均成績(篩選和聚合函數)
select avg(scmark) from tb_score
where couid = 1111;
- 查詢學號為1001的學生所有課程的平均分(篩選和聚合函數)
select avg(scmark) from tb_score
where stuid = 1001;
- 查詢每個學生的學號和平均成績(分組和聚合函數)
select stuid, avg(scmark) from tb_score
group by stuid;
- 查詢平均成績大于等于90分的學生的學號和平均成績
select stuid, avg(scmark) as 平均分 from tb_score
group by stuid
having 平均分>90;
- 查詢年齡最大的學生的姓名(子查詢)
select stuname, stubirth from tb_student;
select stuname, min(stubirth) from tb_student;
select stuname from tb_student
where stubirth = (select min(stubirth) from tb_student);
- 查詢年齡最大的學生姓名和年齡(子查詢+運算)
select stuname, year(now()) - year(stubirth) as 年齡 from tb_student
where stubirth = (select min(stubirth) from tb_student);
- 查詢選了兩門以上的課程的學生姓名(子查詢/分組條件/集合運算)
select stuname from tb_student
where stuid in (
select stuid from tb_score
group by stuid
having count(stuid)>2
);
- 查詢學生姓名、課程名稱以及成績(連接查詢)
select stuname, couname, scmark
from tb_student t1, tb_course t2, tb_score t3
where t1.stuid=t3.stuid and t2.couid=t3.couid;
select stuname, couname, scmark
from tb_student t1 inner join tb_course t2 inner join tb_score t3
on t1.stuid=t3.stuid and t2.couid=t3.couid;
- 查詢選課學生的姓名和平均成績(子查詢和連接查詢)
select stuname, 平均成績 from tb_student t1,(select stuid,avg(scmark) as 平均成績 from tb_score
group by stuid) t2
where t1.stuid = t2.stuid;
select stuname, 平均成績 from tb_student t1 inner join (select stuid,avg(scmark) as 平均成績 from tb_score
group by stuid) t2
on t1.stuid = t2.stuid;
- 查詢每個學生的姓名和選課數量(左外連接和子查詢)
select stuname, 選課數量
from tb_student t1 inner join (select stuid,count(couid) as 選課數量 from tb_score
group by stuid) t2
on t1.stuid=t2.stuid
order by 選課數量 desc
limit 5 offset 2; -- 跳過2條查5條
select stuname, ifnull(選課數量,0)
from tb_student t1 left outer join (select stuid,count(couid) as 選課數量 from tb_score
group by stuid) t2
on t1.stuid=t2.stuid
order by 選課數量 desc
limit 1,1; -- 跳過第一查第二條
DCL 授予權限(grant to)和召回權限(revoke from)
create user 'hellokitty'@'%' identified by '123123'; -- '用戶名'@'IP地址'
grant all privileges on hrs.* to 'hellokitty'@'%'; -- 把hrs數庫的所有權限給新建的用戶
-- 召回新用戶的添加、刪除、更新的權限
revoke insert, delete, update on hrs.* from 'hellokitty'@'%';
drop user 'hellokitty'@'%'; -- 刪掉新用戶
視圖
- 查詢的快照(簡化查詢操作)
- 通過視圖可以將用戶的訪問權限限制到某些指定的列上
-- 創建視圖
create view vw_emp_dept as
select eno, ename, dname from tb_emp t1 inner join tb_dept t2 on t1.dno=t2.dno;
-- 使用視圖
select ename, dname from vw_emp_dept;
-- 刪除視圖
drop view vw_emp_dept;
索引(index)
- 索引可以加速查詢所以應該在經常用于查詢篩選條件的列上建立索引
- 索引會使用額外的存儲空間而且會讓增刪改變得更慢(因為要更新索引)
- 所以不能夠濫用索引
-- 創建索引
create index idx_emp_ename on tb_emp (ename);
-- 刪除索引
drop index idx_emp_ename on tb_emp;
- explain生成執行計劃
explain select eno, ename from tb_emp where eno=7800;
explain select eno, ename from tb_emp where eno<>7900;
explain select eno, ename from tb_emp where ename='張三豐';
explain select eno, ename from tb_emp where ename like '張%';
explain select eno, ename from tb_emp where ename like '%張';
explain select eno, ename from tb_emp where ename<>'張三豐';
如果在執行計劃中,type類型是all 表示查詢語句效率最差,range 次之,const 最好
image.png
觸發器(trigger)
- 為什么不用觸發器:
在執行增刪改操作時可以觸發其他的級聯操作,在數據量很大的情況下,會導致“鎖表”現象,但是有可能導致“鎖表”現象,實際開發中應該盡量避免使用觸發器
-- update tb_dept set dno=11 where dno=10;
-- delete from tb_dept where dno=11;
delimiter $$
create trigger tr_dept_update
after update on tb_dept for each row
begin
update tb_emp set dno=new.dno where dno=old.dno;
end$$
delimiter ;
drop trigger tr_dept_update;
- 替代方案:
在添加外鍵時設置級聯操作cascade
(cascade 表示級聯操作,就是說,如果主鍵表中被參考字段更新,外鍵表中也更新,主鍵表中的記錄被刪除,外鍵表中改行也相應刪除)
默認是 on delete restrict 即不能級聯操作
image.png
事務(transaction)
把多個增刪改的操作做成不可分割的原子性操作,要么全部都做,要么全都不做
begin; -- 開啟事務
delete from tb_emp;
commit; -- 提交(事務中的所有操作全都生效)
rollback; -- 回滾(事務中的所有操作全部撤銷)
(存儲)過程/函數
把一系列的SQL可以封裝到一個過程中,而且可以加上分支和循環,將來通過過程的名字直接調用過程即可,因為創建過程時已經提前編譯了SQL語句,所以比直接執行SQL語句性能更好
-- 創建存儲過程
delimiter $$
create procedure sp_dept_avg_sal(deptno int, out avgsal float)
begin
select avg(sal) into avgsal from tb_emp where dno=deptno;
end$$
delimiter ;
-- 調用存儲過程
call sp_dept_avg_sal(20, @a);
-- 查找存儲在@a變量里的數據
select @a;