概述
主鍵:唯一區分表中每個行(不可重複,不允許null
mysql:基於客戶-伺服器的資料庫系統
使用mysql
mysql是部署在主機上的,可以通過ssh建立mysql連線
# 顯示資料庫
show databases;
# 選擇資料庫
use databases;
# 顯示庫中的表
show tables;
# 顯示錶中的列
show columns from [table];
# 顯示狀態資訊
show status;
# 顯示使用者
show grants;
# 顯示錯誤和警告
show errors;
show warnings;
關於表
default
可以給列賦一個預設值- 這個預設值不允許是函式
not
或者not null
表明插入資料時是否允許該列為null值,預設情況下為null
- 預設的儲存引擎為
innoDB
# 建立表
create table student(
student_id int primary key auto_increment,
name varchar(20) not null default '張大炮'
)engine=innoDB;
# 使用複合主鍵
create test(
test_id int auto_increment,
math int,
chinese int,
primary key(math,test_id)
);
外來鍵約束
外來鍵經常應用的地方為以下兩種情況:
-
父表更新時子表也更新,父表刪除時如果子表有匹配的項,刪除失敗;
-
父表更新時子表也更新,父表刪除時子表匹配的項也刪除。
注意:只有innoDB
支援外來鍵,MyISAM
不支援外來鍵
# 基本格式
constraint (key_name) foreign key(column) references table(column)
on delete/update (觸發語句)
on delete
和on update
表示事件觸發,觸發操作有以下幾種:
- RESTRICT(限制外表中的外來鍵改動,預設值)
- CASCADE(跟隨外來鍵改動)
- SET NULL(設空值)
- SET DEFAULT(設預設值)
- NO ACTION(無動作,預設的)
# 建立外來鍵約束
# 外來鍵關聯的表的元素改地,則這個表裡面的關聯元素也會改動
create table test(
test_id int auto_increment,
subject varchar(10),
date date,
student_id int,
constraint stu_fk foreign key(student_id) references student(student_id)
on update cascade,
primary key(test_id)
)engine=InnoDB;
關於引擎
InnoDB:可靠事務處理引擎,但不支援全文字搜尋
MyISAM:效能高,但不支援事務處理
Memory:功能等同MyISAM,但資料儲存在記憶體,很快但不能永久儲存,適合臨時表
修改表
使用alter table
來修改修改表,一般是add
操作和rename
操作
add
:可以新增新列和鍵約束
# 新增列
alter table student add
class int not null;
# 新增外來鍵約束
alter table student add
constraint st_fk foreign key(student_id) references test(student_id)
on update cascade;
刪除表
drop table student;
資料檢索
基本格式如下
select [column...] from [table];
column可以選擇多個列,也可用萬用字元*
表示所有列
去除重複行:使用distinct
關鍵字,distinct
作用於所有列
# 兩個列都一樣才會認為是重複
select distinct student_id,student_name form student;
使用limit
限制結果
注意:行號從0開始
# 返回前5行
# 相當於 limit 0,5
select student_id form student limit 5;
# 返回行5開始的後5行(包括第5行
select student_id form student limit 5,5;
使用.
來表示全限名
# 表示從school庫的student表查student_name這個列
select student.student_name from school.student;
資料排序
使用order by
字句選擇按照哪個列來進行排序
預設順序:A—>Z,0—>∞,使用DESC
指定為降序排列(必須指定在每個列上
可指定多個列
# 結果通過名字排序
select name from student order by name;
# 優先按照name排序,相同則按照number排序;降序
select name from student order by name DESC,number DESC;
資料過濾
使用where字句
使用where
字句限定條件
運算子 | 效果 |
---|---|
= | 等於 |
!=或<> | 不等於 |
> | 大於 |
< | 小於 |
>= | 大於等於 |
<= | 小於等於 |
between | 限定在兩個值之間 |
- 匹配字串需要單引號,匹配數值則不需要
- 使用
and
和or
連線多個條件,and
運算優先順序高於or
- 使用
is null
檢查空值 - 使用
in
來限定範圍,範圍是一個離散值的集合,離散值用,
隔開 - 使用
not
來否定限定範圍
# 按照id和grade兩個條件進行限定
select name from student where id='0000' and grade=100;
# 空值檢查
select name from student where id is null;
# 使用between限定範圍,下面2個語句等價
select name from student where id between '0000' and '1000';
select name from student where id >= '0000' and id <= '1000';
# 使用in限定範圍,下面2個語句等價
select name from student where id in (1,2);
select name from student where id = 1 or id = 2;
# 使用not取限定範圍以外的值
select name from student where id not in (1,2);
使用萬用字元
使用like
操作符來進行模糊匹配
- 不能匹配null
- 注意:萬用字元時間開銷大,能採用其他操作符儘量採用其他操作符
操作符 | 效果 |
---|---|
% | 匹配任意多個字元 |
_ | 匹配單個字元 |
# 多字元匹配
select name from student where id like '%00%';
# 單字元匹配
select name from student where id like '_00';
建立計算欄位
欄位:多個列的值合成而成
拼接欄位
使用Concat()
來拼接多個列
# 拼接name、=以及grade
select Concat(name,'=',grade) from student;
-
使用
RTrim()
和LTrim()
分別去除左右多餘空格,Trim()
直接去除兩邊空格 -
使用
as
為列賦別名用以顯示# 賦name別名為姓名 select name as 姓名 from student;
算數運算
操作符 | 意義 |
---|---|
+ | 加 |
- | 減 |
* | 乘 |
/ | 除 |
# 計算學號000開頭的學生總成績
select Chinese+Math+English as 總成績 from student where id = '000_';
函式
sql支援以下函式型別:
- 處理文字串
- 算術操作
- 處理日期
- 系統函式(返回登入資訊,檢查版本等
文字處理函式
函式 | 效果 |
---|---|
Left() | 返回左邊的字元 |
Length() | 返回串長度 |
Locate(subStr,string) | 找出字串出現的位置 |
Lower() | 轉換小寫 |
LTrim() | 去除左邊空格 |
RTrim() | 去除右邊空格 |
Right() | 返回右邊的字元 |
Soundex() | 匹配發音類似的值 |
SubString(string,position,length) | 返回字串 |
Upper() | 轉換大寫 |
# 匹配發音類似Y Lei的值
select grade from student where Soundex(name) = Soundex('Y Lei');
日期處理函式
日期時間滿足yyyy-MM-dd HH:mm:SS
形式
函式 | 說明 |
---|---|
AddDate() | 增加一個日期(天、周 |
AddTime() | 增加一個時間(時、分 |
CurDate() | 返回當前日期 |
CurTime() | 返回當前時間 |
Date() | 返回日期時間的日期部分 |
DateDiff() | 計算日期之差 |
Date_Add() | 日期運算 |
Date_Format() | 返回格式化的日期和時間串 |
Day() | 返回日期的天數 |
DayOfWeek() | 返回日期對應的星期幾 |
Hour() | 返回時間的小時部分 |
Minute() | 返回時間的分鐘部分 |
Month() | 返回日期的月份 |
Now() | 返回當前日期和時間 |
Second() | 返回一個時間的秒部分 |
Time() | 返回一個日期時間的時間部分 |
Year() | 返回日期的年份 |
常見情況:Date資料型別的欄位值存入了yyyy-MM-dd HH:mm:SS
形式的欄位值,但匹配時只想要日期或者時間
# 只需要日期值進行比較
select id from student where Date(register_time)='2001-2-3';
# 取出某年某月的資料
select id from student where Year(register_time)=2005 and Month(register_time)=6
數值處理函式
函式 | 說明 |
---|---|
Abs() | 返回絕對值 |
Cos() | 返回餘弦值 |
Exp() | 返回指數值 |
Mod() | 返回餘數 |
Pi() | 返回圓周率Π |
Rand() | 返回隨機數 |
Sin() | 返回正弦值 |
Sqrt() | 返回數的平方根 |
Tan() | 返回角度的正切值 |
# 返回一個餘數值
select Mod(55,33);
資料彙總函式
聚焦函式:確定行數、列數或者找其中某特定值(如最大值、最小值...)
- 使用聚焦函式處理列不能離開
group by
字句
函式 | 效果 |
---|---|
AVG() | 返回平均值 |
COUNT() | 返回某列的行數 |
MAX() | 返回該列最大值 |
MIN() | 返回該列最小值 |
SUM() | 列求和 |
注意:count(*)
多所有行進行計數,count(column)
對該列為null的行不計數
可以和distinct
關鍵詞搭配使用,去除重複值
使用distinct
必須指定列名,也就是說不能和count(*)
搭配使用
# 求平均值,每個值只計算一次
select AVG(DISTINCT grade) from student;
# 都整一遍
select AVG(grade) as 平均成績,
MAX(grade) as 最大值,
MIN(grade) as 最小值
from student;
資料分組
涉及group by
和having
兩個字句
group by
:按照某個屬性分組計算,相當於是對每個分組單獨進行一次sql語句的執行
- 必須出現在
where
之後,order by
之前 - 可指定多個,但最後會彙總到最後指定的屬性進行分組
- 除去聚焦函式(子句中不允許包含聚焦函式),
select
語句中出現的所有列都必須在group by
中給出
# 求業務員分別賣出了多少物品
select id,name,count(*) from kpi
group by id;
having
:起過濾作用,和where
類似。但where
過濾的是行,having
過濾的是分組
# 求除了id為1的業務員分別賣出了多少物品
select id,name,count(*) from kpi
group by id
having id!=1;
不要依賴group by
產生的順序
要正確排序還是應該使用order by
字句,該字句一般放在最後
# 順序求除id為1的每個業務員賣出物品的總價值
select id,sum(price) from kpi
group by id
having id!=1
order by sum(price);
select字句順序
| select
| from
| where
| group by
| having
↓ limit
多表查詢
子查詢
主要用途:查詢多個表
子查詢的執行順序是從內向外的
原理:select語句的查詢結果可以提供給其他select語句作為條件
可以巢狀,但一般不建議超過3層
# 聯結兩個表,查詢數學成績
select student_id from student where grade in(
select grade from test where subject='數學');
# 對每個學生單獨計算成績總和
select student_id,(select sum(grade) from test where test.student_id=student.student_id) as sum
from student order by grade DESC;
聯結表
外來鍵:將一個表的主鍵放在其他表作為外來鍵,加強資料一致性
外來鍵的欄位值依賴於所連線的表的主鍵,會對插入、刪除等操作做檢查
聯結表設定的條件一般是外來鍵
# 聯結多表進行查詢
select name,math
from student,test
where student.student_id=test.student_id;
# 使用表別名縮短sql語句
select name,math
from student as s,test as t
where s.student_id=t.student_id;
不使用where
字句做限定的話會返回一個笛卡爾積
內部聯結
聯結表這種基於兩個表之間相等測試的方法也稱為內部聯結
可以使用join...on...
達到相同目的
inner/outer:表示內聯結或者外聯結
join:使用join加入表
on:條件
# JOIN...ON...
select name,math
from student inner join test
on student.student_id=test.student_id;
高階聯結
自聯結
一張表自己聯結自己
使用場景:前一次查到這張表的資料作為後一次查詢這張表的條件的時候
為了避免二義性,列採用全限定名
# 首先根據test_id=4查到student_id,再根據student_id查到語文成績
select t2.chinese from
test as t1,test as t2
where t1.student_id=t2.student_id
and t1.test_id=4;
# 等效子查詢
select chinese from test
where student_id = (select student_id from test where test_id=4);
自然聯結
避免多表查詢中相同的列多次出現
注意:這是一種規範,不是某種特定的用法
實現:自己刻意避免出現相同列
外部聯結
雖然是兩個有關聯的表進行聯結,但其中一個表不一定所有資料在另外一個表都有對應資料
left outer join
:左邊的表的所有行加入進來,若右邊沒有對應的則顯示null
right outer join
:右邊的表的所有行加入進來,若左邊沒有對應的則顯示null
# 使用左聯結
select s.student_id,t.math
from student as s left join test as t
on s.student_id = t.student_id
student_id=5在右邊表中是沒有對應資料的,但還是會予以顯示
組合查詢
含義:執行多條sql語句,但將結果作為一個結果集返回
- 每個查詢中的內容相同(列、函式
- 預設返回的是並集,使用
union all
會出現重複結果 - 使用
order by
排序時只需要寫在最後一條sql語句上即可 - 相當於
where
子句中使用or
# 簡單測試
select student_id,math,chinese from test
where math > 20
union
select student_id,math,chinese from test
where chinese >20
全文字搜尋
不是所有儲存引擎都支援全文字搜尋
InnoDB不支援,MyISAM支援
啟動全文字查詢支援
在建立表的時候使用fulltext()
索引可以被全文字搜尋的列
同時指定引擎為MyISAM
create table article(
article_id int primary key auto_increment,
name varchar(20),
student_id int,
component text,
fulltext(component)
)engine=MyISAM;
進行全文字搜尋
match()
:指定被搜尋的列
against()
:指定搜尋表示式
# 搜尋帶有When的文字
select component from article
where match(component) against('When');
資料插入
插入完整行
使用insert into
來插入資料
# 基本格式
insert into [table](columns1,columns2,...) values(...);
可以不帶column,但是就需要記住列的順序按序插入
資料約束為null
的列可以插入null值
使用;
分隔多行插入,如果資料一致也可以使用,
分隔多行資料
# 插入多行
insert into student(name) values('袁瑞通過');
insert into student(name) values('贖金小松');
# 如果插入是相同列的資料,也可以這樣
insert into student(name) values('打字話'),('大選呀'),('大批及')
插入搜尋行
可以插入其他行中搜尋出來的結果
插入資料時通過select
字句返回的順序來匹配
# 插入select結果
insert into article(name,student_id)
select name,student_id from student where student_id=3;
資料更新
使用update...set...
來更新資料
ignore
關鍵字:預設更新多行資料如果發生錯誤,則之前更新過的資料恢復原來值;使用ignore
後不會恢復
# 更新多個資料
update ignore article set name='大花衣',
component='bilibili'
where article_id=3;
資料刪除
delete
關鍵字刪除整行的資料
# 刪除一行資料
delete from article where article_id=3;
檢視
檢視是虛擬的表,包含的是動態的sql查詢的結果
建立檢視後,可以進行和表一樣的查詢操作
檢視不能索引,不能有關聯觸發器
建立
# 建立檢視
create view exam as
select student.student_id,name,subject,date
from student,test;
檢視直接組合各個表中的列,在某些特定情況下非常方便
# 和查詢一般的表無異
select * from exam;
select * from exam where date between '2020-1-3' and '2021-3-4';
檢視的更新
檢視是可以更新的,但有很多的限制。一般只用檢視來做資料檢索。
儲存過程
方便後續使用的一條或多條sql語句集合
變數必須以@
開頭
使用call
來呼叫儲存過程
# 括號裡面的是引數
call product(@low,@high);
建立儲存過程
# 遵頊以下格式
create procedure grade_avg()
begin
select avg(grade) as 平均成績
from test;
end;
注意:mysql應用程式中會出現;
衝突,使用delimiter
來定義一個分隔符使用
# 定義分隔符為 //
DELIMITER //
create procedure grade_avg()
begin
select avg(grade) as 平均成績
from test;
end //
使用drop
刪除儲存過程
drop procedure grade_avg();
使用引數
引數:
IN
: 表示輸入引數,可以攜帶資料帶儲存過程中
OUT
: 表示輸出引數,可以從儲存過程中返回結果
INOUT
: 表示輸入輸出引數,兩者結合
使用set
為變數賦值
使用into
把查詢結果賦給變數
# 攜帶輸入引數的儲存過程
DELIMITER //
create procedure search(in sid int)
begin
select * from student where student_id=sid;
end //
# 使用帶內部引數的儲存過程:直接傳入引數值
call search(10);
# 攜帶輸出引數的儲存過程
DELIMITER //
create procedure stu_out(out str varchar(20))
begin
set str='123123';
end //
# 使用外部引數的儲存過程:先獲得這個外部變數值,再進行操作
call stu_out(@name);
select @name;
# 使用select into
delimiter //
create procedure stu_into(in id int,out str varchar(20))
begin
select name into str
from student where student_id=id;
end //
# 使用該儲存過程
call stu_into(5,@name);
select @name as 名字;
使用分支控制語句
if...then...elseif...else...end if
的格式
# 使用分支控制
delimiter //
create procedure weekday(in input int,out output varchar(10))
begin
if input=1 then set output='星期一';
elseif input=2 then set output='星期二';
else set output='其他日子';
end if;
end //
# 使用該儲存過程
call weekday(2,@day);
select @day;
使用迴圈控制語句
通過declare
定義儲存過程的內部變數(也可叫區域性變數、臨時變數
採用while...do...end while
的格式
# 使用迴圈控制
# 計算1到某個數值的和
delimiter //
create procedure stu_while(in input int,out output int)
begin
declare i int default 0;
declare result int default 0;
while i<=input
do
set result=result+i;
set i=i+1;
end while;
set output=result;
end //
# 使用該儲存過程
call stu_while(4,@res);
select @res as 和;
還可以採用repeat...until...end repeat
語句
# 修改上面例子的迴圈部分
repeat
set result=result+i;
set i=i+1;
until i>input end repeat;
遊標
場景:為了在檢索出來的行中前進後者後退幾行
只能用在儲存過程
- 在儲存過程中用
declare
宣告遊標,遊標的變數名是cursor
- 使用
for
來使遊標關聯select
語句 - 建立好過後,還要使用
open
來開啟遊標;並且不使用的話還要使用close
關閉遊標釋放資源 - 一般遊標用在迴圈語句,為了使遊標可以正常退出,一般需要繫結一個對應的錯誤處理
異常處理
exit handler
:出現某種異常後退出
continue handler
:出現某種異常後繼續
應用場景:事務出現錯誤時進行回滾
遊標中的使用:遊標檢索完時設定退出標誌
使用遊標
fetch...into...
將遊標值賦給變數
# 使用遊標
delimiter //
create procedure cursor_test()
begin
declare done boolean default 0;
declare str varchar(20);
declare ct cursor for
select name from student;
declare continue handler for not found set done=1;
open ct;
repeat
fetch ct into str;
until done end repeat;
close ct;
end //
一個使用場景
涉及到資料遷移,使用遊標迴圈將資料轉移非常的方便
# 將多行資料轉移建立一個新的表
delimiter //
create procedure new_test()
begin
declare name varchar(20);
declare id int;
declare grade int;
declare subject varchar(20);
declare done boolean default 0;
declare cs cursor for
select student.name,student.student_id,test.grade,test.subject from student,test where student.student_id=test.student_id;
declare continue handler for not found set done=1;
create table if not exists grades(
grades_id int primary key auto_increment,
name varchar(20),
student_id int,
grade int,
subject varchar(20)
);
open cs;
repeat
fetch cs into name,id,grade,subject;
insert into grades(name,student_id,grade,subject) values(name,id,grade,subject);
until done end repeat;
close cs;
end //
觸發器
觸發器是某張表執行某一型別的語句後,表自動去執行某一儲存過程
比如:某一張表的資料有修改,另一張表跟著也要修改
響應語句型別:delete
,insert
,update
- 觸發器只能繫結到表,不能繫結到檢視
mysql
的觸發器不能呼叫儲存過程
刪除和建立
建立觸發器給出四條資訊:
- 觸發器名
- 關聯表名
- 響應活動(delete、insert、update)
- 響應時間(before、after)
# 建立觸發器
create trigger ct after insert on student
for each row
select 'balbala';
# 刪除觸發器
drop trigger ct;
insert觸發器
new
可以訪問最新插入的行before insert
觸發器中new
的值可以更改,即把將要插入的值更改了再插入
# 建立一個insert觸發器
create trigger ct after insert on student
for each row
select new.student_id into @id;
# 執行insert語句後可以訪問@id
insert into student(name) values('asduh');
select @id;
delete觸發器
old
訪問被刪除的行,裡面的資料是隻讀的
# 建立一個delete觸發器
create trigger ct after delete on grades
for each row
select old.student_id,old.name into @id,@name;
# 執行delete語句後可以訪問引數
delete from grades where grades_id=1;
select @id as id,@name as name;
update觸發器
old
訪問該行更新前的數值,new
訪問該行更新後的數值before update
觸發器可以更改new
中的值old
都是隻讀的
# 建立update觸發器,將更新值全部換成大寫
create trigger ct4 before update on choice
for each row
set new.choice01=upper(new.choice01);
# 檢視結果
update choice set choice01='wasdfg' where choice_id=1;
select * from choice;
事務處理
- 使用
InnoDB
,MyISAM
不支援事務處理 - mysql預設的事務處理是每條sql語句自動提交
# autocommit為0:不自動提交
set autocommit=0;
事務:一組sql語句
回滾:撤銷指定sql語句
提交:將未儲存的sql語句提交到資料庫,也就是執行
保留點:臨時佔位符,可以釋出回退
開始事務處理
使用start transaction
標誌事務的開始
使用commit
提交事務,事務中的多條sql語句是被一起提交的
使用rollback撤銷事務
,只能在一個事務內使用
# 提交事務
start transaction;
delete from student where name='打字話';
insert into student(name) values('asd');
commit;
# 撤銷事務
start transaction;
delete from student where name='打字話';
insert into student(name) values('asd');
rollback;
使用保留點
rollback
事務回滾是直接回滾到transaction還沒開始的地方
保留點用在部分回滾的場景
使用savepoint...
設定保留點
# 設定保留點,部分回退
start transaction;
delete from student where name='打字話';
savepoint sv1;
insert into student(name) values('asd');
rollback to sv1;
安全管理
管理使用者
名為mysql
的資料庫中儲存了資料庫設定等資訊,可以在裡面的user
表檢視資訊
# 檢視使用者
use mysql;
select user from user;
建立和刪除使用者
identified by
設定密碼
# 建立使用者
create user xt identified by '123456';
# 修改使用者名稱
rename user xt to xtbro;
# 刪除使用者
drop user xtbro;
# 更新密碼,需要加密入表
set password for xt = Password('1234567');
賦予許可權
show grants for...
檢視許可權- 使用
grant
賦予許可權
# 賦予school資料庫下的所有表的insert許可權
grant insert on school.* to xt;
# 檢視許可權
show grant for xt;
# 撤銷許可權
revoke insert on school.* from xt;
許可權的層次:
整個伺服器:grant all
整個資料庫:on database.*
特定的表:on database.table
特定的列:on database.table.column
特定的儲存過程