不論是做那種語言的編程,我們都離不開和數據庫打交道,在面試過程中難免會問到一些和數據庫相關的知識點,下面我來對常用並且比較重點的知識點進行梳理,大家在面試之前也可以看看,祝找到更好的工作,下面以mysql爲例進行說明。
下面是供大家參考 的文章的目錄,內容有些豐富哦,希望大家耐心的看完,對加強mysql的基礎有重要的幫助。
目錄
存儲在數據庫中的一段過程代碼,多條sql語句的記錄和,用於完成某一個功能,類似於一個方法;
1.約束
mysql中的約束有五種: 主鍵,外鍵,唯一,非空,默認,檢查(mysql 沒有實現)。
1.1 主鍵
是一行數據的唯一標識
不重複
不能爲空
自動創建索
儘量使用業務無關的數據作爲主鍵
1.1.1建表時添加主鍵
create table tb(
id int primary key.
);
create table tb(
id int,
...,
primary key(id)
);
雙主鍵,字段組合作爲主鍵,儘量不用
create table tb(
name varchar(20),
ip varchar(20),
primary key(name, ip)
);
1.1.2 修改表時添加主鍵
alter table tb4
add primary key(id);
1.1.3 查看主鍵約束
desc tb4;
show create table tb4\G
1.1.4刪除主鍵約束
alter table tb4
drop primary key;
1.1.5 自增主鍵
向表中插入數據時,不需要提供自增主鍵的值,它會自動產生連續增加的值.
如果插入null,自動填入新的自增值.
如果插入較大值,以後會從插入的值繼續向後遞增.
1.1.6 添加自增主鍵
mysql中,只有主鍵才允許自增
create table tb5(
id int primary key auto_increment,..
);
alter table tb5
modify id int auto_increment;
1.1.7 獲得剛剛插入的自增值
使用函數: last_insert_id() 函數.
沒有執行過insert語句,函數返回0
多個客戶端都產生了自增值,只查詢當前會話的自增值
select last_insert_id();
set names gbk; -- 通知服務器客戶端字符集
use test;
-- 同時向班學生表和練習方式表插入數據
insert into xuesheng(name)
values('張三');
insert into lianxi(xs_id,tel)
values(last_insert_id(),'234563462345');
select * from xuesheng;
select * from lianxi;
1.2 外鍵
外鍵引用主鍵中存在的值,
外鍵允許重複,也允許null值,
外鍵自動出創建索引
外鍵會降低表的訪問效率,在大型互聯網應用中,數據庫表一般都不添加外鍵約束,用程序來保證數據的正確性。
學生表
id(PK) |
姓名 |
性別 |
1 |
張三 |
男 |
2 |
李四 |
女 |
3 |
王五 |
男 |
學生練習方式表
學生id(FK) |
電話 |
|
1 |
1412341234 |
1234213 |
3 |
23423452345 |
3452345 |
1.2.1 建表時添加外鍵
create table tb5(
id int,
xs_id int, -- 學生id,引用學生表的主鍵id
...,
foreign key(xs_id) references xuesheng(id)
);
1.2.2 修改表時添加外鍵
alter table tb5
add foreign key(xs_id) references xuesheng(id);
1.2.3 外鍵測試:
-- 創建學生表
drop table xuesheng;
create table xuesheng(
id int primary key auto_increment,
name varchar(20)
)engine=innodb charset=utf8;
-- 創建班級表
drop table banji;
create table banji(
id int primary key auto_increment,
name varchar(20)
)engine=innodb charset=utf8;
-- 修改學生表,添加banji_id外鍵,引用班級的主鍵
alter table xuesheng
add (
banji_id int,
foreign key(banji_id) references banji(id)
);
insert into banji(name)
values('一班'),('二班'),('三班');
insert into xuesheng(name,banji_id)
values('張三',1) , ('李四',3)
, ('王五',3) , ('趙六',1);
select * from banji;
select * from xuesheng;
1.2.4 刪除外鍵約束
刪除外鍵約束,不會自動刪除它的索引
通過約束名(show create table看到的名字)刪除外鍵:
alter table xuesheng
drop foreign key xuesheng_ibfk_1;
通過索引名再刪除索引:
alter table xuesheng
drop index banji_id;
1.3 唯一約束
保證字段中的值不重複,但允許重複的null值
唯一約束會創建索引,如果取消唯一約束,通過刪除索引來取消
1.3.1 創建表時添加唯一約束
create table tb5(
id int primary key auto_increment,
email varchar(100) unique,
...
);
create table tb5(
id int primary key auto_increment,
email varchar(100)
...,
unique key(email)
);
1.3.2 修改表時添加唯一約束
alter table tb5
modify email varchar(100) unique;
alter table tb5
add unique key(email);
1.3.3 添加字段組合唯一約束
create table tb5(
...,
name ...,
ip ...,
...,
unique key(name, ip)
);
alter table tb5
add unique key(name, ip);
1.3.4 測試唯一約束
-- 班級表name唯一
-- 如果已經存在重複值,不能添加唯一約束
alter table banji
add unique key(name);
insert into banji(name)
values('a'),('b');
insert into banji(name)
values('a'),('b');
1.3.5 刪除唯一約束
使用唯一約束的索引名來刪除
alter table tb5
drop index name;
1.4 非空約束
約束字段不能取null(空)值
1.4.1 添加非空約束
create table tb5(
...,
email varchar(100) not null,
...
);
alter table tb5
modify email varchar(100) not null;name非空
-- 如果字段中已經存在null值,
-- 不能添加非空約束
alter table xuesheng
modify name varchar(20) not null;
-- 失敗,name 非空
insert into xuesheng(name,banji_id)
values(null, 2);
1.4.2 查看非空約束
desc xuesheng;
show create table xuesheng\G
1.4.3 刪除非空約束
alter table tb5
modify email varchar(100) null;
-- 不寫也可以
alter table tb5
modify email varchar(100);
1.5 檢查約束
設置檢查條件,判斷存入字段中的值,是否符合要求
mysql支持檢查約束的語法,但沒有實現檢查約束
對年齡範圍進行檢查: >=7 並且 <=60
對性別取值檢查: ='男' 或者 ='女'
create table tb5(
...,
age int,
gender char(1),
...
check(age>=7 and age<L=60),
check(gender='男' or gender='女')
);
1.6 默認值
設置了默認值的字段,如果插入數據時不提供數據,會自動插入默認值
create table tb5(
...,
deleted tinyint default 0,
...
);值測試
-- 學生表添加status字段
-- 1-正常 2-休學 3-刪除
alter table xuesheng
add status int default 1;
insert into xuesheng(name)
values('a'),('b');
select * from xuesheng;
2 事務
- 事務由多個數據操作(增刪改查)組合
- 事務是數據操作的最小單元
- 事務中所有操作全部成功,事務整體成功
- 當事務中一項操作失敗,事務整體失敗
例如,遊戲中 A 賬戶向 B 賬戶轉賬
- A 更新,減掉金額
- B 更新,加金額失敗(斷電),轉賬事務要整體失敗,回退到以前的狀態
2.1 事務特性:ACID
A - 原子性 Atomic
C - 一致性 Consistency
轉賬前 a+b = 100
轉帳後 a+b = 100
I - 隔離性 Isolation
一個事物進行中時,
另一事物不能操作數據
D - 持久性 Durancy
提交事務之後,
數據持久生效
2.2 mysql事務操作
2.2.1 開啓事務
- begin
- start transactio
- Set-autocommit=0
- 設置關閉自動提交
2.2.2 提交事務
commit
2.2.3 回滾事務
rollback
2.2.3 事務的例子
-- 多對多關係 - kecheng表
會話1 |
會話2 |
begin; |
begin; |
insert into kecheng(name) values('a'),('b');
update kecheng set name='x' where id=1;
select * from kecheng; |
|
|
select * from kecheng; |
commit; |
|
|
select * from kecheng; |
|
commit; |
|
select * from kecheng; |
會話一 |
會話二 |
bigin; |
bigin; |
insert into kecheng(name) values('c'),('d');
update kecheng set name='y' where id=1;-- 鎖定一行數據
select * from kecheng; |
|
|
-- 不能修改加鎖數據,除非其它事務結束 update kecheng set name='k' where id=1; |
rollback; |
|
select * from kecheng; |
|
|
update kecheng set name='k' where id=1; |
|
commit; |
2.3 事務隔離
事務完全隔離,一個事務完成,另一個事務才能執行,效率低
事務不隔離,會有數據訪問衝突,數據不安全
數據庫當中,可以設置事務的隔離性,來兼顧安全和性能
2.3.1 數據訪問衝突
- 髒讀(一般不允許發生): 一個會話未提交的數據,被另一個會話讀取
- 不可重複讀:同一行數據,再次執行相同查詢,與第一次查詢結果不一致
- 幻讀
- 其它會話新插入並提交的數據,查詢不到
- 其它會話刪除並提交的數據,仍然能查詢到
2.3.2 事務隔離級別
set tx_isolation='READ-UNCOMMITTED';
set tx_isolation='read-committed';
set tx_isolation='repeatable-read';
set tx_isolation='serializable';
READ-UNCOMMITTED: 髒讀,不可重複讀,幻讀
read-committed: 不可重複讀,幻讀
repeatable-read: 幻讀
serializable: x
2.3.3 隔離級別測試
隔離級別
會話1 |
會話2 |
rollback; |
rollback; |
set tx_isolation='READ-UNCOMMITTED' |
|
begin; |
begin; |
|
select * from kecheng; |
insert into kecheng(name) values('e'),('f');
update kecheng set name='h' where id=1;
select * from kecheng; |
|
|
select * from kecheng; |
rollback; |
|
|
select * from kecheng; |
|
rollback; |
會話1 |
會話2 |
set tx_isolation='read-committed'; |
|
begin; |
begin; |
|
select * from kecheng; |
insert into kecheng(name) values('g'),('h');
update kecheng set name='w' where id=1;
select * from kecheng; |
|
|
select * from kecheng; |
commit; |
|
|
select * from kecheng;-- 不一致,不可重複讀 |
|
commit; |
會話1 |
會話2 |
set tx_isolation='repeatable-read'; |
|
begin; |
begin; |
|
select * from kecheng; |
insert into kecheng(name) values('i'),('j');
update kecheng set name='v' where id=1;
select * from kecheng; |
|
|
select * from kecheng; |
commit; |
|
|
select * from kecheng;-- 事務日誌查詢 |
|
commit; |
|
select * from kecheng; |
會話1 |
會話2 |
rollback; begin; |
rollback; begin; |
|
select * from kecheng; |
insert into kecheng(name) values('k'),('l'); |
|
commit; |
|
|
select * from kecheng; |
|
selct count(*) from kecheng; |
|
update kecheng set name= concat('*',name); |
|
select * from kecheng; |
|
commit; |
會話1 |
會話2 |
rollback; begin; |
rollback; begin; |
|
select * from kecheng; |
delete from kecheng where name in('*k','*l','*i'); |
|
commit; |
|
|
select * from kecheng; |
|
update kecheng set name= concat(name,'*'); |
|
select * from kecheng; |
|
commit; |
|
select * from kecheng; |
3 視圖
將查詢語句保存到數據庫,起個名字,就是視圖,以後可以簡單的從視圖查詢
爲什麼要是用視圖
- 簡化查詢
- 安全 可以向用戶之暴露視圖,而不暴露具體的表
3.1 創建視圖
create or replace view v1 as select ....;
set names gbk;
use hr;
create or replace view v1
as
select
e1.employee_id,e1.first_name,
d.department_name,
l.city,
e2.first_name dept_mgr,
e3.first_name mgr_name
from
employees e1
join departments d
on e1.department_id=d.department_id
join locations l
on d.location_id=l.location_id
join employees e2
on d.manager_id=e2.employee_id
join employees e3
on e1.manager_id=e3.employee_id;
select * from v1;
3.2 查看視圖
show tables;
desc v1;
show create table v1\G
3.3 刪除視圖
drop view v1;
4 索引
加速查詢
索引爲字段中數據,生成一份索引數據,通過索引數據,可以快速定位數據
mysql 的innodb和myisam數據表引擎,生成索引模式使用b-tree(平衡紅黑樹)數據結構
缺點: 在執行插入 更新 刪除的操作時,索引會進行變動,影響了操作的效率。
4.1 創建索引
create index index1 on tb1(c1);
where c1='sdfsdf'
where c1 like 'a%'
where c1 like '%a' 不能使用索引
create index index1 on tb1(c1, c2);
where c1='sdf' and c2='sdf'
where c1='sdf'
where c2='sdfsdf'
創建索引
create index index_name
on employees(first_name, last_name);
4.2 查看索引
show create table employees\G
4.3 刪除索引
alter table employees
drop index index_name;
4.4 查詢語句是否使用索引來查詢
create index index_name
on employees(first_name, last_name);
explain select * from employees
where first_name='a' and last_name='b';
5 數據庫備份恢復
在操作系統命令行執行
- mysqldump 命令備份數據
- mysql 命令恢復數據
5.1 備份
一行命令:
mysqldump -uroot -p
--default-character-set=utf8 //表中存的是什麼編碼
stu>/home/soft01/stu.sql //庫>文件
5.2 恢復
- 新建hr2庫
create database hr2 charset=utf8;
-- 數據恢復
mysql -uroot -p
--default-character-set=utf8
hr2<d:\hr.sql
-- 查看hr2庫的數據
use hr2;
show tables;
select * from employees;
數據庫編程
6 變量
6.1 自定義會話變量
set @v1=43; -- 變量賦值必須set
select @v1;
set @v1=5;
select @v1;
6.2 mysql系統環境變量
show variables;
show variables like 'tx\_%';
show variables like '%char%';
show variables like '%auto%';
set autocommit=off;
set @@autocommit=off;
6.3 代碼塊中的局部變量
begin
declare i int;
declare i int default 0;
end;
7 儲過程存
存儲在數據庫中的一段過程代碼,多條sql語句的記錄和,用於完成某一個功能,類似於一個方法;
7.1 創建存儲過程
7.1.1 基本語法
-- 自定義結束符
delimiter //
drop procedure if exists p1;
//
create procedure p1()
begin
select now();
end;
//
7.1.2 參數
- in 輸入參數
- out 輸出參數
- inout 即可作爲輸入參數也可作爲輸出參數
- p1(in a int, out b int)
- call p1(5, @v1); 5作爲入參傳給a;@v1 變量作爲輸出參數,來獲得存儲過程的計算結果
7.2 調用存儲過程
drop procedure if exists p2;
//
create procedure p2(in a int, out b int)
begin
set b = a*a;
end;
//
call p2(5, @v1); //
select @v1; //
call p2(3, @v1); //
select @v1; //
--調用
call p1();
7.3 查看存儲過程
show procedure status\G
所有存儲過程
show procedure status where db='test'\G
查看指定庫中的存儲過程
show create procedure p1\G
7.4 刪除存儲過程
drop procedure if exists p1;
7.5 分支判斷
if 條件 then
...
end if;
if 條件 then
...
else
...
end if;
case
when 條件 then ...;
when 條件 then ...;
else
end case;
case 數據
when 值1 then ...;
when 值2 then ...;
else
end case;
分支測試
drop procedure if exists p3;
//
create procedure p3(in a int)
begin
if a=1 then
select 1;
end if;
case
when a=2 then select 2;
when a=3 then select 3;
else select 4;
end case;
end;
//
call p3(1); //
call p3(2); //
call p3(3); //
call p3(4); //
call p3(5); //
7.6 循環
while 條件 do
...
end while;
lp:loop -- 給循環起別名
...
if ... then
leave lp; -- 離開lp循環
end if;
end loop;
repeat
...
until 條件 end repeat;
循環測試
-- 創建一個測試表
create table t(
c int
);
-- 創建存儲過程,循環向表中插入n行數據
create procedure p4(in n int)
begin
-- 定義一個控制循環次數的變量
-- declare 定義局部變量
declare i int default 0;
-- while
while i<5 do
insert into t values(i+1);
set i=i+1;
end while;
set i=0;
lp:loop
insert into t values(i+1);
set i=i+1;
if i>=5 then
leave lp;
end if;
end loop;
set i=0;
repeat
insert into t values(i+1);
set i=i+1;
until i>=5 end repeat;
end;
//
call p4(5);
//
8 函數
函數有返回值,存儲過程是一個特殊的函數
8.1 創建函數
create or replace function fn1(a int)
returns varchar(255)
begin
declare r int;
set r = a*a;
return r;
end;
8.2 調用函數
select fn1(3);
select employee_id,fn1(department_id)
from employees;
8.3 查看函數
show function status\G
show function status where db='test'\G
show create function f\G
8.4 刪除函數
drop function if exists f;
8.5 函數demo
-- a的b次方
drop function if exists fn_pow;
create function fn_pow(a bigint, b bigint)
returns bigint
begin
declare r bigint;-- 用來存結果
declare i int; -- 用來控制循環此時
set r = a; -- 從第一個a開始,向後乘b-1次
set i = 0;
while i<b-1 do
set r = r*a;
set i = i+1;
end while;
return r;
end;
//
select fn_pow(2,3);
//
select c, fn_pow(c,3) from t;
//
產生隨機字符串
-- 算長度* 隨機產生[a, b)長度的字符串
* a+[0,b-a): floor(a+rand()*(b-a))
* 假設隨機長度是 3,產生三個隨機字符
* 從一組字符串s0隨機選取 'abcdefg....'
* 隨機定位j位置1+[0,char_length(s0)-1)
* 取一個字符substring(s0,j,1)
* 重複3次取三個字符連接
drop function if exists fn_randstr;
create function fn_randstr(a int, b int)
returns varchar(255)
begin
declare len int;-- 隨機的長度
declare s0 varchar(600) default ' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ的一是在不了有和人這中大爲上個國我以要他時來用們生到作地於出就分對成會可主發年動同工也能下過子說產種面而方後多定行學法所民得經十三之進着等部度家電力裏如水化高自二理起小物現實加量都兩體制機當使點從業本去把性好應開它合還因由其些然前外天政四日那社義事平形相全表間樣與關各重新線內數正心反你明看原又麼利比或但質氣第向道命此變條只沒結解問意建月公無系軍很情者最立代想已通並提直題黨程展五果料象員革位入常文總次品式活設及管特件長求老頭基資邊流路級少圖山統接知較將組見計別她手角期根論運農指幾九區強放決西被幹做必戰先回則任取據處隊南給色光門即保治北造百規熱領七海口東導器壓志世金增爭濟階油思術極交受聯什認六共權收證改清己美再採轉更單風切打白教速花帶安場身車例真務具萬每目至達走積示議聲報鬥完類八離華名確才科張信馬節話米整空元況今集溫傳土許步羣廣石記需段研界拉林律叫且究觀越織裝影算低持音衆書布覆容兒須際商非驗連斷深難近礦千周委素技備半辦青省列習響約支般史感勞便團往酸歷市克何除消構府稱太準精值號率族維劃選標寫存候毛親快效斯院查江型眼王按格養易置派層片始卻專狀育廠京識適屬圓包火住調滿縣局照參紅細引聽該鐵價嚴龍飛';
declare j int; -- 從s0隨機挑選的位置
-- 保存最終結果,從空串開始
declare s varchar(255) default '';
declare i int default 0;-- 控制次數
set len = floor(a+rand()*(b-a));
-- 循環len次挑選字符連接到s
while i<len do
-- 隨機定位
set j =
floor(1+rand()*(char_length(s0)-1));
-- 拿出s0中j位置的一個字符連到s
set s=concat(s, substring(s0,j,1));
set i=i+1;
end while;
return s;
end;
//
select fn_randstr(3,6);
//
set names gbk;
//
-- 如果數據庫字符集是latin1,設置gbk也不管用
-- 1.換庫 2.改當前庫的字符集屬性
alter database 庫名 charset utf8;
產生大量的數據
-- 創建一張內存表,大量暫時插入內存表中
-- 再將內存表數據,一次導入磁盤表
-- 內存表
create table tm(
c varchar(20)
)engine=memory charset=utf8;
//
-- 磁盤表
create table td(
id int primary key auto_increment,
c varchar(20)
)engine=innodb charset=utf8;
//
-- 批量產生數據的存儲過程
drop procedure if exists gen_data;
//
create procedure gen_data(in n int)
begin
declare i int default 0;-- 控制次數
-- 每次產生的字符串
declare s varchar(255);
-- 向內存表插入n條數據
while i<n do
set s = fn_randstr(3,6);
insert into tm values(s);
set i=i+1;
end while;
-- 將內存表數據一次導入磁盤表
insert into td(c) select * from tm;
-- 清空內存表
delete from tm;
end;
//
call gen_data(50000);//
call gen_data(50000);//
call gen_data(50000);//
...
9 觸發器
在插入、修改和刪除時,可以自動觸發一段代碼執行
- 操作之前觸發
- 操作之後觸發
- 六種觸發器:
- 一張表中最多只能有6個觸發器
- before insert
- before update
- before delete
- after insert
- after update
- after delete
- 兩個隱含的對象
- new - 新數據
- old - 舊數據
- insert
- new 插入的新數據
- old 沒有
- update
- new 修改之後的新數據
- old 修改之前的舊數據
- delete
- new 沒有
- old 被刪除的數據
- 訪問新的數據行或舊的數據行:
- new.employee_id
- old.first_name
9.1 創建觸發器
create trigger before_td_insert
before insert on td for each row
begin
...
end;
觸發器測試
-- 新建tb1表
create table tb1(
id int primary key auto_increment,
c varchar(20),
created datetime,
updated datetime
)engine=innodb charset=utf8;
//
-- 新建觸發器,插入數據時
-- 自動爲created和updated填入當前時間
create trigger tb1_before_insert
before insert on tb1 for each row
begin
set new.created=now();
set new.updated=now();
end
//
insert into tb1(c) values('a');
//
select * from tb1;
//
9.2 查看觸發器
use information_schema
//
select * from triggers\G
//
9.3 刪除觸發器
drop trigger 觸發器名
很感謝大家能夠耐心的看到這裏,是不是感覺自己又重新理清了一下對數據庫知識的思路,哈哈,感謝大家的支持,你們的支持就是我的動力,如果大家感覺這整理的還不錯的話,就轉發出去吧,讓我們一起在技術的海洋中遨遊向前,達到勝利的彼岸!謝謝大家!