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 早些年使用
*/
MYISAM | INNODB | |
---|---|---|
事務支援 | 不支援 | 支援 |
資料行鎖定 | 不支援 | 支援 |
外來鍵 | 不支援 | 支援 |
全文索引 | 支援 | 不支援 |
表空間大小 | 較小 | 較大,約為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=6 | false |
<>或!= | 不等於 | 5<>6 | true |
> | |||
< | |||
>= | |||
<= | |||
between…and… | 在某個範圍內 | [2,5] | |
and | 我和你&& | 5>1 and 1>2 | false |
or | 我或你|| | 5>1 or 1>2 | true |
--通過多個條件定位資料
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 null | a is null | 如果操作符為null,結果為真 |
is not null | a is not null | 如果操作符不為null,結果為真 |
between | a between b and c | 若a在b和c之間,則結果為真 |
like | a like b | SQL匹配,如果a匹配b,則結果為真 |
in | a 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
自連線(瞭解)
自己表和自己的表連線,核心:一張表拆為兩張一樣的表即可
父類
categoryid | categoryName |
---|---|
2 | 資訊科技 |
3 | 軟體開發 |
5 | 美術設計 |
子類
pid | categoryid | categoryName |
---|---|---|
3 | 4 | 資料庫 |
2 | 8 | 辦公資訊 |
3 | 6 | web開發 |
5 | 7 | 美術設計 |
操作:查詢父類對應的子類關係
父類 | 子類 |
---|---|
資訊科技 | 辦公資訊 |
軟體開發 | 資料庫 |
軟體開發 | 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