- 實體與實體之間有3種對應(yīng)關(guān)系孙援,這些關(guān)系也需要存儲下來
- 在開發(fā)中需要對存儲的數(shù)據(jù)進行一些處理谱煤,用到內(nèi)置的一些函數(shù)
- 視圖用于完成查詢語句的封裝
- 事務(wù)可以保證復雜的增刪改操作有效
先看個問題
問:查詢每個學生每個科目的分數(shù)
分析:學生姓名來源于students表,科目名稱來源于subjects倦踢,分數(shù)來源于scores表,怎么將3個表放到一起查詢,并將結(jié)果顯示在同一個結(jié)果集中呢癌淮?
答:當查詢結(jié)果來源于多張表時,需要使用連接查詢
關(guān)鍵:找到表間的關(guān)系沦补,當前的關(guān)系是
students表的id---scores表的stuid
subjects表的id---scores表的subid
則上面問題的答案是:
select students.sname,subjects.stitle,scores.score
from scores
inner join students on scores.stuid=students.id
inner join subjects on scores.subid=subjects.id;
結(jié)論:當需要對有關(guān)系的多張表進行查詢時乳蓄,需要使用連接join
關(guān)系
-
創(chuàng)建成績表scores,結(jié)構(gòu)如下
- id
- 學生
- 科目
- 成績
思考:學生列應(yīng)該存什么信息呢夕膀?
答:學生列的數(shù)據(jù)不是在這里新建的虚倒,而應(yīng)該從學生表引用過來美侦,關(guān)系也是一條數(shù)據(jù);根據(jù)范式要求應(yīng)該存儲學生的編號魂奥,而不是學生的姓名等其它信息
同理菠剩,科目表也是關(guān)系列,引用科目表中的數(shù)據(jù)
- 創(chuàng)建表的語句如下
create table scores(
id int primary key auto_increment,
stuid int,
subid int,
score decimal(5,2)
);
外鍵
- 思考:怎么保證關(guān)系列數(shù)據(jù)的有效性呢耻煤?任何整數(shù)都可以嗎具壮?
- 答:必須是學生表中id列存在的數(shù)據(jù),可以通過外鍵約束進行數(shù)據(jù)的有效性驗證
- 為stuid添加外鍵約束
alter table scores add constraint stu_sco foreign key(stuid) references students(id);
- 此時插入或者修改數(shù)據(jù)時哈蝇,如果stuid的值在students表中不存在則會報錯
- 在創(chuàng)建表時可以直接創(chuàng)建約束
create table scores(
id int primary key auto_increment,
stuid int,
subid int,
score decimal(5,2),
foreign key(stuid) references students(id),
foreign key(subid) references subjects(id)
);
外鍵的級聯(lián)操作
- 在刪除students表的數(shù)據(jù)時棺妓,如果這個id值在scores中已經(jīng)存在,則會拋異常
- 推薦使用邏輯刪除买鸽,還可以解決這個問題
- 可以創(chuàng)建表時指定級聯(lián)操作涧郊,也可以在創(chuàng)建表后再修改外鍵的級聯(lián)操作
- 語法
alter table scores add constraint stu_sco foreign key(stuid) references students(id) on delete cascade;
- 級聯(lián)操作的類型包括:
- restrict(限制):默認值,拋異常
- cascade(級聯(lián)):如果主表的記錄刪掉眼五,則從表中相關(guān)聯(lián)的記錄都將被刪除
- set null:將外鍵設(shè)置為空
- no action:什么都不做
連接查詢
連接查詢分類如下:
表A inner join 表B:表A與表B匹配的行會出現(xiàn)在結(jié)果中
表A left join 表B:表A與表B匹配的行會出現(xiàn)在結(jié)果中妆艘,外加表A中獨有的數(shù)據(jù),未對應(yīng)的數(shù)據(jù)使用null填充
表A right join 表B:表A與表B匹配的行會出現(xiàn)在結(jié)果中看幼,外加表B中獨有的數(shù)據(jù)批旺,未對應(yīng)的數(shù)據(jù)使用null填充
在查詢或條件中推薦使用“表名.列名”的語法
如果多個表中列名不重復可以省略“表名.”部分
如果表的名稱太長,可以在表名后面使用' as 簡寫名'或' 簡寫名'诵姜,為表起個臨時的簡寫名稱
練習
- 查詢學生的姓名汽煮、平均分
select students.sname,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
group by students.sname;
- 查詢男生的姓名、總分
select students.sname,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
where students.gender=1
group by students.sname;
- 查詢科目的名稱棚唆、平均分
select subjects.stitle,avg(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
group by subjects.stitle;
- 查詢未刪除科目的名稱暇赤、最高分、平均分
select subjects.stitle,avg(scores.score),max(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
where subjects.isdelete=0
group by subjects.stitle;
字符串函數(shù)
- 查看字符的ascii碼值ascii(str)宵凌,str是空串時返回0
select ascii('a');
- 查看ascii碼值對應(yīng)的字符char(數(shù)字)
select char(97);
- 拼接字符串concat(str1,str2...)
select concat(12,34,'ab');
- 包含字符個數(shù)length(str)
select length('abc');
- 截取字符串
left(str,len)返回字符串str的左端len個字符
right(str,len)返回字符串str的右端len個字符
substring(str,pos,len)返回字符串str的位置pos起len個字符
select substring('abc123',2,3);
- 去除空格
ltrim(str)返回刪除了左空格的字符串str
rtrim(str)返回刪除了右空格的字符串str
trim([方向 remstr from str)返回從某側(cè)刪除remstr后的字符串str鞋囊,方向詞包括both、leading瞎惫、trailing溜腐,表示兩側(cè)、左瓜喇、右
select trim(' bar ');
select trim(leading 'x' FROM 'xxxbarxxx');
select trim(both 'x' FROM 'xxxbarxxx');
select trim(trailing 'x' FROM 'xxxbarxxx');
返回由n個空格字符組成的一個字符串space(n)
select space(10);
- 替換字符串replace(str,from_str,to_str)
select replace('abc123','123','def');
- 大小寫轉(zhuǎn)換挺益,函數(shù)如下
lower(str)
upper(str)
select lower('aBcD');
- 數(shù)學函數(shù)
求絕對值abs(n)
select abs(-32);
求m除以n的余數(shù)mod(m,n),同運算符%
select mod(10,3);
select 10%3;
地板floor(n)乘寒,表示不大于n的最大整數(shù)
select floor(2.3);
天花板ceiling(n)望众,表示不小于n的最大整數(shù)
select ceiling(2.3);
求四舍五入值round(n,d),n表示原數(shù),d表示小數(shù)位置黍檩,默認為0
select round(1.6);
求x的y次冪pow(x,y)
select pow(2,3);
獲取圓周率PI()
select PI();
隨機數(shù)rand()叉袍,值為0-1.0的浮點數(shù)
select rand();
- 還有其它很多三角函數(shù)始锚,使用時可以查詢文檔
- 日期時間函數(shù)
- 獲取子值,語法如下
- year(date)返回date的年份(范圍在1000到9999)
- month(date)返回date中的月份數(shù)值
- day(date)返回date中的日期數(shù)值
- hour(time)返回time的小時數(shù)(范圍是0到23)
- minute(time)返回time的分鐘數(shù)(范圍是0到59)
- second(time)返回time的秒數(shù)(范圍是0到59)
- select year('2016-12-21');
- 日期計算,使用+-運算符肌似,數(shù)字后面的關(guān)鍵字為year义黎、month、day姐呐、hour殿怜、minute、second
select '2016-12-21'+interval 1 day;- 日期格式化date_format(date,format)曙砂,format參數(shù)可用的值如下
- 獲取年%Y头谜,返回4位的整數(shù)
- 獲取年%y,返回2位的整數(shù)
- 獲取月%m鸠澈,值為1-12的整數(shù)
- 獲取日%d柱告,返回整數(shù)
- 獲取時%H,值為0-23的整數(shù)
- 獲取時%h笑陈,值為1-12的整數(shù)
- 獲取分%i际度,值為0-59的整數(shù)
- 獲取秒%s,值為0-59的整數(shù)
select date_format('2016-12-21','%Y %m %d');
- 當前日期current_date()
select current_date();
- 當前時間current_time()
select current_time();
- 當前日期時間now()
select now();
視圖
- 對于復雜的查詢涵妥,在多次使用后乖菱,維護是一件非常麻煩的事情
- 解決:定義視圖
- 視圖本質(zhì)就是對查詢的一個封裝
定義視圖
create view stuscore as
select students.*,scores.score from scores
inner join students on scores.stuid=students.id;
視圖的用途就是查詢
select * from stuscore;
子查詢
- 查詢支持嵌套使用
- 查詢各學生的語文、數(shù)學蓬网、英語的成績
select sname,
(select score from scores
inner join subjects sub on sco.subid=sub.id
where sub.stitle='語文' and stuid=stu.id) as 語文,
(select score from scores
inner join subjects sub on sco.subid=sub.id
where sub.stitle='數(shù)學' and stuid=stu.id) as 數(shù)學,
(select score from scores
inner join subjects sub on sco.subid=sub.id
where sub.stitle='英語' and stuid=stu.id) as 英語
from students;
事務(wù)
當一個業(yè)務(wù)邏輯需要多個sql完成時窒所,如果其中某條sql語句出錯,則希望整個操作都退回
使用事務(wù)可以完成退回的功能帆锋,保證業(yè)務(wù)邏輯的正確性
事務(wù)四大特性(簡稱ACID)原子性(Atomicity):事務(wù)中的全部操作在數(shù)據(jù)庫中是不可分割的吵取,要么全部完成,要么均不執(zhí)行
一致性(Consistency):幾個并行執(zhí)行的事務(wù)窟坐,其執(zhí)行結(jié)果必須與按某一順序串行執(zhí)行的結(jié)果相一致
隔離性(Isolation):事務(wù)的執(zhí)行不受其他事務(wù)的干擾海渊,事務(wù)執(zhí)行的中間結(jié)果對其他事務(wù)必須是透明的
持久性(Durability):對于任意已提交事務(wù),系統(tǒng)必須保證該事務(wù)對數(shù)據(jù)庫的改變不被丟失哲鸳,即使數(shù)據(jù)庫出現(xiàn)故障
要求:表的類型必須是innodb或bdb類型臣疑,才可以對此表使用事務(wù)
查看表的創(chuàng)建語句
show create table students;
- 修改表的類型
alter table '表名' engine=innodb;
事務(wù)語句
- 開啟begin;
- 提交commit;
- 回滾rollback;
示例1
- 步驟1:打開兩個終端,連接mysql徙菠,使用同一個數(shù)據(jù)庫讯沈,操作同一張表
終端1:
select * from students;
終端2:
begin;
insert into students(sname) values('張飛');
- 步驟2
終端1:
select * from students;- 步驟3
終端2:
commit;
終端1:
select * from students;
示例2
步驟1:打開兩個終端,連接mysql,使用同一個數(shù)據(jù)庫缺狠,操作同一張表
終端1:
select * from students;
終端2:
begin;
insert into students(sname) values('張飛');
步驟2
終端1:
select * from students;
- 步驟3
終端2:
rollback;
終端1:
select * from students;