1. 程式人生 > 實用技巧 >Luogu6018 [Ynoi2010]Fusion tree

Luogu6018 [Ynoi2010]Fusion tree

1、初識MySQL

java EE:企業級java開發 web

前端(頁面:展示,資料!)

後臺(連線點:連線資料庫JDBC,連線前端(控制,控制檢視跳轉,和給前端傳遞資料))

資料庫(存資料,Txt,Excel,word)

只會寫程式碼,學好資料庫,基本混飯吃

作業系統,資料結構與演算法!當一個不錯的程式設計師!

離散數學,數位電路,體系結構,編譯原理。+實戰經驗,高就程式設計師優秀的程式設計師

1.1、為什麼學習資料庫

1、崗位需求

2、現在的世界,大資料時代~,得資料庫者得天下。

3、被迫需求:存資料

4、資料庫是所有軟體體系最核心的存在 DBA

1.2、什麼是資料庫

資料庫(DB,DataBase)

概念:資料倉庫,軟體,安裝在作業系統(windows、Mac、linux)之上!SQL,可以儲存大量的資料。500萬

作用:儲存資料,管理資料

1.3、資料庫分類

關係型資料庫:
  • MySQL,Oracle,Sql Server,DB2,SQLlist
  • 通過表和表之間,行和行之間的關係進行資料的儲存, 學員資訊表,考勤表…
非關係型資料庫:
  • Redis,MongDB
  • 非關係型資料庫,物件儲存,通過物件的自身的屬性來決定。

DBMS(資料庫管理系統)

  • 資料庫的管理軟體,科學有效的管理我們的資料。維護和獲取資料;
  • MySQL,資料庫管理系統!

1.4、MySQL

MySQL是一個關係型資料庫管理系統

前世:瑞典的MySQL AB公司

今生:屬於Oracle旗下產品

MySQL是最好的 (Relational Database Management System,關係資料庫管理系統) 應用軟體之一。

體積小、速度快、總體擁有成本低,招人成本低,所有人必須會~

中小型網站、或者大型網站,叢集!

官網:https://www.mysql.com/

安裝建議:

1、儘量不要使用exe,

2、儘可能使用壓縮包安裝~

1.5 安裝MySQL

教程:https://www.cnblogs.com/hellokuangshen/p/10242958.html

2、操作資料庫

2.1、操作資料庫(瞭解)

1、建立資料庫
create database [if not exists] ...
2、刪除資料庫
drop database [if exist] ...
3、使用資料庫
--tab鍵的上面,如果你的表名或者欄位名是一個特殊字元,就需要帶``
use `...`
4、檢視資料庫
show database -- 檢視所有的資料庫

2.2資料庫的資料型別

數值
  • int 標準的證書 4個位元組
  • bigint 較大的資料 8個位元組
  • float 浮點數 4個位元組
  • double 浮點數 8個位元組(精度問題!)
  • decimal 字串形式的浮點數 金融計算時,一般是使用decimal
字串
  • char 字串固定大小的 0~255
  • varchar 可變字串 0~65535 常用的變數 String
  • tinytext 微型文字 2^8-1
  • text 文字串 2^16-1 儲存大文字
時間日期

java.util.Date

  • date YYYY-MM-DD,日期格式
  • time HH:mm:ss時間格式
  • datatime YYYY-MM-DD HH:mm:ss 最常用的時間格式
  • **timestamp 時間戳, 1970.1.1到現在的毫秒數!**也比較常用!
  • year 年份表示

null

  • 沒有值,未知
  • 注意,不要使用NULL進行運算,結果為NULL

2.3資料庫的欄位屬性(重點)

Unsigned:
  • 無符號的整數
  • 聲明瞭該列不能宣告為負數
zerofill:
  • 0填充的
  • 不足的位數,使用0來填充, int(3), 5 — 005
自增:
  • 通常理解為自增,自動在上一條記錄的基礎上+1(預設)
  • 通常用來設計唯一的主鍵~ index,必須是整數型別
  • 可以自定義設計主鍵資政的起始值和步長
非空 NULL not null:
  • 假設設定為not null,如果不給它賦值,就會報錯!
  • MULL,如果不填寫值,預設就是null!
預設:
  • 設定預設的值!
  • sex,預設值為男,如果不指定該列的值,就會有預設的值!

2.4、建立資料庫表(重點)

create table if not exist `student`(
    `id` int(4) not null auto_increment comment '學號',
    `name` varchar(30) not null default '匿名' comment '姓名',
    `pwd` varchar(20) not null default '123456' comment '密碼',
    `sex` varchar(2) not null default '女' comment '性別',
    `birthday` datatme defalut null comment '出生日期',
    `address` varchar(100) defalut null comment '家庭住址',
    `email` varchar(50) defalut null comment '郵箱',
    primary key(`id`)
)ending=innoDB default charset=utf8

格式

create table [if not exist] `表名`(
    `欄位名` 列型別 [屬性] [索引] [註釋],
    ......
    `欄位名` 列型別 [屬性] [索引] [註釋]
)[表型別][字串設定][註釋]

常用命令

show create database school --檢視建立資料庫的語句
show create table student --檢視student資料庫表的定義語句
desc student --顯示錶的結構

2.5、資料表的型別

--關於資料庫引擎
/*
INNODB 預設使用
MYISAM 早些年使用
*/
MYISAMINNODB
事務支援不支援支援
資料行鎖定不支援支援
外來鍵不支援支援
全文索引支援不支援
表空間大小較小較大,約為2倍

常規使用操作

  • MYISAM 節約空間,速度較快
  • INNODB 安全性高,事務的處理,多表多使用者操作
在物理空間存在的位置下

所有的資料庫檔案都存在data目錄下,一個資料夾就對應一個數據庫

本質還是檔案的儲存!

MySQL引擎在物理檔案上的區別

  • InnoDb在資料庫表中只有一個*.frm檔案,以及上級目錄下的ibdata1檔案
  • MyIASM對應的檔案:
    • *.frm 表結構的定義檔案
    • *.MYD 資料檔案(data)
    • *.MYI 索引檔案(index)
設定資料庫表的字符集編碼
charset=utf8

不設定的話,會是mysql預設的字符集編碼~(不支援中文!)

MySQL的預設編碼是Latin1,不支援中文

在my.ini中配置預設的編碼

character-set-server=utf8

2.6、修改刪除表

修改
--修改表名  alter table 舊錶名 rename as 新表名
alter table teacher rename as teacher1
--增加表的欄位 alter table 表名 add 欄位名 列表名
alter table teacher1 add int(11)

--修改表的欄位(重新命名,修改約束!)
--alter table 表名 modify 欄位名 列屬性[]
alter table teacher1 modify age varchar(11) --修改約束
--alter table 表名 change 舊名字 新名字 列屬性[]
alter table teacher1 change age age1 int(1) --欄位重新命名

--刪除表的欄位:alter table 表名 drop 欄位名
alter table teacher1 drop age1
刪除
--刪除表(如果表存在就刪除)
drop table if exist teacher1

所有的修改和刪除操作儘量加上判斷,以免報錯~

3、MySQL的資料管理

3.1、外來鍵(瞭解即可)

方式一、在建立表的時候,增加約束(麻煩,比較複雜)

create table `grade`(
    `gradeid` int(10) not null auto_increment comment '年級id',
    `gradename` varchar not null comment '年級名稱',
    primary key(`gradeid`)
)edning=innodb default charser=utf8


--學生表的gradeid欄位 要去引用年級表的額gradeid
--定義外來鍵key
--給這個外來鍵新增約束(執行引用) references引用

create table if not exist `student`(
    `id` int(4) not null auto_increment comment '學號',
    `name` varchar(30) not null default '匿名' comment '姓名',
    `pwd` varchar(20) not null default '123456' comment '密碼',
    `sex` varchar(2) not null default '女' comment '性別',
    `birthday` datatme defalut null comment '出生日期',
    `gradeid` int(10) not null auto_increment comment '學生的年級',
    `address` varchar(100) defalut null comment '家庭住址',
    `email` varchar(50) defalut null comment '郵箱',
    primary key(`id`),
    key `FK_gradeif`(`gradeid`),
    constraint `FK_gradeid` foreing key(`gradeid`) referents `grade`(`gradeid`)
)ending=innoDB default charset=utf8

刪除有外來鍵關係的表的時候,必須要先刪除引用別人的表(從表),再刪除被引用的表(主表)

方式二、建立表成功後,新增外來鍵約束

create table `grade`(
    `gradeid` int(10) not null auto_increment comment '年級id',
    `gradename` varchar not null comment '年級名稱',
    primary key(`gradeid`)
)edning=innodb default charser=utf8

create table if not exist `student`(
    `id` int(4) not null auto_increment comment '學號',
    `name` varchar(30) not null default '匿名' comment '姓名',
    `pwd` varchar(20) not null default '123456' comment '密碼',
    `sex` varchar(2) not null default '女' comment '性別',
    `birthday` datatme defalut null comment '出生日期',
    `gradeid` int(10) not null auto_increment comment '學生的年級',
    `address` varchar(100) defalut null comment '家庭住址',
    `email` varchar(50) defalut null comment '郵箱',
    primary key(`id`)
)ending=innoDB default charset=utf8

--建立表的時候沒有外來鍵關係
alter table `student`
add constraint `FK_gradeid` foreing key(`gradeid`) references `grade`(`gradeid`);

--alter table 表 add constraint 約束名 foreing key(作為外來鍵的列) references 那個表(哪個欄位)

以上的操作都是物理外來鍵,資料庫級別的外來鍵,我們不建議使用!(避免資料過多造成困擾)

最佳實現

  • 資料庫就是單純的表,只用來存資料,只有行(資料)和列(欄位)
  • 我們想使用多張表的資料,想使用外來鍵(程式去實現)

3.2、DML語言(全部記住)

**資料庫的意義:**資料儲存,資料管理

DML語言:資料操作語言

  • insert
  • update
  • dalete

3.3、新增

--插入語句(新增)
--insert into 表名([欄位名1,欄位名2,欄位名3])values('值1'),('值2'),('值3',....)
insert into `grade`(`gradename`) values('大四')

--由於主鍵自增我們可以省略(如果不寫表的欄位,他就會一一匹配)
insert into `grade` values('大三')

--一般寫插入語句,我們一定要資料和欄位一一對應!
insert into `grade`(`name`,`sex`,`pwd`) values('張三','男','123456'),('李四','女','987654')
--插入多個欄位
insert into `grade`(`gradename`) values('大二'),('大一')

注意事項:

  • 欄位和欄位之間使用 英文逗號 隔開
  • 欄位是可以省略的,但是後面的值必須要一一對應,不能少
  • 可以同時插入多條資料,values後面的值,需要使用‘**, ** ’隔開即可

3.4、修改

update 修改誰 (條件) set原來的值=新值
--修改學元員名字,帶了簡介
update `student` set `name`='zhanghui' where id=1

--不指定條件的情況下,會改動所有表
update `student` set `name`='zhangsan'

--修改多個屬性,逗號隔開
update `student` set `name`='zhanghui',`email`='[email protected]' where id=1

--語法:
--update 表名 set colnum_name=value,[colnum_name=value,....] where [條件]

條件:where字句運算子

操作符含義範圍結果
=等於5=6false
<>或!=不等於5<>6true
>
<
>=
<=
between…and…在某個範圍內[2,5]
and我和你&&5>1 and 1>2false
or我或你||5>1 or 1>2true
--通過多個條件定位資料
update `studet` set `name`='張三' where `name`='李四' and sex='女'

注意:

  • colnum_name是資料庫的列,儘量帶上’’
  • 條件,篩選的條件,如果沒有指定,則會修改所有的列
  • value,是一個具體的值,也可以是一個變數
  • 多個設定的屬性之間,使用英文逗號隔開

3.5、刪除

delete

語法:delete from 表名 [where 條件]

-- 刪除資料(避免這樣寫,會全部刪除)
delete from student

--刪除指定的資料
delete from `student` where id=1
truncate命令

作用:完全清空一個數據庫表,表的結構和索引約束不會變

--清空student表
truncate `student`
delete 和 truncate 區別
  • 相同點:都能刪除資料,都不會刪除表結構
  • 不同:
    • truncate 重新設定 自增列 計數器會歸零
    • truncate 不會影響事務
--測試 delete 和 truncate 區別
create table `test`(
    `id` int(4) not null auto_increment,
    `coll` varchar(20) not null,
    primary key(`id`)
)ending=innodb default charset=utf8

insert into `test`(`coll`) value('1'),('2'),('3')

delete from `test` --不會影響自增

truncate table `test` --自增會歸零

瞭解即可:delete刪除的問題,重啟資料庫,現象

  • InnoDB 自增列會從1開始(存在記憶體當中的,斷電即失)
  • MYISAM 繼續從上一個自增量開始(存在檔案中,不會丟失)

4、DQL查詢資料(最重點)

4.1、DQL

(Data Query Language:資料查詢語言)

  • 所有的查詢操作都用它 Select
  • 簡單的查詢,複雜的查詢他都能做~
  • 資料庫中最核心的語言,最重要的語句
  • 使用頻率最高的語句

4.2、指定查詢欄位

--查詢所有的學生     select 欄位 from 表
select * from student

--查詢指定欄位
select `StudentNo`,`StudentName` from student

--別名,給結果起一個名字 as  可以給欄位起別名,也可以給表起別名
select `StudentNo` as 學號,`StudentName` as 學生姓名 from student as s

--函式 concat(a,b)
select concat('姓名:',StudentName) as 新名字 from student

語法:select 欄位,…from 表

有時候,列的名字不是那麼的見名知意。我們起別名 as 欄位名 as 別名 表名 as 別名
去重 distinct

作用:去除select查詢出來的結果中重複的資料,重複資料只顯示一條

--查詢一下有哪些同學參加了考試,成績
select * from result --查詢全部的考試成績
select `StudentNo` from result --查詢有哪些同學參加了考試
select distnct `StudentNo` from result --發現重複資料,去重
資料庫的列(表示式)
select version() --查詢系統版本(函式)
select 100*3-1 as 計算結果 --用來計算(表示式)
select @@auto_increment_increment --查詢自增的步長(變數)

--學員考試成績+1分檢視
select `StudentNo`,`StudentResult`+1 as '提分後' from result

資料庫中的表示式:文字值,列,null,函式,計算表式,系統變數…

select 表示式 from 表

4.3、where條件字句

作用:檢索資料中符合條件的值

搜尋的條件由一個或者多個表示式組成!結果 布林值

邏輯運算子
運算子語法描述
and &&a and b a&&b邏輯與,兩個都為真,結果為真
or ||a or b a||b邏輯或,一個為真,則結果為真
not !not !a邏輯非,真為假,假為真

儘量使用英文字母

--===============================  where  ===============================
select studentNo,`StudentResulet` from result

--查詢考試成績在95~100分之間
select studentNo,`StudentResult` from result where StudentResult>=95 and StidentResult<=100

--and   &&
select studentNo,`StudentResult` from result where StudentResult>=95 && StidentResult<=100

--模糊查詢(區間)
select studentNo,`StudentResult` from result where StudentResult between 95 and 100

--除了1000號學生之外的學生的成績
select studentNo,`StudentResult` from result where studentNo!=1000

-- !=   not
select studentNo,`StudentResult` from result where not studentNo=1000
模糊查詢:比較運算子
運算子語法描述
is nulla is null如果操作符為null,結果為真
is not nulla is not null如果操作符不為null,結果為真
betweena between b and c若a在b和c之間,則結果為真
likea like bSQL匹配,如果a匹配b,則結果為真
ina in(a1,a2,a3)假設a在a1,或者a2…其中的某一個值中,結果為真
--====================================  模糊查詢  ==================================
--查詢姓劉的同學
--like結合 %(代表0到任意個字元)     (一個字元)
select `StudentNo`,`StudentName` from `student` where StudentName like '劉%'

--查詢姓劉的同學,名字後面只有一個字的
select `StudentNo`,`StudentName` from `student` where StudentName like '劉_'

--查詢姓劉的同學,名字後面只有兩個字的
select `StudentNo`,`StudentName` from `student` where StudentName like '劉__'

--查詢名字中有嘉字的同學 %嘉%
select `StudentNo`,`StudentName` from `student` where StudentName like '%嘉%'

--============ in  =============
--查詢1001,1002,1003號學員
select `StudentNo`,`StudentName` from `student` where StudentName in (1001,1002,1003)

--查詢在北京的學生
select `StudentNo`,`StudentName` from `student` where `Address` in ('安徽','河南洛陽')

--============null    not null===============
--查詢地址為空的學生 null ''
select `StudentNo`,`StudentName` from `student` where address='' or address is null

--查詢有出生日期的學生   不為空
select `StudentNo`,`StudentName` from `student` where `BornData` is not null

4.4、聯表查詢

join

在這裡插入圖片描述

--=================================  聯表查詢 join  ======================================
--查詢參加了考試的同學(學號,姓名,科目編號,分數)
select * from student
select * from result

/*思路
1.分析需求,分析查詢的欄位來自哪些表(連線查詢)
2.確定使用哪種連線查詢? 7種
確定交叉點(這兩個表中哪個資料是相同的)
判斷的條件:學生表中的 studentNo = 成績表 studentNo
*/

-- join (練接的表) on (判斷條件) 連線查詢
-- where  等值查詢
select s.studentNo,studentName,subjectNo,studentResult
from student as s
inner join result as r
where s.studentNo=r.studentNo


select s.studentNo,studentName,subjectNo,studentResult
from student as s
inner join result as r
on s.studentNo=r.studentNo

--right join
select s.studentNo,studentName,subjectNo,studentResult
from student as s
right join result as r
on s.studentNo=r.studentNo

--left join
select s.studentNo,studentName,subjectNo,studentResult
from student as s
left join result as r
on s.studentNo=r.studentNo


--查詢缺考的同學
select s.studentNo,studentName,subjectNo,studentResult
from student as s
left join result as r
on s.studentNo=r.studentNo
where StudentResult is null


--思考題(查詢參加了考試的同學資訊:學號,學生姓名,科目名,分數)
/*思路
1.分析需求,分析查詢的欄位來自哪些表,student,result,subject(連線查詢)
2.確定使用哪種連線查詢? 7種
確定交叉點(這兩個表中哪個資料是相同的)
判斷的條件:學生表中的 studentNo = 成績表 studentNo
*/

select s.studentNo,studentName,subjectNo,studentResult
from student as s
right join result as r
on r.studentNo=s.studentNo
inner join subject as sub
on r.studentNo=sub.studentNo



--我要查詢哪些資料 select...
--從哪幾個表中查 from 表 XXX join 連線的表 on 交叉條件
--假設存在一種多張表查詢,慢慢來,先查詢兩張表然後再慢慢增加

--from a left Join b
--from a right Join b
自連線(瞭解)

自己表和自己的表連線,核心:一張表拆為兩張一樣的表即可

父類

categoryidcategoryName
2資訊科技
3軟體開發
5美術設計

子類

pidcategoryidcategoryName
34資料庫
28辦公資訊
36web開發
57美術設計

操作:查詢父類對應的子類關係

父類子類
資訊科技辦公資訊
軟體開發資料庫
軟體開發web開發
美術設計ps技術
-- 查詢父子資訊

select a.`categoryName` as '父欄目',b.`categoryName` as '子欄目'
from `category` as a,`category` as b
where a.`categoryid`=b.`pid`

--查詢學員所屬的年級(學號,學生的姓名,年級名稱)
select studentNo,studentName,`GradeName`
from student s
inner join `grade` g
on s.`GradeID`=g.`GradeID`


--查詢科目所屬的年級(科目名稱,年級名稱)
select `SubjectName`,`GradeName`
from `subject` sub
inner join `grade` g
on sub.`GradeID`=g.`GradeID`


--思考題(查詢參加了資料庫結構-1考試的同學的資訊:學號,學生姓名,科目名,分數)
select s.`StudentNo`,`StudentName`,s.`SubjectName`,`StudentResult`
from student s
inner join `result` r
on s.`StudentNo`=r.`StudentNo`
inner `subject` sub
on r.`SubjectNo`=sub.`SubjectNo`
where subjectName='資料庫結構-1'

4.5、分頁和排序

排序
-- ================================  分頁 limit 和排序 order  ===============================

--排序:升序 asc ,降序desc
--order by 通過哪個欄位排序,怎麼排
--查詢的結果根據 成績降序 排序
select s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
from student s
inner join `result` r
on s.`StudentNo`=sub.`StudentNo`
where subjectName='資料庫結構-1'
order by StudentResult asc
分頁
--100萬
--為什麼要分頁
--緩解資料庫壓力,給人的體驗更好,瀑布流

--分頁,每頁只顯示五條資料
--語法:limit 起始值,頁面的大小
select s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
from student s
inner join `result` r
on s.`StudentNo`=sub.`StudentNo`
where subjectName='資料庫結構-1'
order by StudentResult asc
limit 0,5

--第一頁  limit 0,5
--第二頁  limit 5,5
--第三頁  limit 10,5
--第N頁  limit (n-1)*pageSize,pageSize
-- 【pageSize:頁面大小】
--【(n-1)*pageSize:起始值】
--【n:當前頁】
--【資料總數/頁面大小=總頁數】

語法:limit(查詢起始下標,pageSize)

--思考
--查詢java第一學年 課程成績排名前十的學生,並且分數要大於80的學生資訊(學號,姓名,課程名稱,分數)
select s.`StudentNO`,`StudentName`,`SubjectName`,`StudentReshult`
from `student` s
inner join `result` r
on s.StudentNo=r.StudentNo
inner join `subject` sub
on r.`SubjectNo`=sub.`SubjectNo`
where sub.`SubjectName`='java第一學年' and StudentResult>80
order by StudentResult desc
limit 0,10

4.6、子查詢

where(這個值是計算出來的)

本質:在where語句語句中巢狀一個子查詢語句

--============================  where  ===========================

--1、查詢資料庫結構-1 的所有考試結果(學號,科目編號,成績),降序排列
--方式一:使用連線查詢
select `StudentNO`,r.`SubjectNo`,`SubjectResult`
from `result` r
inner join `subject` sub
on r.SubjectNo=sub.SubjectNo
where SubjectName='資料庫結構-1'
order by StudentResult desc

--方式二:使用子查詢(由裡及外)
select `StudentNO`,r.`SubjectNo`,`SubjectResult`
from `result`
where SubjectNo=(
    select SubjectNo from `subject`
    where SubjectName='資料庫結構-1'
)
order by StudentResult desc


--分數不小於80分的學生的學號和姓名
select distinct s.`StudentNo`,`StudentName`
from student s
inner join `result` r
on s.`StudentNo`=r.`StudentNo`
where `SubjectResult`>=80

--查詢課程為高等數學-2 且分數不小於80分的同學的學號和姓名
select distinct s.`StudentNo`,`StudentName`
from student s
inner join `result` r
on s.`StudentNo`=r.`StudentNo`
inner join 'subject' sub
on r.`SubjectNo`=sub.`SubjectNo`
where `SubjectName`='高等數學-2' and StudentResult>=80

--在這個基礎上增加一個科目, 高等數學-2
--查詢 高等數學-2 的編號
select distinct s.`StudentNo`,`StudentName`
from student s
inner join `result` r
on s.`StudentNo`=r.`StudentNo`
where `SubjectResult`>=80 and `SubjectNo`=(
    select `SubjectNo` from `subject`
    where `SubjectName`='高等數學-2'
)

--再改造(由裡及外)
select `StudentNo`,`StudentName` from `student` where `StudentNo` in(
    select `StudentNo` from `result` where `StudentResult`>=80 and `SubjectNo`(
        select `SubjectNo` from `subject` where `SubjectName`='高等數學-2'
    )
)

4.7、分組和過濾

--查詢不同課程的平均分,最高分,最低分,平均分大於80
--核心:(根據不同的課程分組)
select SubjectName,avg(StudentResult) as 平均分,max(StudentResult) as 最高分,min(StudentResult) as 最低分
from `result` r
inner join 'subject' sub
on r.`SubjectNo`=sub.`SubjectNo`
group by r.`SubjectNo` --通過什麼來分組
having 平均分 > 80

5、MySQL函式

5.1、常用函式

-- ============================ 常用函式  =========================

--數學運算
select abs(-8)  --絕對值
select ceiling(9.4)  --向上取整
select floor(9.4)  --向下取整
select rand()  --返回一個1~0之間的隨機數
select sign(10)  --判斷一個數的符號  0-0   負數返回-1,正數返回 1

--字串函式
select char_length()  --字串長度
select concat() --拼接字元創
select insert()  --查詢,替換(從某個位置開始替換某個長度)
select lower()  --小寫字母
select upper()  --大寫字母
select instr()  --返回第一次出現的子串的索引
select replace()  --替換出現的指定字串
select substr()  --返回指定的字串(源字串,擷取的位置,擷取的長度)
select reverse()  --反正字串

--查詢姓 周的同學,名字  紂
select replace(`StudentName`,'周','紂') from `student`
where `StudentName` like '周%'

--時間和日期函式(記住)
select current_date()  --獲取當前時期
select curdate()  --獲取當前日期
select now()  --獲取當前時間
select localtime()  --本地時間
select sysdate()  -- 系統時間

select year(now())
select month(now())
select day(now())
select hour(now())
select minute(now())
select second(now())

--系統
select system_user()
select user()
select version()

5.2、聚合函式(常用)

函式名稱描述
count()計數
sum()求和
avg()平均值
max()最大值
min()最小值
--  ============================  聚合函式  =========================
-- 都能夠統計 表中的資料(想查詢一個表中有多少個記錄,就使用這個count())
select count(StudentName) from student  --count(欄位),會忽略所有的null值
select count(*) from student  --count(*),不會忽略null值  本質  計算行數
select count(1) from result  --count(1),不會忽略null值  本質  計算行數

select sum(`StudentResult`) as 總和 result
select avg(`StudentResult`) as 平均分 result
select max(`StudentResult`) as 最高分 result
select min(`StudentResult`) as 最低分 result

5.3、資料庫級別的MD5加密(擴充套件)

什麼是MD5?

主要增強演算法複雜性和不可逆性

MD5不可逆,具體的值的md5是一樣的

MD5破解網站的原理,背後有一個字典,MD5加密後的值,加密前的值

-- =====================測試MD5 加密========================

create table `testmd5`(
    `id` int(4) not null,
    `name` varchar(20) not null,
    `pwd` varchar(50) not null,
    primary key('id')
)ending=innodb default charset=utf8

--明文密碼
insert into testmd5 value(1,'zhangsan','123456'),(2,'lisi','123456'),(3,'wangwu','123456')
--加密
update testmd5 set pwd=MD5(pwd) where id=1
update testmd5 set pwd=MD5(pwd) --加密全部的密碼

--插入的時候加密
insert into testmd5 value(4,'xiaoming',MD5('123456'))

--如何校驗:將使用者傳遞進來的密碼,進行md5加密,然後對比加密後的值
select * from testmd5 where `name`='xiaoming' and pwd=MD5('123456')

6、事務

6.1、什麼是事務

要嗎成功,要麼失敗

——————

1、SQL執行 A 給 B 轉賬 A 1000 —>200 B 200

2、SQL執行 B收到A的錢 A 800 —> B 400

——————

將一組SQL放在一個批次中執行

事務原則:ACID原則 原子性 一致性 隔離性 永續性 (髒讀,幻讀…)

參考部落格連結:https://blog.csdn.net/dengjili/article/details/82468576

原子性(Atomicity)

要麼都成功,要麼都失敗

一致性(Consistency)

事務前後的資料晚自習要保證一致

永續性(Durability)

事務一旦提交則不可逆,被持久化到資料庫中!

隔離性(Isolation)

事務的隔離性是多個使用者併發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作資料所幹擾,多個併發事務之間要相互隔離。

隔離所導致的一些問題
髒讀:

指一個事務讀取了另外一個事務未提交的資料。

不可重複讀:

在一個事務內讀取表中的某一行資料,多次讀取結果不同。(這個不一定是錯誤,只是某些場合不對)

幻讀

是指在一個事務內讀取到了別的事務插入的資料,導致前後讀取不一致。
(一般是行影響,多了一行)

執行事務
--===========================  事務  ===========================

--mysql 是預設開啟資料庫自動提交的
set autocommit = 0  /* 關閉 */
set autocommit = 1  /* 開啟(預設的)*/

--手動處理事務
set autocommit = 0 --關閉自動提交
--事務開啟
start transaction --標記一個書屋的開始,從這個之後的sql都在同一個事務內

insert XX
insert XX

--提交:持久化(成功!)
commit
--回滾:回到原來的樣子(失敗!)
rollback
--事務結束
set autocommit = 1  --開啟自動提交

--瞭解
savepoint 儲存點名  --設定一個事務的儲存點
rollback to savepoint 儲存點名  --回滾到儲存點
release savepoint 儲存點名  --撤銷儲存點
模擬場景
--轉賬
create datebase shop character set utf8 collate utf8_general_ci
use shop

create table `account`(
    `id` int(3) not null auto_increment,
    `name` varchar(30) not null,
    `money` decimal(9,2) not null,
    primary key(`id`)
)ending=innodb default charset=utf8

insert into account(`name`,`money`)
value('A',2000.00),('B',10000.00)

-- 模擬轉賬:事務
set autocommit = 0; --關閉自動提交
start transaction --開啟一個事務(一組事務)

update account set money=money-500 where `name`='A' --A減500
update account set money=money+500 where `name`='B' --B加500

commit; --提交事務,就持久化了!
rollback; --回滾

set autocommit = 1;  --恢復預設值

7、索引

MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取資料的資料結構

提取句子主幹,就可以得到索引的本質:索引是資料結構。

7.1、索引的分類

在一個表中,主鍵索引只能有一個,唯一索引可以有多個

  • 主鍵索引(primary key)
    • 唯一的標識,主鍵不可重複,只能有一個列作為主鍵
  • 唯一索引(unique key)
    • 避免重複列的出現,唯一索引可以重複,多個列都闊以標識為唯一索引
  • 常規索引(key/index)
    • 預設的,index,key關鍵字來設定
  • 全文索引(fulltext)
    • 在特定的資料庫引擎下才有,MYISAM
    • 快速定位資料

基礎語法

--索引的使用
--1、在建立表的時候給欄位增加索引
--2建立完畢後,增加索引

--顯示所有的索引資訊
show index from student

--增加一個全文索引(索引名)  列名
alter table school.student add fulltext index `studentname`(`studentname`);

--explain 分析sql執行的狀況

explain select * from student; --非全文索引

explain select * from student where match(studentname) against('劉');

7.2、測試索引

-- 插入100萬資料
delimiter $$  --寫函式之間必須要寫,標誌

create function mock_data()
returns int
begin
   declare num int default 1000000;
   declare i int default 0;
   while i<num do
         -- 插入語句
         insert into app_user(`name`,`email`,`gender`,`password`,``age) value(concat('使用者',i),'[email protected]',concat('18',floor(rand()*((999999999-100000000)+1000000000))),floor(rand()*2,uuid(),floor(rand()*100))
         set i=i+1;
   end while;
   return i;
end;

select * from app_user where `name`='使用者9999'; --0.993sec
                                                                              
explain select * from app_user where `name`='使用者9999';
select * from student

--id_表名_欄位名
--create index 索引名 on 表(欄位)  
create index id_app_user_name on app_user(`name`); 
select * from app_user where `name`='使用者9999'; --0.001sec
explain select * from app_user where `name`='使用者9999';

索引在小資料量的時候,用處不大,但是在大資料的時候,區別十分明顯~

7.3、索引原則

  • 索引不是越多越好
  • 不要對程序變動資料加索引
  • 小資料量的表不要加索引
  • 索引一般加在常用來查詢的欄位上
索引的資料結構

Hash 型別的索引

Btree:InnoDB的預設資料結構~

閱讀:http://blog.codinglabs.org/articles/theory-of-mysql-index.html

8、許可權管理

8.1、使用者管理

SQL yog 視覺化管理
SQL命令操作

使用者表:mysql.user

本質:讀這張表進行增刪改查

--建立使用者 create user 使用者名稱 identified by '密碼'
create user zhangsan identified by '123456'

--修改密碼(修改當前使用者密碼)
set password = password('123456')

--修改密碼(修改指定使用者密碼)
set password for zhangsan = password('123456')

--重新命名  rename user 原來名字 to 新的名字
rename user zhangsan to zhangsan1

--使用者授權 all privileges 全部的許可權  , 庫.表
--all privileges 除了給別人授權,其他的都能幹
grant all privileges on *.* to zhangsan1

--查詢許可權
show grant for zhangsan1  --檢視指定使用者的許可權
show grant for root@localhost 

--root 使用者的許可權:grant all privileges on *.* to 'root@localhost' with grant option

--撤銷許可權  revoke 哪些許可權 , 在哪個庫撤銷 , 給誰撤銷
revoke all privileges on *.* from zhangsan1

--刪除使用者
drop user zhangsan

8.2、資料庫備份

為什麼要備份

  • 保證重要的資料不丟失
  • 資料轉移

MySQL資料庫備份的方式

  • 直接拷貝物理檔案

  • 在SQLyog這種視覺化工具中手動匯出

  • 使用命令列匯出 mysqldump 命令列使用

    # mysql -h 主機  -u 使用者名稱  -p 密碼  資料庫  表名  > 物理磁碟位置/檔名
    mysql -hlocalhost -uroot -p123456 school student >D:/a.sql
    
    # mysql -h 主機  -u 使用者名稱  -p 密碼  資料庫  表1 表2 表3  > 物理磁碟位置/檔名
    mysql -hlocalhost -uroot -p123456 school student result >D:/b.sql
    
    # mysql -h 主機  -u 使用者名稱  -p 密碼  資料庫  > 物理磁碟位置/檔名
    mysql -hlocalhost -uroot -p123456 school >D:/c.sql
    
    # 匯入
    # 登入的情況下,切換到指定的資料庫
    # source 備份檔案
    source d/:a.sql
    
    mysql -u使用者名稱 -p密碼 庫名< 備份檔案
    

假設你要備份資料庫,防止資料丟失。

把資料庫給朋友!sql檔案給別人即可!

9、規範資料庫設計

9.1、為什麼需要設計

但實際比較複雜的時候,我們就需要設計了

糟糕的資料庫設計:

  • 資料冗餘,浪費空間
  • 資料庫插入和刪除都會麻煩、異常【遮蔽使用物理外來鍵】
  • 程式的效能差

良好的資料庫設計

  • 節省記憶體空間
  • 保證資料庫的完整性
  • 方便我們開發系統

軟體開發者,關於資料庫的設計

  • 分析需求:分析業務和需要處理的資料庫的需求
  • 概要設計:設計關係圖 E-R圖

設計資料庫的步驟:(個人部落格)

  • 收集資訊,分析需求
    • 使用者表(使用者登入登出,使用者的個人資訊,寫部落格,建立分類)
    • 分類表(文章分類,誰建立的)
    • 文章表(文章的資訊)
    • 友連結串列(友鏈資訊)
    • 自定義表(系統資訊,某個關鍵的字,或者一些主欄位) key:value
    • 說說表(發表心情 … id … content … create_time)
  • 標識實體(把需求落地到每個欄位)
  • 標識實體之間的關係
    • 寫部落格:user–>blog
    • 建立分類:user–>category
    • 關注:user–>user
    • 友鏈:links
    • 評論:user–>user-blog

9.2、三大正規化

為什麼需要資料規範化

  • 資訊重複
  • 更新異常
  • 插入異常
    • 無法正常顯示資訊
  • 刪除異常
    • 丟失有效資訊
三大正規化(瞭解)

第一正規化(1NF)

原子性:保證每一列不可再分

第二正規化(2NF)

前提:滿足第一正規化

每張表只描述一件事情

第三正規化(3NF)

前提:滿足第一正規化和第二正規化

第三正規化需要確保資料庫表中的每一列資料都和主鍵直接相關,而不能間接相關。

(規範資料庫的設計)

規範性 和 效能的問題

關聯查詢的表不得超過三張表

  • 考慮商業化的需求和目標,(成本,使用者體驗!)資料庫的效能更加重要
  • 在規範效能的問題的時候,需要適當考慮一下 規範性!
  • 故意給某些表增加一些冗餘的欄位。(從多表查詢變為但表查詢)
  • 故意增加一些計算列(從大資料量降低為小資料量的查詢:索引)

10、JDBC(重點)

10.1、資料庫驅動

驅動:音效卡,顯示卡,資料庫

我們的程式會通過 資料庫 驅動,和資料庫打交道!

10.2、JDBC

SUN公司為了簡化開發人員的(對資料庫的統一)操作,提供了一個(java操作資料庫的)規範,俗稱JDBC

這些規範的實現由具體的廠商去做~

對於開發人員來說,我們只需要掌握JDBC介面的操作即可!

java.sql

javax.sql

還需要匯入一個數據庫驅動包 mysql-connector-java-5.1.47.jar

10.3、第一個JDBC程式

建立測試資料庫
create database jdbcStudy character set utf8 collate utf8_general_ci

use jdbcStudey

create table users(
    id int primary key
    name varchar(40),
    password varchar(40)
    email varchar(60);
    birthday date
);

insert into users(id,name,password,email,birthday)
values(1,'zhangsan','123456','[email protected]','1998-06-12'),
(2,'lisi','123456','[email protected]','1998-04-12'),
(3,'wangwu','123456','[email protected]','1997-06-12'),

1、建立一個普通專案

2、匯入資料庫驅動

3、編寫測試程式碼

public class JdbcFirstDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.載入驅動
        Class.forName("com.zhang.jdbc.Driver");//固定寫法,載入驅動

        //2.使用者資訊和url
        //useUnicode=true&characterEncoding=utf8&useSSl=true
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSl=true";
        String username = "root";
        String password = "123456";

        //3.連線成功,資料庫物件  connection 代表資料庫
        Connection connection = DriverManager.getConnection(url, username, password);

        //4.執行SQL的物件  statement 執行sql物件
        Statement statement = connection.createStatement();

        //5.執行SQL的物件 去 執行SQL,可能存在結果,檢視返回結果
        String sql = "select * from users";

        ResultSet resultSet = statement.executeQuery(sql); //返回結果集,結果集中封裝了我們全部的查詢出來的結果

        while(resultSet.next()){
            System.out.println("id=" + resultSet.getObject("id"));
            System.out.println("name=" + resultSet.getObject("NAME"));
            System.out.println("password=" + resultSet.getObject("PASSWORD"));
            System.out.println("email=" + resultSet.getObject("email"));
            System.out.println("birthday=" + resultSet.getObject("birthday"));
        }

        //6.釋放連線
        resultSet.close();
        statement.close();
        connection.close();

    }
}

步驟總結:

1、載入驅動

2、連線資料庫 DriverManager

3、獲得執行sql的物件 Statement

4、獲得返回的結果集

5、釋放連線

DriverManager
//DriverManager.registerDriver(new com.zhang.jdbc.Driver());
Class.forName("com.zhang.jdbc.Driver");//固定寫法,載入驅動
Connection connection = DriverManager.getConnection(url, username, password);

//connection 代表資料庫
//資料庫設定自動提交
//事務提交
//事務回滾

connection.commit();
connection.rollback();
connection.setAutoCommit();
URL
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSl=true";

//mysql -- 3306
//jdbc:mysql://主機地址:埠號/資料庫名?引數1&引數2&引數3

//oracle -- 1521
//jdbc:oracle:thin:@localhost:1521:sid
Statement 執行SQL的物件 PrepareStatement
String sql = "select * from users";//編寫SQL

statement.executeQuery();//查詢操作,返回ResultSet
statement.execute();//執行任何SQL
statement.executeUpdate();//更新,插入,刪除 都是用這個,返回一個受影響的行數
ResultSet 查詢的結果集:封裝了所有的查詢結果

獲得指定的型別

resultSet.getObject();//在不知道列型別的情況下使用
resultSet.getInt();
//如果知道列的型別就使用指定的型別
resultSet.getString();
resultSet.getFloat();
resultSet.getDouble();
resultSet.getDate();
....

遍歷,指標

resultSet.beforeFirst();//移動到最前面
resultSet.afterLast();//移動到最後面
resultSet.next();//移動到下一資料
resultSet.previous();//移動到前一行
resultSet.absolute(raw);//移動到指定行
釋放資源
resultSet.close();
statement.close();
connection.close();

10.4statement物件

jdbc中的statement物件用於向資料庫傳送SQL語句,想完成對資料庫的增刪改查,只需要通過這個物件向資料庫傳送增刪改查語句即可

Statement物件的executeUpdate方法,用於向資料庫傳送增、刪、改的sql語句,executeUpdate執行完成後,將會返回一個整數(即增刪改語句導致了資料庫幾行資料發生了變化)。

Statement.executeQuery方法用於向資料庫傳送查詢語句,executeQuery方法返回代表查詢結果的ResultSet物件。

CRUD操作-crate

使用executeUpdate(String sql)方法完成資料的新增操作,示例操作:

Statement st = com.createStatement();
String sql = "insert into user(...) value(...)";
int num = st.executeUpdate(sql);
if(num>0){
    System.out.println("插入成功!!!");
}
CRUD操作-delete
Statement st = com.createStatement();
String sql = "delete from user where id=1";
int num = st.executeUpdate(sql);
if(num>0){
    System.out.println("刪除成功!!!");
}
CRUD操作-update
Statement st = com.createStatement();
String sql = "update user set name='' where name=''";
int num = st.executeUpdate(sql);
if(num>0){
    System.out.println("修改成功!!!");
}
CRUD操作-read

使用executeQuery(String sql)方法完成資料的查詢操作,示例操作:

Statement st = com.createStatement();
String sql = "select * from user where id=1";
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
    //根據獲得列的資料型別,分別呼叫rs的相應方法對映到java物件中
}
程式碼實現

1、提取工具類

package com.zhang.lesson02.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {

    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;

    static{
        try{
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(in);

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //驅動只用載入一次
            Class.forName(driver);

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //獲取連線
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    //釋放連線資源
    public static void release(Connection con, Statement st, ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(con!=null){
            try {
                con.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

2、編寫增刪改的方法,EXEcuteUpdate

package com.zhang.lesson02.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestInsert {
    public static void main(String[] args) {

        Connection con = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            Connection connection = JdbcUtils.getConnection();//獲取資料庫連線
            st = con.createStatement();//獲取SQL的執行物件
            String sql = "insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`)"+
                    "values(4,'zhangsan','123456','[email protected]','1998-02-05')";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("插入成功!!!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        JdbcUtils.release(con,st,rs);
    }
}
package com.zhang.lesson02.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestDelete {
    public static void main(String[] args) {

        Connection con = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            Connection connection = JdbcUtils.getConnection();//獲取資料庫連線
            st = con.createStatement();//獲取SQL的執行物件
            String sql = "delete from users where id = 4";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("刪除成功!!!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        JdbcUtils.release(con,st,rs);
    }
}
package com.zhang.lesson02.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestUpdate {
    public static void main(String[] args) {

        Connection con = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            Connection connection = JdbcUtils.getConnection();//獲取資料庫連線
            st = con.createStatement();//獲取SQL的執行物件
            String sql = "update users ser `NAME`='zhangsan',`email`='[email protected]' while id=1";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("更新成功!!!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        JdbcUtils.release(con,st,rs);
    }
}

3、查詢 executeQuery

package com.zhang.lesson02.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestSelect {
    public static void main(String[] args){

        Connection con = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            con = JdbcUtils.getConnection();
            st = con.createStatement();
            //SQl
            String sql = "select * from users where id=1";
            rs = st.executeQuery(sql);//查詢
            if(rs.next()){
                System.out.println(rs.getString("NAME"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,rs);
        }
    }
}
SQL注入的問題

sql存在漏洞,會被攻擊導致資料洩露 SQL會被拼接 or

package com.zhang.lesson02.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class SQl注入 {
    
    public static void main(String[] args) {
        //login("zhangsan","123456");
        login(" 'or '1=1"," ' or '1=1");
    }

    public static void login(String username,String passwprd){
        Connection con = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            con = JdbcUtils.getConnection();
            st = con.createStatement();
            //SQl
            //select * from users where `NAME`='zhangsan' and `password`='123456';
            //select * from users where `NAME`=' 'or '1=1' and `password`=' 'or '1=1';
            String sql = "select * from users where `NAME`='"+username+"' and `password`='"+passwprd+"'";
            rs = st.executeQuery(sql);//查詢
            if(rs.next()){
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("password"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,rs);
        }
    }
}

10.5、PreparedStatement物件

PreparedStatement可以預防SQL注入。效率更好!

1、新增

package com.zhang.lesson03;

import com.zhang.lesson01.JdbcFirstDemo;
import com.zhang.lesson02.utils.JdbcUtils;
import java.util.Date;
import java.sql.*;

public class TestInsert {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement pst = null;

        try {
            con = JdbcUtils.getConnection();
            //區別
            //使用?佔位符代替引數
            String sql = "insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`) values(?,?,?,?,?)";
            pst = con.prepareStatement(sql);//預編譯SQl,先寫SQl,然後不執行
            //手動給引數賦值
            pst.setInt(1,4);
            pst.setString(2,"zhangsan");
            pst.setString(3,"123456");
            pst.setString(4,"[email protected]");
            //注意點:sql.Date    資料庫     java.sql.Date
            //      util.Date    java     new Date().getTime()   獲得時間戳
            pst.setDate(5,new java.sql.Date(new Date().getTime()));
            //執行
            int i = pst.executeUpdate();
            if(i>0){
                System.out.println("插入成功");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally{
            JdbcUtils.release(con,pst,null);
        }
    }
}

2、刪除

package com.zhang.lesson03;

import com.zhang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;

public class TestDelete {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement pst = null;

        try {
            con = JdbcUtils.getConnection();
            //區別
            //使用?佔位符代替引數
            String sql = "delete from users where id=?";
            pst = con.prepareStatement(sql);//預編譯SQl,先寫SQl,然後不執行
            //手動給引數賦值
            pst.setInt(1,4);
            //執行
            int i = pst.executeUpdate();
            if(i>0){
                System.out.println("刪除成功");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally{
            JdbcUtils.release(con,pst,null);
        }
    }
}

3、更新

package com.zhang.lesson03;

import com.zhang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;

public class TestUpdate {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement pst = null;

        try {
            con = JdbcUtils.getConnection();
            //區別
            //使用?佔位符代替引數
            String sql = "update users set `NAME`=?  where id=?;";
            pst = con.prepareStatement(sql);//預編譯SQl,先寫SQl,然後不執行
            //手動給引數賦值
            pst.setString(1,"張三");
            pst.setInt(2,1);
            //執行
            int i = pst.executeUpdate();
            if(i>0){
                System.out.println("更新成功");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally{
            JdbcUtils.release(con,pst,null);
        }
    }
}

4、查詢

package com.zhang.lesson03;

import com.zhang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestSelect {
    public static void main(String[] args) {

        Connection con = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            con = JdbcUtils.getConnection();

            String sql = "select * from users where id=?;";

            pst = con.prepareStatement(sql);

            pst.setInt(1,1);

            rs = pst.executeQuery();

            if(rs.next()){
                System.out.println(rs.getString("NAME"));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,pst,rs);
        }
    }
}

5、防止SQL注入

package com.zhang.lesson03;

import com.zhang.lesson02.utils.JdbcUtils;
import java.sql.*;

public class SQl注入 {
    public static void main(String[] args) {
        //login("zhangsan","123456");
        login("'' or 1=1","'' or 1=1");
    }

    public static void login(String username,String passwprd){

        Connection con = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            con = JdbcUtils.getConnection();
            //PreparedStatement 防止SQL注入的本質,把傳遞進來的引數當做字元
            //假設其中存在轉義字元,比如說‘ 會被直接轉義
            String sql = "select * from users where `NAME`=? and `password`=?";
            pst = con.prepareStatement(sql);

            pst.setString(1,username);
            pst.setString(2,passwprd);

            rs = pst.executeQuery();
            if(rs.next()){
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("password"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,rs);
        }
    }
}

10.7、使用IDEA連線資料庫

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-qO38Pb7R-1606715263427)(C:\Users\asus\AppData\Roaming\Typora\typora-user-images\image-20201126135253568.png)]

10.8、JDBC操作事務

要麼都成功,要麼都失敗

ACID原則

原子性:要麼全部完成,要麼都不完成

一致性:總數不變

隔離性:多個事務互不干擾

永續性:一旦提交不可逆,持久化到資料庫了

隔離性的問題:

髒讀:一個事務讀取了另一個沒有提交的事務

不可重複的;在同一個事務內,重複讀取表中的資料,表資料發生了改變

幻讀(虛讀):在一個事務內,讀取了別人插入的資料,導致前後讀出來結果不一致

程式碼實現

1、開啟事務 con.setAutoCommit(false)

2、一組業務執行完畢,提交事務

3、可以再catch語句中顯示的定義回滾語句,但預設失敗就會回滾

package com.zhang.lesson04;

import com.zhang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestTransaction {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            con = JdbcUtils.getConnection();
            //關閉資料庫自動提交,自動會開啟事務
            con.setAutoCommit(false);//開啟事務
            
            String sql1 = "update account set money=money-100 where name=A;";
            pst = con.prepareStatement(sql1);
            pst.executeUpdate();

            int x = 1/0;

            String sql2 = "update account set money=money+100 where name=b;";
            pst = con.prepareStatement(sql2);

            con.commit();
            System.out.println("成功!");
        } catch (SQLException throwables) {
            //如果失敗,預設回滾
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,pst,rs);
        }
    }
}

10.9、資料庫連線池

資料庫連線----執行完畢----釋放

連線—釋放 十分浪費資源

池化技術:準備一些預先的資源,過來就連線預先準備好的

--------開門—業務員 : 等待—服務----

最小連線數:10

最大連線數:15業務最高承載上限

等待超時:100ms

編寫連線池,實現一個介面 DataSource

開源資料來源實現(拿來即用)

DBCP

C3P0

Druid:阿里巴巴

使用了這些資料庫連線池之後,我們在專案開發中就不需要編寫連線資料庫的程式碼了!

DBCP

需要用到的jar包

commons-dbcp-1.4、commons-pool-1.6

C3P0

需要匯入的jar包

c3p0-0.9.5.5、mchange-commons-java-0.2.19

結論

無論使用什麼資料來源,本質還是一樣的,DataSource介面不會變,方法就不會變

Druid

stem.out.println(rs.getString(“NAME”));
System.out.println(rs.getString(“password”));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(con,st,rs);
}
}
}




### 10.7、使用IDEA連線資料庫

[外鏈圖片轉存中...(img-qO38Pb7R-1606715263427)]





### 10.8、JDBC操作事務

**要麼都成功,要麼都失敗**

> ##### ACID原則

原子性:要麼全部完成,要麼都不完成

一致性:總數不變

隔離性:多個事務互不干擾

永續性:一旦提交不可逆,持久化到資料庫了



隔離性的問題:

髒讀:一個事務讀取了另一個沒有提交的事務

不可重複的;在同一個事務內,重複讀取表中的資料,表資料發生了改變

幻讀(虛讀):在一個事務內,讀取了別人插入的資料,導致前後讀出來結果不一致



> ##### 程式碼實現

1、開啟事務  **con.setAutoCommit(false)**

2、一組業務執行完畢,提交事務

3、可以再catch語句中顯示的定義回滾語句,但預設失敗就會回滾

```java
package com.zhang.lesson04;

import com.zhang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestTransaction {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            con = JdbcUtils.getConnection();
            //關閉資料庫自動提交,自動會開啟事務
            con.setAutoCommit(false);//開啟事務
            
            String sql1 = "update account set money=money-100 where name=A;";
            pst = con.prepareStatement(sql1);
            pst.executeUpdate();

            int x = 1/0;

            String sql2 = "update account set money=money+100 where name=b;";
            pst = con.prepareStatement(sql2);

            con.commit();
            System.out.println("成功!");
        } catch (SQLException throwables) {
            //如果失敗,預設回滾
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,pst,rs);
        }
    }
}

10.9、資料庫連線池

資料庫連線----執行完畢----釋放

連線—釋放 十分浪費資源

池化技術:準備一些預先的資源,過來就連線預先準備好的

--------開門—業務員 : 等待—服務----

最小連線數:10

最大連線數:15業務最高承載上限

等待超時:100ms

編寫連線池,實現一個介面 DataSource

開源資料來源實現(拿來即用)

DBCP

C3P0

Druid:阿里巴巴

使用了這些資料庫連線池之後,我們在專案開發中就不需要編寫連線資料庫的程式碼了!

DBCP

需要用到的jar包

commons-dbcp-1.4、commons-pool-1.6

C3P0

需要匯入的jar包

c3p0-0.9.5.5、mchange-commons-java-0.2.19

結論

無論使用什麼資料來源,本質還是一樣的,DataSource介面不會變,方法就不會變

Druid

Apache