天天看點

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

1、初始MySQL

JavaEE : 企業級Java開發Web

  • 前端(頁面:展示,資料!)
  • 背景(連接配接點:連接配接資料庫JDBC,連結前端(控制,控制視圖跳轉,和給前端傳遞資料))
  • 資料庫(存資料,Txt,Excel,word)

隻會寫代碼,學好資料庫,基本混飯吃!

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

離散數學,數字電路,體系結構,編譯原理。+實戰經驗,進階程式猿優秀的程式猿

1.1、為什麼學習資料庫

  1. 崗位需求
  2. 現在的世界,大資料時代~,得資料庫者得天下。
  3. 被迫需求:存資料
  4. 資料庫是所有軟體體系中最核心的存在 DBA==

1.2、什麼是資料庫

  • 資料庫(DB,DataBase)
  • 概念:資料倉庫,軟體,安裝在作業系統( window ,linux, mac、…之上! SQL,可以存儲大量的資料。500萬!
  • 作用:存儲資料,管理資料

1.3、資料庫分類

關系型資料庫:(SQL)

  • MySQL,Oracle,Sql Server,DB2,SQLlite
  • 通過表和表之間,行和列之間的關系進行資料的存儲,學員資訊表,考勤表,…

非關系型資料庫:(NoSQL)Not Only

  • Redis,MongDB
  • 非關系型資料庫,對象存儲,通過對象的自身的屬性來決定。

DBMS(資料庫管理系統)

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

DBMS(資料庫管理系統)

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

1.4、MySQL簡介

MySQL是一個關系型資料庫管理系統前世:瑞典MySQL AB公司

今生:屬于Oracle旗下産品

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

開源的資料庫軟體~

體積小、速度快、總體擁有成本低,招人成本比較低,所有人必須會~中小型網站、或者大型網站,叢集!

安裝建議:

  1. 盡量不要使用exe,系統資料庫
  2. 盡可能使用壓縮包安裝~

1.5、安裝教程

1.5.1、軟體下載下傳

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

官網下載下傳位址:https://dev.mysql.com/downloads/mysql

1.5.2、操作步驟

下載下傳後得到zip壓縮包.

解壓到自己想要安裝到的目錄,本人解壓到的是D:\EnvironmentImysql-5.7.19

添加環境變量

  1. 我的電腦->屬性-→>進階->環境變量
  2. 選擇PATH,在其後面添加:你的mysql安裝檔案下面的bin檔案夾
  3. 在D:\Environmentimysql-5.7.19下建立my.ini檔案
  4. 編輯my.ini檔案,注意替換路徑位置

[mysqld]

basedir=D:\Program Files\mysql-5.7

datadir=D:\Program Files\mysql-5.7\data

port=3306

default-time-zone=’+8:00’

#skip-grant-tables

  1. 啟動管理者模式下的CMD,并将路徑切換至mysql下的bin目錄,然後輸入mysqld -install(安裝mysql)
  2. 再輸入mysqld --initialize-insecure --user=mysql初始化資料檔案
  3. 輸入net start mysql
  4. 然後再次啟動mysql然後用指令 mysql -u root -p進入mysql管理界面(密碼可為空)
  5. 進入界面後更改root密碼

update mysql.user set authentication_string=password ( '123456 ‘) where user=‘root’ and Host= ’ localhost’;

#mysql8.0以上更改root密碼

ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘password’;

(最後輸入flush privileges;重新整理權限)

  1. 修改my.ini檔案删除最後一句skip-grant-tables重新開機mysql即可正常使用

net stop mysql

net start mysql

  1. 連接配接上測試出現以下結果就安裝好了
    MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
    幹掉MySQL
sc delete mysql,清空服務

1.6、安裝SQLyog

  1. 下載下傳

    下載下傳位址:

    https://sqlyog.en.softonic.com/download

    MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
  2. 安裝

    注冊名:kuangshen

    注冊碼:8d8120df-a5c3-4989-8f47-5afc79c56e7c

  3. 建立一個資料庫 school
    MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
    每一個sqlyog的執行操作,本質就是對應了一個sql,可以在軟體的曆史記錄中檢視
  4. 建立一張表 student
字段:id,name,age,
           
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

5. 檢視表

6. 嘗試添加多條資料

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

1.7、連接配接資料庫

指令行連接配接!

mysql -u root -p	--連接配接資料庫
update mysql.user set authentication_string=password ( '123456 ') where user='root' and Host= ' localhost'; --修改使用者密碼
flush privileges;	--重新整理權限
---------------------------------------------------------
--所有的語句都使用;結尾

show databases;--檢視所有的資料庫

mysql> use school  --切換資料庫use資料庫名
Database changed

show tab1es; --檢視資料庫中所有的表
describe student; --顯示資料庫中所有的表的資訊
create database westos; --建立一個資料庫
exit;	--退出連接配接
--單行注釋(SQL的本來的注釋) 
/*	(sq1的多行注釋)
he1loi
asdasdasdas
*/
           
CRUD增删改查!

DDL 資料庫定義語言

DML 資料庫操作語言

DQL 資料庫查詢語言

DCL 資料庫控制語言

2、操作資料庫

操作資料庫>操作資料庫中的表>操作資料庫中表的資料

mysql關鍵字不分區大小寫

2.1、操作資料庫(了解)

  1. 建立資料庫
  1. 删除資料庫
  1. 使用資料庫
-- tab鍵的上面,如果你的表名或者字段名是一個特殊字元,就需要帶``
USE school
           
  1. 檢視資料庫

對比: SQLyog的可視化操作

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
SELECT `user` FROM student
           

學習思路:

  • 對照sqlyog究視化曆史記錄檢視sql
  • 固定的文法或關鍵字必須要強行記住!

2.2、資料庫的列類型

數值
  • tinyint 十分小的資料 1個位元組
  • smallint 較小的資料 2個位元組
  • mediumint 中等大小的資料 3個位元組
  • int 标準的整數 4個位元組 常用的 int
  • bigint 較大的資料 8個位元組
  • float 浮點數 4個位元組
  • double 浮點數 8個位元組 (精度問題!)
  • decima l字元串形式的浮點數 金融計算的時候,一般是使用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 時間格式
  • datetime 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 ,如果不給它指派,就會報錯!
  • NULL,如果不填寫值,預設就是null !

預設:

  • 設定預設的值!
  • sex,預設值為男,如果不指定該列的值,則會有預設的值!

拓展:聽聽就好

/*每一個表,都必須存在以下五個字段!未來做項目用的,表示一個記錄存在意義!
id	主鍵
`version`	樂觀鎖
is_delete	僞删除
gmt_create	建立時間
gmt_update	修改時間
*/

           

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

-- 目标:建立一個school資料庫
-- 倉建立學生表(列,字段)使用sQL建立
-- 學号int 登入密碼varchar(20)姓名,性别varchar(2),出生日期(datetime),家庭住址, email

-- 注意點,使用英文(),表的名稱和字段盡量使用 `` 括起來
-- AUTOINCREMENT自增
-- 字元串使用單引号括起來!
-- 所有的語句後面加,(英文的),最後一個不用加
-- COMMENT 是備注bai、注釋的意思,寫上COMMENT 'id'之後du,在建表信zhi息裡可以看到dao添加的備注資訊。
-- DEFAULT預設的
-- PRIMARY KEY 主鍵,一般一個表隻有一個唯一的主鍵!
CREATE TABLE IF NOT EXISTS `student`(
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '學号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(30) NOT NULL DEFAULT '123456' COMMENT '密碼',
`sex` VARCHAR(2) DEFAULT '男' COMMENT '性别',
`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
`address` VARCHAR(30) DEFAULT NULL COMMENT '家庭住址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
           

格式

CREATE TABLE [IF NOT EXISTS]`表名`(
`字段名`列類型[屬性][索引][注釋],
`字段名`列類型[屬性][索引][注釋],
.......
`字段名`列類型[屬性][索引][注釋]
)[表類型][字元集設定][注釋]

           

常用指令:

SHOW CREATE DATABASE school -- 檢視建立資料庫的語句
SHOW CREATE TABLE student -- 檢視student資料表的定義語句
DESC student -- 檢視表的結構
           

2.5、資料表的類型

-- 關于資料庫引擎
/*
INNODB預設使用~
MYISAM早些年使用的
*/
           
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

正常使用操作:

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

所有的資料庫檔案都存在data目錄下

本質還是檔案的存儲!

MySQL引擎在實體檔案上的差別

  • InnoDB在資料庫表中隻有一個*.frm檔案,以及上級目錄下的 ibdata1檔案
  • MYISAM對應檔案
    • *.frm表結構的定義檔案木
    • *.MYD資料檔案(data)
    • *.MYI索引檔案(index)
設定資料庫表的字元集編碼
CHARSET=utf8
           

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

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

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

character-set-server=utf8
           

2.6、修改删除表

修改
-- 修改表名	ALTER TABLE 舊表名 RENAME AS 新表名
ALTER TABLE student RENAME AS student1

-- 增加表的字段		ALTER TABLE 表名 ADD 字段名 列屬性
ALTER TABLE student1 ADD age INT(10)

-- 修改表的字段(重命名,修改限制!)
-- ALTER TABLE 表名 MODIFY 字段名 列屬性[]
ALTER TABLE student1 MODIFY age VARCHAR(10)	-- 修改限制
-- ALTER TABLE 表名 CHANGE 舊名字 新名字 列屬性[]
ALTER TABLE student1 CHANGE age age1 INT(10)	-- 字段重名名

-- 删除表的字段
-- ALTER TABLE 表名 DROP 字段名
ALTER TABLE student1 DROP age1
           
删除
-- 删除表(如果表存在再删除)
DROP TABLE IF EXISTS student1
           

所有的建立和删除操作盡量加上判斷,以免報錯~

注意點:

  • `` 字段名,使用這個包裹!
  • 注釋 --
  • sql關鍵字大小寫不敏感,建議大家寫小寫
  • 所有的符号全部用英文!

3、MySQL資料管理

3.1、外鍵(了解即可)

方式一、在建立表的時候,增加限制(麻煩,比較複雜)
-- 學生表的 gradeid 字段要去引用年級表的 gradeid
-- 定義外鍵key
-- 給這個外鍵添加限制(執行引用) references 引用

CREATE TABLE IF NOT EXISTS `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT  COMMENT '年級id',
`gradename` VARCHAR(20) NOT NULL COMMENT '年級名稱',
PRIMARY KEY(`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

CREATE TABLE IF NOT EXISTS `student`(
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '學号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(30) NOT NULL DEFAULT '123456' COMMENT '密碼',
`sex` VARCHAR(2) DEFAULT '男' COMMENT '性别',
`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
`gradeid` INT(10) NOT NULL   COMMENT '學生的年級',
`address` VARCHAR(30) DEFAULT NULL COMMENT '家庭住址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY(`id`),
KEY `FK_gradeid` (`gradeid`),
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
           

删除有外鍵關系的表的時候,必須要先删除引用别人的表(從表),再删除被引用的表(主表)

方式二:建立表成功後,添加外鍵限制
-- 學生表的 gradeid 字段要去引用年級表的 gradeid
-- 定義外鍵key
-- 給這個外鍵添加限制(執行引用) references 引用

CREATE TABLE IF NOT EXISTS `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT  COMMENT '年級id',
`gradename` VARCHAR(20) NOT NULL COMMENT '年級名稱',
PRIMARY KEY(`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

CREATE TABLE IF NOT EXISTS `student`(
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '學号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(30) NOT NULL DEFAULT '123456' COMMENT '密碼',
`sex` VARCHAR(2) DEFAULT '男' COMMENT '性别',
`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
`gradeid` INT(10) NOT NULL   COMMENT '學生的年級',
`address` VARCHAR(30) DEFAULT NULL COMMENT '家庭住址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

-- 建立表的時候沒有外鍵關系
ALTER TABLE student 
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)
-- ALTER TABLE 表 ADD CONSTRAINT 限制名 FOREIGN KEY( 作為外鍵的列) REFERENCES 哪個表(哪個字段)

           

以上的操作都是實體外鍵,資料庫級别的外鍵,我們不建議使用!(避免資料庫過多造成困擾,這裡了解即可)

最佳實踐

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

3.2、DML語言(全部記住)

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

DML語言:資料操作語言

  • lnsert
  • update
  • delete

3.3、添加

insert
-- 插入語句(添加)
-- insert into 表名 ([字段名1,字段2,字段3])values ('值1'),('值2'),('值3'),....)
INSERT INTO `grade` (`gradename`) VALUES ('大四') 

-- 由于主鍵自增我們可以省略(如果不寫表的字段,他就會一一比對)
INSERT INTO `grade` VALUES ('大三')
-- 一般寫插入語句,我們一定要資料和字段一一對應!

-- 插入多個字段
INSERT INTO`grade` (`name`) VALUES ('張三')
INSERT INTO`student` (`name`,`pwd`,`sex`) VALUES ('張三','aaaaaa','男')
INSERT INTO`student` (`name`,`pwd`,`sex`) VALUES ('張三','aaaaaa','男'),('李四','aaaaaa','男'),('王五','aaaaaa','男')
           

文法:

insert into 表名 ([字段名1,字段2,字段3])values ('值1'),('值2'),('值3'),....)

注意事項:

  1. 字段和字段之間使用英文逗号隔開
  2. 字段是可以省略的,但是後面的值必須要要——對應,不能少
  3. 可以同時插入多條資料,VALUES後面的值,需要使用,隔開即可

    VALUES(),()....

3.4、修改

update 修改誰 (條件) set 原來的值=新值
-- 修改學員名字,帶了條件
UPDATE	`student` SET `name`='java' WHERE id=1

-- 不指定條件的情況下,會改動所有表!
UPDATE	`student` SET `name`='長江一号' 

-- 修改多個屬性,逗号隔開
UPDATE `student` SET `name`='長江一号',`email`='[email protected]' WHERE id=1;

-- 文法:
UPDATE	表名	set co1num_name = value , [co1num_name = value , .. . .]	where 條件[]
           

條件: where子句運算符id等于某個值,大于某個值,在某個區間内修改…

操作符會傳回布爾值

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
--通過多個條件定位資料
UPDATE `student` SET `name`='長江7号' WHERE name ='狂神44' AND sex='女'
           

文法:

UPDATE 表名 set co1num_name = value , [co1num_name = value , .. . .] where 條件[]

注意:

  1. colnum_name是資料庫的列,盡量帶上 ``
  2. 條件,篩選的條件,如果沒有指定,則會修改所有的列
  3. value,是一個具體的值,也可以是一個變量
  4. 多個設定的屬性之間,使用英文逗号隔開

3.5、删除

delete指令

文法:

delete from 表名 [where 條件]

--删除資料	(避免這樣寫,會全部删除)
DELETE FROM `student`

--删除指定資料
DELETE FROM `student` WHERE id = 1;
           
TRUNCATE指令

作用:完全清空一個資料庫表,表的結構和索引限制不會變!

--	清空student表
TRUNCATE  `student` 
           
delete 和T RUNCATE 差別
  • 相同點:都能删除資料,都不會删除表結構
  • 不同:
    • TRUNCATE 重新設定自增列計數器會歸零
    • TRUNCATE 不會影響事務
-- 測試delete 和 TRUNCATE差別
CREATE TABLE `test`(
`id`  INT(4) NOT NULL AUTO_INCREMENT,
`co11` VARCHAR(20) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `test`(`co11`) VALUES('1'),('2'),('3')

DELETE FROM `test` --不會影響自增

TRUNCATE TABLE `test` --自增會歸零
           

了解即可:

DELETE

删除的問題,重新開機資料庫,現象

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

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

           
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

文法:

SELECT

字段,…FROM表

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

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

--查詢一下有哪些同學參加了考試,成績

SELECT * FROM result	--查詢全部的考試成績
SELECT `StudentNo` FROM result 	--查詢有哪些同學參加了考試
SELECT DISTINCT `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條件子句

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

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

邏輯運算符
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

盡量使用英文字母

-- =================where=====================
SELECT `studentNo`, `StudentResult` FROM result

-- 查詢考試成績在95~100分之間
SELECT `studentNo`,`StudentResult` FROM result
WHERE StudentResult>=95 AND StudentResult<=100

-- and &&
SELECT `studentNo`,`StudentResult` FROM result
WHERE StudentResult>=95 && StudentResult<=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

           
模糊查詢:比較運算符
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
-- =================模糊查詢=====================
-- 查詢姓劉的同學
-- 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 StudentNo 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 `BornDate` IS NOT NULL
-- 查詢沒有有出生日期的同學 為空
SELECT `StudentNo`, `StudentName` FROM `student`
WHERE `BornDate` IS NULL
           

4.4、聯表查詢

JOIN 對比
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
-- =================聯表查詢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

--  Right Join
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student s
RIGHT JOIN result r
ON s.studentNO = r.studentNO

-- Left Join
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student s
LEFT JOIN result r
ON s.studentNO = r.studentNO

-- 查詢缺考的同學
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student s
LEFT JOIN result r
ON s.studentNO = r.studentNO
WHERE StudentResult IS NULL
           
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
-- 思考題(查詢了參加考試的同學資訊:學号,學生姓名,科目名,分數)
/*思路
1.分析需求,分析查詢的字段來自哪些表, student、result、subject(連接配接查詢)
2.确定使用哪種連接配接查詢?	7種
确定交叉點(這兩個表中哪個資料是相同的)
判斷的條件:學生表的中 studentNo =成績表studentNo
*/
SELECT s.studentNo,studentName,subjectName,`studentResult`
FROM student s
RIGHT JOIN result r
ON r.studentNo = s.studentNo
INNER JOIN`subject` sub
ON r.SubjectNo = sub.SubjectNo

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

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

父類

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

子類

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

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

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
-- 查詢父子資訊:把一張表看為兩個一模一樣的表
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`,`GradeNameFROM `subject` sub
INNER JOIN `grade` g
ON sub.`GradeID`= g.`GradeID`

-- 查詢了參加 資料庫結構-1 考試的同學資訊:學号,學生姓名,科目名,分數
SELECT s.`studentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM student s
INNER JOIN result  r
ON s.studentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`subjectNo	= sub.`SubjectNo`
WHERE subjectName ='資料庫結構-1'

           

4.5、分頁和排序

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

-- 排序:升序 ASC ,降序 DESC
-- ORDER BY 通過那個字段排序,怎麼排
-- 查詢的結果根據 成績降序 排序

SELECT s.`studentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM student s
INNER JOIN result  r
ON s.studentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`subjectNo	= sub.`SubjectNo`
WHERE subjectName ='資料庫結構-1'
ORDER BY StudentResult ASC

           
分頁
-- 100萬
-- 為什麼要分頁?
-- 緩解資料庫壓力,給人的體驗更好,瀑布流

-- 分頁,每頁隻顯示五條資料
-- 文法: limit 起始值,頁面的大小
-- 網頁應用:目前,總的頁數,頁面的大小
-- LIMIT 0,5	1~5
-- LIMIT l,5	2~6
-- Limit 6,5

SELECT s.`studentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM student s
INNER JOIN result  r
ON s.studentNo = r.StudentNo
INNER JOIN `subject` sub
ON r.`subjectNo	= sub.`SubjectNo`
WHERE subjectName ='資料庫結構-1'
ORDER BY StudentResult DESC
LIMIT 1,5

-- 第一頁limit 0,5	(1-1)*5
-- 第二頁limit 5,5	(2-1)*5
-- 第三頁limit 10,5	(3-1)*5
-- 第N頁limit 0,5	(n-1) * pagesize, pagesize
-- [pageSize:頁面大小]
-- [(n-1)* pageSize: 起始值]
-- [n: 目前頁]
-- [資料總數/頁面大小=總頁數]

           

文法: limit (查詢起始下标,pagesize)

-- 思考:
-- 查詢JAVA第一學年課程成績排名前十的學生,并且分數要大于80 的學生資訊(學号,姓名,課程名稱,分數)
SELECT s.`studentNo`,`studentName`,`subjectName`,`studentResult`
FROM `student` s
INNER JOIN `result` r
ON s.studentNo = r.studentNo
INNER JOIN  subject sub
ON sub.SubjectNo = r.SubjectNo
WHERE SubjectName = 'JAVA第一學年' AND StudentResult>=80
ORDER BY studentResult DESC
LIMIT 0,10

           

4.6、子查詢

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

本質︰在 wher e語句中嵌套一個子查詢語句

where (select * from )

-- =================where=====================
-- 1、查詢資料庫結構-1的所有考試結果(學号,科目編号,成績),降序排列
-- 方式一:使用連接配接查詢
SELECT `studentNo`,r.`subjectNo`,`studentResult`
FROM `result` r
INNER JOIN `subject` sub
ON r.subjectNo = sub.subjectNo
WHERE SubjectName = '資料庫結構-1'
ORDER BY StudentResult DESC

-- 方式二:使用子查詢(使用子查詢(由裡及外))
SELECT `studentNo`,`SubjectNo`,`studentResult
FROM `result`
WHERE SubjectNo = (
	SELECT SubjectNo FROM `subject`
	WHERE SubjectName = '資料庫結構-1'
)
ORDER BY StudentResult DESC
-- 查詢所有資料庫結構-1 的學生學号
SELECT SubjectNo FROM `subject` WHERE SubjectName = '資料庫結構-1'

-- 分數不小于80分的學生的學号和姓名	DISTINCT 去重
SELECT DISTINCT s.`studentNo`,`studentName
FROM student s
INNER JOIN result r
ON r.studentNo = s.studentNo
WHERE `studentResult`>=80

-- 在這個基礎上增加一個科目,高等數學-2
-- 查詢 高等數學-2的編号
SELECT DISTINCT s.`StudentNo`,`studentName
FROM student s
INNER JOIN result r
ON r.studentNo = s.studentNo
WHERE `studentResult`>=80 AND `subjectNo`= (
	SELECT SubjectNo FROM `subject`
	WHERE`subjectName` ='高等數學-2'
)

-- 查詢課程為高等數學-2且分數不小于80的同學的學号和姓名
SELECT 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

-- 再改造 (由裡及外)
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

           

4.8、Select小結

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

5、MySQL函數

官網: https://dev.mysql.com/doc/refman/8.0/en/sql-function-reference.html

5.1、常用函數

-- =================常用函數=====================

-- 數學運算
SELECT ABS(-8)		--絕對值
SELECT CEILING(9.4)	--向上取整
SELECT FLOOR(9.4)	--向下取整
SELECT RAND ()		--傳回一個0~l之間的随機數
SELECT SIGN (10)	--判斷一個數的符号0-0	負數傳回-1,正數傳回1

-- 字元串函數
SELECT CHAR_LENGTH ('即使再小的帆也能遠航')	-- 字元串長度
SELECT CONCAT ('我','愛','你們')				 --拼接字元串
SELECT INSERT ('我愛程式設計helloworld',1,2,'超級熱愛')	--插入,從某個位置開始替換某個長度
SELECT LOWER ('Kuangshen') 	--小寫字母
SELECT UPPER ('KuangShen') 	--大寫字母
SELECT INSTR ('kuangshen','h') -- 傳回第一次出現的子串的索引
SELECT REPLACE ('狂神說堅持就能成功','堅持','努力') --替換出現的指定字元串
SELECT SUBSTR ('狂神說堅持就能成功',4,3)	--傳回指定的子字元串(源字元串,截取的位置,截取的長度)
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、聚合函數(常用)

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
-- =================聚合函數===================== 
-- 都能夠統計表中的資料 (想查詢一個表中有多少個記錄,就使用這個count () )
SELECT COUNT (`BornDate`) FROM student; -- Count(字段),會忽略所有的null值
SELECT COUNT(*) FROM student; -- Count (*),不會忽略null值,本質計算行數
SELECT COUNT(1)FROM result; -- Count (1),不會忽略忽略所有的null值本質計算行數

SELECT SUM (`studentResult`) AS 總和 FROM result
SELECT AVG (`studentResult`) As 平均分 FROM result
SELECT MAX (`StudentResult`) AS 最高分 FROM result
SELECT MIN (`studentResult`) AS 最低分 FROM result

-- 查詢不同課程的平均分,最高分,最低分,平均分大于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.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`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

-- 明文密碼
INSERT INTO testmd5 VALUES(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 VALUES (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原則 原子性, 一緻性,隔離性,持久性 (髒讀,幻讀…)

原子性 (Atomicity)

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

一緻性 (Consistency)

  • 事務前後的資料完整性要保證一緻,1000

持久性(Durability) —事務送出

  • 事務一旦送出則不可逆,被持久化到資料庫中!

隔離性(lsolation)

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

髒讀:

  • 指一個事務讀取了另外一個事務未送出的資料。

不可重複讀:

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

虛讀(幻讀)

  • 是指在一個事務内讀取到了别的事務插入的資料,導緻前後讀取不一緻。
-- =================事物===================== 
--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	儲存點名		-- 撤銷儲存點
           
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
模拟場景
-- =================轉賬===================== 
CREATE DATABASE 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`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO account(`name`,`money`) 
VALUES	('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;	--恢複預設值

           
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

7、索引

MySQL官方對索引的定義為:索引(Ilndex)是幫助MySQL高效擷取資料的資料結構。提取句子主幹,就可以得到索引的本質:索引是資料結構。

7.1、索引的分類

在一個表中,主鍵索引隻能有一個,唯一索引可以有多個
  • 主鍵索引 (PRIMARY KEY )
    • 唯一的辨別,主鍵不可重複,隻能有一個列作為主鍵
  • 唯一索引 (UNIQUE KEY)
    • 避免重複的列出現,唯一索引可以重複,多個列都可以辨別位唯一索引
  • 正常索引 (KEY/INDEX)
    • 預設的, index 或者 key關鍵字來設定
  • 全文索引 (FullText)
    • 在特定的資料庫引擎下才有,MylSAM
    • 快速定位資料

基礎文法:

-- 索引的使用
-- 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 ()
RETURN INT
BEGIN
	DECLARE	num INT DEFAULT	1000000;
	DECLARE i	INT DEFAULT 0;
	WHILE i<num DO
		--插入語句
		INSERT INTO app_user (`name`,`email`,`phone`,`gender`,`password`, `age`)
		VALUES (CONCAT ('使用者',i), '[email protected]', CONCAT ('18',FLOOR(RAND()*((999999999-100000000)+100000000))),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100));
		SET i= i+1;
	END WHILE
	RETURN i;
END;

SELECT * FROM app_user WHERE `name` = '使用者9999';-- 0.993 sec
SELECT * FROM app_user wHERE `name` = '使用者9999';-- 1.098 sec
SELECT * FROM app_user WHERE `name` = '使用者9999';--- 0.788 sec

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.001 sec
SELECT * FROM app_user wHERE `name` = '使用者9999';
EXPLAIN SELECT * FROM app_user WHERE `name`= '使用者9999';
           
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

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

7.3、索引原則

  • 索引不是越多越好
  • 不要對經常變動的資料加索引
  • 小資料量的表不需要加索引
  • 索引一般加在常用來查詢的字段上!
索引的資料結構

Hash類型的索引

Btree : lnnoDB的預設資料結構~

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

8、權限管理和備份

8.1、使用者管理

SQL yog可視化管理
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
SQL指令操作

使用者表:mysql.user

本質:對這張表進行增删改查

-- 建立使用者 CREATE USER 使用者名 IDENTIFIED BY '密碼'
CREATE USER kuangshen IDENTIFIED BY '123456'

-- 修改密碼(修改目前使用者密碼)
SET PASSWORD =PASSWORD('111111')

-- 修改密碼(修改指定使用者密碼)
SET PASSWORD FOR kuangshen = PASSWORD('111111')

-- 重命名	RENAME USER 原來名字 TO 新的名字
RENAME USER kuangshen TO kuangshen2

-- 使用者授權ALL PRIVILEGES全部的權限,庫.表
-- ALL PRIVILEGES 除了給别人授權,其他都能夠幹
GRANT ALL PRIVILEGES ON *.* TO kuangshen2

-- 查詢權限
SHOW GRANTS FOR kuangshen2
SHOW GRANTS FOR root@localhost

-- ROOT使用者權限:GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost’ WITH GRANT OPTION

-- 撤銷權限REVOKE哪些權限,在哪個庫撤銷,給誰撤銷
REVOKE ALL PRIVILEGES ON *.*  FROM	 kuangshen2

-- 删除使用者
DROP USER kuangshen

           

8.2、MySQL備份

為什麼要備份:

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

MySQL資料庫備份的方式

  • 直接拷貝實體檔案
  • 在Sqlyog這種可視化工具中手動導出
    • 在想要導出的表或者庫中,右鍵,選擇備份或導出
      MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
      MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
  • 使用指令行導出mysqldump指令行使用
# mysqldump -h主機 -u使用者名-p密碼﹐資料庫表名 >實體磁盤位置/檔案名
mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sq1

# mysq1dump -h主機 -u使用者名 -p密碼 資料庫 表1 表2 表3 > 實體磁盤位置/檔案名
mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sq1

# mysqldump -h主機 -u使用者名 -p密碼 資料庫 > 實體磁盤位置/檔案名
mysqldump -hlocalhost -uroot -p123456 school >D:/a.sq1

# 導入
# 登入的情況下,切換到指定的資料庫
# 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):

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

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

第二範式 (2NF)

前提:滿足第一範式

每張表隻描述一件事情

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

第三範式 (3NF)

前提:滿足第一範式和第二範式

第三範式需要確定資料表中的每一列資料都和主鍵直接相關,而不能間接相關。

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

(規範資料庫的設計)

規範性和性能的問題

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

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

10、JDBC(重點)

10.1、資料庫驅動

驅動:聲霸卡,顯示卡、資料庫

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

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

10.2、JDBC

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

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

對于開發人員來說,我們隻需要掌握JDBC接口的操作即可

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、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 jdbcStudy;

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,'zhansan','123456','[email protected]','1980-12-04'),
(2,'lisi','123456','[email protected]','1981-12-04'),
(3,'wangwu','123456','[email protected]','1979-12-04');

           
  1. 建立一個普通項目
  2. 導入資料庫驅動
    MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
package 第一個jdbc程式;

import com.mysql.jdbc.Driver;

import java.sql.*;

//我的第一個JDBC程式
public class jdbcFirst01 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加載驅動
        //DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
        Class.forName("com.mysql.cj.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 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("email"+resultSet.getObject("email"));
            System.out.println("birth"+resultSet.getObject("birthday"));
            System.out.println("===================================");
        }
        //6、釋放連接配接
        resultSet.close();
        statement.close();
        connection.close();
    }
}

           

步驟總結:

  1. 加載驅動
  2. 連接配接資料庫DriverManager
  3. 獲得執行sql的對象Statement
  4. 獲得傳回的結果集
  5. 釋放連接配接
DriverManager
//DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
Class.forName("com.mysql.cj.jdbc.Driver");//固定寫法,加載驅動   推薦使用這個

Connection connection = DriverManager.getConnection(url, username, password);
//connection	代表資料庫
//資料庫設定自動送出
//事務送出
//事務滾回
connection.rollback();
connection.commit();
connection.setAutoCommit();

           
URL
String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";

//mysql端口預設-3306
//協定://主機位址:端口/資料庫名?參數1&參數2&參數3
//Oracle預設端口-1521
//jdbc:oracle:thin:@localhost:1521:sid

           

Statement 執行SQL的對象

PrepareStatement 執行SQL的對象

String sql="SELECT * FROM users";//編寫sql
statement.executeQuery(); //查詢操作傳回ResultSet
statement.execute(); //執行任何SQL
statement.executeUpdate();//更新、插入、删除。都是用這個,傳回一個受影響的行數

           
ResultSet 查詢的結果集:封裝了所有的查詢結果

獲得指定的資料類型

resultset.getObject();//在不知道列類型的情況下使用
//如果知道列的類型就使用指定的類型
resultset.getSring();
resultset.getInt();
resu1tset.getFloat();
resu1tset.getDate();
resultset.getObject();

           

周遊,指針

resultSet.beforeFirst();//移動到最前面
resultSet.afterLast();//移動到最後面
resultSet.next();//移動到下一個資料
resultSet.previous(); //移動到前一行
resultset.absolute(row); //移動到指定行

           
釋放資源
//6、釋放連接配接
resultSet.close();
statement.close();
connection.close();//耗資源,用完關掉

           

10.4、statement對象

Jdbc中的statement對象用于向資料庫發送SQL語句,想完成對資料庫的增删改查,隻需要通過這個對象向資料庫發送增删改查語句即可。

Statement對象的executeUpdate方法,用于向資料庫發送增、删、改的sql語句,executeUpdate執行完後,将會傳回一個整數(即增删改語句導緻了資料庫幾行資料發生了變化)。

Statement.executeQuery方法用于向資料庫發送查詢語句,executeQuery方法傳回代表查詢結果的ResultSet對象。

CRUD操作-create

使用executeUpdate(String sql)方法完成資料添加操作,示例操作:

Statement st = conn.createStatement();
String sql = "insert into user(.. ) values(.... . )";
int num = st.executeUpdate(sql);
if(num>0){
	System.out.println("插入成功!!!");
}

           
CRUD操作-delete

使用executeUpdate(String sql)方法完成資料删除操作,示例操作:

Statement st = conn.createStatement();
String sql = "delete from user where id=1";
int num = st.executeUpdate(sql);
if(num>0){
	System.out.println("删除成功!!!");
}
           
CRUD操作-update使用executeQuery(String sql)方法完成資料查詢操作,示例操作:

使用executeUpdate(String sql)方法完成資料修改操作,示例操作:

Statement st = conn.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 = conn.createStatement();
String sql = "select * from user where id=1";
ResultSet rs = st.executeQuery(sql);
while(rs.next(){
//根據擷取列的資料類型,分别調用rs的相應方法映射到java對象中
}

           
代碼實作

1、提取工具類

package 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");
            //1.驅動隻用加裁一次
            Class.forName(driver);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //1.擷取連接配接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }
    //釋放連接配接資源
    public static void release(Connection con, Statement st, ResultSet re) throws SQLException {
        if (re!=null){
            re.close();
        }
        if (st!=null){
            st.close();
        }
        if (con!=null){
            con.close();
        }
    }
}

           

2、編寫增删改的方法,executeupdate

package 測試工具類;

import utils.JdbcUtils;

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) throws SQLException {
        Connection con=null;
        Statement st=null;
        ResultSet re=null;
        try {
            con = JdbcUtils.getConnection();//擷取資料庫連接配接
            st= con.createStatement();//獲得SQL的執行對象
            String sql="INSERT INTO users (`id`,`NAME`,`PASSWORD`,`email`,`birthday`)" +
                    "VALUES (4,'java','123456','[email protected]','2021-2-24')";
            int i = st.executeUpdate(sql);
            if (i>0){
                System.out.println("添加成功");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

           
package 測試工具類;

import utils.JdbcUtils;

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) throws SQLException {
        Connection con=null;
        Statement st=null;
        ResultSet re=null;
        try {
            con = 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();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

           
package 測試工具類;

import utils.JdbcUtils;

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) throws SQLException {
        Connection con=null;
        Statement st=null;
        ResultSet re=null;
        try {
            con = JdbcUtils.getConnection();//擷取資料庫連接配接
            st= con.createStatement();//獲得SQL的執行對象
            String sql="UPDATE users SET `NAME`='xiaojian' , `email`='[email protected]' WHERE id=1";
            int i = st.executeUpdate(sql);
            if (i>0){
                System.out.println("更新成功");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

           

3、查詢

package 測試工具類;

import utils.JdbcUtils;

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) throws SQLException {
        Connection con=null;
        Statement st=null;
        ResultSet re=null;
        try {
            con = JdbcUtils.getConnection();//擷取資料庫連接配接
            st= con.createStatement();//獲得SQL的執行對象
            // SQL
            String sql="select * from user where id=1";
            re = st.executeQuery(sql);//查詢完畢會傳回一個結果集
            while (re.next()){

                System.out.println(re.getString("NAME"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

           
SQL注入的問題

sql存在漏洞,會被攻擊導緻資料洩露

SQL會被拼接or

package 測試工具類;

import utils.JdbcUtils;

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) throws SQLException {
        login("'' 'or 1=1","''or,1=1");

    }
    //登入業務
    public static void login(String username,String password ) throws SQLException {
        Connection con=null;
        Statement st=null;
        ResultSet re=null;
        try {
            con = JdbcUtils.getConnection();//擷取資料庫連接配接
            st= con.createStatement();//獲得SQL的執行對象
            // SQL
            String sql="select * from users ";
            re = st.executeQuery(sql);//查詢完畢會傳回一個結果集
            while (re.next()){

                System.out.println(re.getString("NAME"));
                System.out.println(re.getString("password"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

           

10.5、PreparedStatement對象

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

1、新增

package PreparedStatement測試;

import utils.JdbcUtils;

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

public class TestInsert {
    public static void main(String[] args) throws SQLException {
        Connection con =null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con= JdbcUtils.getConnection();
            //差別
            //使用?占位符代替參數
            String sql="INSERT INTO users (`id`,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES (?,?,?,?,?)";
            st = con.prepareStatement(sql);//預編譯SQL,先寫sqL,然後不執行
            //手動給參數指派
            st.setInt(1,4);
            st.setString(2,"xiaojian");
            st.setString(3,"123456");
            st.setString(4,"[email protected]");
            //注意點:  sql.Date資料庫            java.sql.Date
            //          util.Date Java       new Date().getTime()   獲得時問戳
            st.setDate(5, new java.sql.Date(new Date().getTime()));
            //執行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,null);
        }
    }
}

           

2、删除

package PreparedStatement測試;

import utils.JdbcUtils;

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

public class TestDelete {
    public static void main(String[] args) throws SQLException {
        Connection con =null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con= JdbcUtils.getConnection();
            //差別
            //使用?占位符代替參數
            String sql="delete from users where id=?";
            st = con.prepareStatement(sql);//預編譯SQL,先寫sqL,然後不執行
            //手動給參數指派
            st.setInt(1,4);
            //執行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("删除成功");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,null);
        }
    }
}

           

3、更新

package PreparedStatement測試;

import utils.JdbcUtils;

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


public class TestUpdate {
    public static void main(String[] args) throws SQLException {
        Connection con =null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con= JdbcUtils.getConnection();
            //差別
            //使用?占位符代替參數
            String sql="update users set `name` =?  where id=?;";
            st = con.prepareStatement(sql);//預編譯SQL,先寫sqL,然後不執行
            //手動給參數指派
            st.setString(1,"小賤");
            st.setInt(2,4);
            //執行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("更新成功");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,null);
        }
    }
}

           

4、查詢

package PreparedStatement測試;

import 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) throws SQLException {
        Connection con =null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con= JdbcUtils.getConnection();
            //差別
            //使用?占位符代替參數
            String sql="select * from users where id=?";
            st = con.prepareStatement(sql);//預編譯SQL,先寫sqL,然後不執行
            //手動給參數指派
            st.setInt(1,1);//傳遞參數
            //執行
            re = st.executeQuery();
            while (re.next()){
                System.out.println(re.getString("NAME"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

           

5、防止SQL注入

package PreparedStatement測試;

import utils.JdbcUtils;

import java.sql.*;

public class SQL注入 {
    public static void main(String[] args) throws SQLException {
//        login("lisi","123456");
        login("'' 'or 1=1","''or,1=1");

    }
    //登入業務
    public static void login(String username,String password ) throws SQLException {
        Connection con=null;
        PreparedStatement st=null;
        ResultSet re=null;
        try {
            con = JdbcUtils.getConnection();//擷取資料庫連接配接
            // SQL
            String sql="select * from users where `NAME`=? and `PASSWORD`=?";
            //PreparedStatement防止lSQL注入的本質,把傳遞進來的參數當做字元
            //假設其中存在轉義字元,就直接忽略,比如說’ 引号會被直接轉義
            st= con.prepareStatement(sql);//獲得SQL的執行對象
            st.setString(1,username);
            st.setString(2,password);
            re = st.executeQuery();//查詢完畢會傳回一個結果集
            while (re.next()){

                System.out.println(re.getString("NAME"));
                System.out.println(re.getString("PASSWORD"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(con,st,re);
        }
    }
}

           

10.6、使用IDEA連接配接資料庫

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

連接配接成功後,可以選擇資料庫

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

輕按兩下資料庫

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

更新資料

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)
/*建立賬戶表*/
CREATE TABLE account(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(40),
	money FLOAT
);
/*插入測試資料*/
insert into account(name,money) values('A',1000);
insert into account(name,money) values('B',1000);
insert into account(name,money) values('c',1000);

           

連接配接失敗,檢視原因

MySQL1、初始MySQL2、操作資料庫3、MySQL資料管理4、DQL查詢資料(最重點)5、MySQL函數6、事務7、索引8、權限管理和備份9、規範資料庫設計10、JDBC(重點)

10.7、事務

要麼都成功,要麼都失敗

ACID原則

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

一緻性:總數不變

隔離性:多個程序互不幹擾

持久性:一旦送出不可逆,持久化到資料庫了

隔離性的問題

  • 髒讀:一個事務讀取了另一個沒有送出的事務

不可重複讀:

  • 在同一個事務内,重複讀取表中的資料,表資料發生了改變

虛讀(幻讀)

  • 在一個事務内,讀取到了别人插入的資料,導緻前後讀出來結果不一緻
代碼實作

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

2、一組業務執行完畢I送出事務

3、可以在catch語句中顯示的定義復原語句,但預設失敗就會復原

package 事物;

import utils.JdbcUtils;

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

public class TestTransaction2 {
    public static void main(String[] args) throws SQLException {
        Connection con=null;
        PreparedStatement st=null;
        ResultSet rs=null;
        try{
            con = JdbcUtils.getConnection();
            //關閉資料庫的自動送出,自動會開啟事務
            con.setAutoCommit(false);//開啟事務
            String sql1="update account set money=money-100 where name ='A'";
            st = con.prepareStatement(sql1);
            st.executeUpdate();

            int x=1/0;//報錯

            String sql2="update account set money=money+100 where name ='B'";
            st = con.prepareStatement(sql2);
            st.executeUpdate();
            //業務完畢,送出事務
            con.commit();
            System.out.println("成功");

        }
        catch (SQLException throwables) {
            //如果失敗,則預設復原
            con.rollback();//如果失敗則復原事務
            throwables.printStackTrace();
        }
        finally {
            JdbcUtils.release(con,st,rs);
        }
    }
}

           

10.8、資料庫連接配接池

資料庫連接配接—執行完畢—釋放

連接配接–釋放十分浪費系統資源

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

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

常用連接配接數10個

最小連接配接數:10

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

排隊等待: 100ms

編寫連接配接池,實作一個接口DataSource

開源資料源實作

DBCP

C3PO

Druid: 阿裡巴巴

使用了這些資料庫連接配接池之後,我們在項目開發中就不需要編寫連接配接資料庫的代碼了!

DBCP

需要用到的jar包

commons-dbcp-1.4 ,commons-pool-1.6

dbcpconfig.properties配置檔案

#連接配接設定	這裡面的名字,是DBCP資料源中定義好的
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
#<!--初始化連接配接-->

initialSize=10

#最大連接配接數量
maxActive=50
#<! --最大空閑連接配接-->
maxIdle=20
#<! --最小空閑連接配接-->
minIdle=5
#<!--逾時等待時問以毫秒為機關6000毫秒/1000等丁60秒-->
maxWait=60000
#JDBC驅動建立連接配接時附帶的連接配接屬性屬性的格式必須為這樣:[屬性名=property; ]
#注意: "user”與“password”兩個屬性會被明确地傳遞,是以這裡不需要包含他們。
connectionProperties=useUnicode=true;characterEncoding=UTF8

#指定由連接配接池所建立的連接配接的自動送出(auto-commit)狀态。
defaultAutoCommit=true
#driver default指定由連接配接池所建立的連接配接的隻讀(read-only)狀态。
#如果沒有設定該值,則"setReadOnly”方法将不被調用。(某些驅動并不支援隻讀模式,如:Informix>)
defaultReadonly=

#driver default 指定由連按池所建立的連接配接的事務級别(TransactionIsoLation)。
#可用值為下列之一:(詳情可見javadoc。) NONE ,READ_UNCONNITTED,READ_CONWNITTED,REPEATABLE_READ,SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
           

DBCP工具類

package utils;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;

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

public class JdbcUtils_DBCP {
    private static BasicDataSource dataSource=null;
    static {
        try{
            InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            Properties properties = new Properties();
            properties.load(in);
            //建立資料源 工廠模式--> 建立
            dataSource = BasicDataSourceFactory.createDataSource(properties);

        } catch (IOException  e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //1.擷取連接配接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();//從資料源中擷取連接配接
    }
    //釋放連接配接資源
    public static void release(Connection con, Statement st, ResultSet re) throws SQLException {
        if (re!=null){
            re.close();
        }
        if (st!=null){
            st.close();
        }
        if (con!=null){
            con.close();
        }
    }
}

           

測試

package DBCP_C3P0;

import utils.JdbcUtils_DBCP;

import java.sql.*;

public class TestDBCP {
    public static void main(String[] args) throws SQLException {
        Connection con =null;
        PreparedStatement st=null;
        try {
            con= JdbcUtils_DBCP.getConnection();
            //差別
            //使用?占位符代替參數
            String sql="INSERT INTO users (`id`,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES (?,?,?,?,?)";
            st = con.prepareStatement(sql);//預編譯SQL,先寫sqL,然後不執行
            //手動給參數指派
            st.setInt(1,5);
            st.setString(2,"xiaojian");
            st.setString(3,"123456");
            st.setString(4,"[email protected]");
            //注意點:  sql.Date資料庫            java.sql.Date
            //          util.Date Java       new Date().getTime()   獲得時問戳
            st.setDate(5, new java.sql.Date(new java.util.Date().getTime()));
            //執行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils_DBCP.release(con,st,null);
        }
    }
}

           
C3PO

需要用到的jar包

c3p0-0.9.5.5、mchange-commons-java-0.2.19

配置檔案

<?xml version="1.0" encoding="UTF-8"?>
<!--
C3PO的預設(預設)配置,
如果在代碼中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”這樣寫就表示使用的是c3p0的預設(預設)配置資訊來建立資料源
-->
<c3p0-config>
    <default-config>
        <property name="driverClass" >com.mysql.cj.jdbc.Driver</property>
        <property name= "jdbcUrl" >jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true</property>
        <property name="user">root</property>
        <property name="password" >123456</property>
        <property name="acquirelncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </default-config>

<!--
C3PO的命名配置,
如果在代碼中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”這樣寫就表示使用的是name是MySQL的配置資訊來建立資料源
-->
    <named-config name="MySQL">
        <property name="driverClass" >com.mysql.cj.jdbc.Driver</property>
        <property name= "jdbcUrl" >jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true</property>
        <property name="user">root</property>
        <property name="password" >123456</property>
        <property name="acquirelncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>

           

C3P0工具類

package utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class JdbcUtils_C3P0 {

    private static ComboPooledDataSource dataSource=null;
    static {
        try{
//            //代碼版配置
//            dataSource =new ComboPooledDataSource();
//            dataSource.setDriverClass();
//            dataSource.setUser();
//            dataSource.setPassword();
//            dataSource.setJdbcUrl();
//            dataSource.setMaxPoolSize();
//            dataSource.setMinPoolSize();
            //建立資料源 工廠模式--> 建立
            dataSource = new ComboPooledDataSource("MySQL");//配置檔案寫法



        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //1.擷取連接配接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();//從資料源中擷取連接配接
    }
    //釋放連接配接資源
    public static void release(Connection con, Statement st, ResultSet re) throws SQLException {
        if (re!=null){
            re.close();
        }
        if (st!=null){
            st.close();
        }
        if (con!=null){
            con.close();
        }
    }
}

           

測試

package DBCP_C3P0;

import utils.JdbcUtils_C3P0;
import utils.JdbcUtils_DBCP;

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

public class TestC3P0 {
    public static void main(String[] args) throws SQLException {
        Connection con =null;
        PreparedStatement st=null;
        try {
            con= JdbcUtils_C3P0.getConnection();//原來是自己的實作的,現在用别人實作的

            //差別
            //使用?占位符代替參數
            String sql="INSERT INTO users (`id`,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES (?,?,?,?,?)";
            st = con.prepareStatement(sql);//預編譯SQL,先寫sqL,然後不執行
            //手動給參數指派
            st.setInt(1,4);
            st.setString(2,"xiaojian");
            st.setString(3,"123456");
            st.setString(4,"[email protected]");
            //注意點:  sql.Date資料庫            java.sql.Date
            //          util.Date Java       new Date().getTime()   獲得時問戳
            st.setDate(5, new java.sql.Date(new java.util.Date().getTime()));
            //執行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils_C3P0.release(con,st,null);
        }
    }
}

           
結論

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