目錄
- 初識MySQL
- 為什么學習資料庫
- 什么是資料庫
- 資料庫分類
- MySQL簡介
- Windows安裝MySQL
- 安裝建議
- 軟體下載
- 安裝步驟
- 安裝SQLyog
- 下載安裝
- 連接資料庫
- 簡單操作
- 命令列連接資料庫
- 操作資料庫
- SQL語言的分類
- 注意事項
- 操作資料庫
- 資料型別
- 數值
- 字串
- 日期時間
- 欄位屬性
- 操作資料表
- 修改表
- 資料庫引擎
- 資料表的字符集編碼
- MySQL資料管理
- 外鍵
- 插入資料
- 修改資料
- 洗掉資料
- 清空表
- delete和truncate的區別
- where子句運算子
- DQL資料查詢語言
- DQL
- 簡單查詢和別名(as)
- 拼接(concat)和去重(distinct)
- 查詢函式/計算運算式/系統變數
- where條件字句
- 邏輯運算子
- 模糊查詢:比較運算子
- 聯表查詢join
- 自連接
- 排序和分頁
- 分組和過濾
- 子查詢和嵌套查詢
- MySQL函式
- 常用函式
- 聚合函式
- 資料庫級別的MD5加密
- 事務
- 什么是事務
- 事務原則ACID原則
- 隔離導致的問題
- 手動處理事務
- 模擬轉賬
- 索引
- 索引的分類
- 索引的創建
- 測驗索引
- 插入100萬資料
- 分析查詢陳述句
- 結論
- 索引原則
- 索引的資料結構
- 權限管理和備份
- 用戶管理
- MySQL備份
- 規范資料庫設計
- 為什么需要設計
- 設計資料庫的步驟(個人博客)
- 三大范式
- 第一范式(1NF)-原子性
- 第二范式(2NF)
- 第三范式(3NF)
- 規范性和性能的問題
- JDBC
- 資料庫驅動
- JDBC
- 相關jar包
- 第一個JDBC程式
- 步驟總結
- DriverManager
- URL
- Statement
- 釋放資源
- 初次優化,提取工具類
- SQL注入問題
- PreparedStatement
- 為什么PreparedStatement能防止sql注入呢?
- 使用IDEA連接資料庫
- JDBC操作事務
- 資料庫連接池
- 常用連接池
初識MySQL
為什么學習資料庫
- 崗位需求
- 現在的世界,大資料時代,得資料者得天下
- 被迫需求:存資料
- 資料庫是所有軟體體系中最核心的存在
什么是資料庫
- 資料庫(DB,DataBase)
- 概念:資料倉庫,軟體,安裝在作業系統之上,
- 作用:存盤資料,管理資料,
資料庫分類
- 關系型資料庫(SQL)
- MySQL,Oracle,SQLServer,DB2,SQLlite
- 通過表和表之間,行和列之間的關系進行資料的存盤
- 非關系型資料庫(NoSQL-Not Only SQL)
- Redis,MongoDB
- 物件存盤,通過物件的屬性來決定,
- 資料庫管理系統(DBMS)
- 資料庫的管理軟體,科學有效的管理資料,維護和獲取資料,
- MySQL,資料庫管理系統,
MySQL簡介

- MySQL是一個關系型資料庫管理系統,
- 前世:瑞典MySQL AB 公司
- 今生:屬于Oracle旗下產品
- MySQL是最好的RDBMS(Relational Database Management System,關系資料庫管理系統) 應用軟體之一,
- 開源的資料庫軟體,
- 體積小、速度快、總體擁有成本低,招人成本比較低,所有人必須會!
- 中小型網站或者大型網站(集群),
- 官網:https://www.mysql.com
Windows安裝MySQL
安裝建議
- 盡量不要使用exe,卸載麻煩,注冊表
- 盡可能使用壓縮包安裝
軟體下載
- 下載地址:https://downloads.mysql.com/archives/community/
- MySQL5.7.31 64位下載地址:https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.31-winx64.zip
安裝步驟
- 解壓到安裝的目錄,如:D:\environment\mysql-5.7.31
- 添加環境變數
- 我的電腦-》屬性-》高級-》環境變數
- 選擇PATH,在其后添加:MySQL安裝目錄下的bin目錄路徑,如:D:\environment\mysql-5.7.31\bin
- 在MySQL安裝目錄D:\environment\mysql-5.7.31下新建my.ini檔案
- 編輯my.ini檔案
- 注意:data目錄不需要創建,會在初始化時自動生成
- 注意:skip-grant-tables是跳過密碼驗證,設定密碼后,需要注釋掉
[mysqld]
basedir=D:\environment\mysql-5.7.31\
datadir=D:\environment\mysql-5.7.31\data\
port=3306
skip-grant-tables
character-set-server=utf8
- 安裝MySQL服務:啟動管理員模式下的cmd,并將路徑切換到MySQL下的bin目錄,然后輸入mysqld -install,成功,回傳:Service successfully installed.
cd /d D:\environment\mysql-5.7.31\bin
mysqld -install
- 初始化資料檔案:輸入mysqld --initialize-insecure --user=mysql,成功,生成data目錄,data目錄下的目錄對應資料庫,如:mysql,sys,performance_schema,
mysqld --initialize-insecure --user=mysql

- 啟動MySQL:輸入net start mysql,成功,回傳:MySQL 服務正在啟動 MySQL服務已經啟動成功,并且任務管理器中出現MySQL服務,
net start mysql
- 進入MySQL管理界面:輸入mysql -u root -p,回車,不輸密碼,再回車,成功,
- 注意:-p后不能加空格,空格也是字符,也會認為是密碼,
- 注意:配置skip-grant-tables,會跳過密碼驗證,輸入密碼時,不需要輸入,直接回車,
- 注意:注釋掉skip-grant-tables后,有兩種輸入密碼方法:一是-p后直接回車,再輸入密碼;二是-p后直接輸密碼,再回車,如:mysql -u root -p123456,但是不推薦這樣,
mysql -u root -p
- 更改root密碼,其實就是修改mysql資料庫的user表的authentication_string欄位,password()函式用于md5加密,
update mysql.user set authentication_string=password('123456') where user='root' and Host='localhost';
- 重繪權限:flush privileges,
flush privileges;
- 注釋掉my.ini檔案中的skip-grant-tables,不再跳過密碼驗證,
[mysqld]
basedir=D:\environment\mysql-5.7.31\
datadir=D:\environment\mysql-5.7.31\data\
port=3306
#skip-grant-tables
character-set-server=utf8
- 重啟mysql:net stop mysql,net start mysql
# 退出mysql
exit
# 關閉mysql
net stop mysql
# 啟動mysql
net start mysql
- 測驗,
C:\Users\Administrator>mysql -u root -p
Enter password: ******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15
Server version: 5.7.29 MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
安裝SQLyog
下載安裝
- 下載地址:https://sqlyog.en.softonic.com/
- SQLyog-13.1.6下載地址:https://gsf-fl.softonic.com/1ce/278/b337b72b7ac51c9fcc627a7e1aa8a7710b/SQLyog-13.1.6-0.x64Community.exe?Expires=1609550838&Signature=d64bccebb6402a44cda8f80f9016fa852af514d0&url=https://sqlyog.en.softonic.com&Filename=SQLyog-13.1.6-0.x64Community.exe
- 按提示安裝,免費版不需要注冊,專業版需要注冊,如果注冊,可以嘗試下面的注冊碼,
- 注冊名:kuangshen
- 注冊碼:8d8120df-a5c3-4989-8f47-5afc79c56e7c

連接資料庫

簡單操作
- 新建資料庫school,基字符集:utf8,資料庫排序規則:utf8_general_ci,
utf8_unicode_ci和utf8_general_ci對中、英文來說沒有實質的差別,
utf8_general_ci 校對速度快,但準確度稍差,
utf8_unicode_ci 準確度高,但校對速度稍慢,
如果你的應用有德語、法語或者俄語,請一定使用utf8_unicode_ci,一般用utf8_general_ci就夠了,
ci是 case insensitive, 即 "大小寫不敏感", a 和 A 會在字符判斷中會被當做一樣的;
bin 是二進制, a 和 A 會別區別對待,
例如你運行:
SELECT * FROM table WHERE txt = 'a'
那么在utf8_bin中你就找不到 txt = 'A' 的那一行, 而 utf8_general_ci 則可以,
utf8_general_ci 不區分大小寫,這個你在注冊用戶名和郵箱的時候就要使用,
utf8_general_cs 區分大小寫,如果用戶名和郵箱用這個 就會照成不良后果
utf8_bin:字串每個字串用二進制資料編譯存盤, 區分大小寫,而且可以存二進制的內容

每一個SQLyog的執行操作,本質就是對應了一個SQL陳述句,都可以在軟體的歷史記錄中查看,
如:創建資料庫,在歷史記錄中如下,本質是執行陳述句:CREATE DATABASEschoolCHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE DATABASE `school`CHARACTER SET utf8 COLLATE utf8_general_ci;
- 新建表student,引擎:InnoDB,字符集:utf8,核對:utf8_general_ci,

對應陳述句如下
CREATE TABLE `school`.`student` ( `id` INT(10) NOT NULL COMMENT '學員ID', `name` VARCHAR(100) NOT NULL COMMENT '學員姓名', `age` INT(3) NOT NULL COMMENT '學員年齡', PRIMARY KEY (`id`) ) ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci;
- 查看表:右鍵點擊student,打開表資料視窗,查看表資料視窗,

- 添加記錄:在表資料視窗,輸入記錄,點擊保存或者點擊重繪,保存記錄,
INSERT INTO `school`.`student` (`id`, `name`, `age`) VALUES ('1003', 'zhwj', '66');
命令列連接資料庫
單行注釋:--
多行注釋:/* */
mysql -u root -p --連接資料庫
exit; --退出連接
update mysql.user set authentication_string=password('123456') where user='root' and Host='localhost'; --修改用戶密碼
flush privileges; --重繪權限
--------------------------------------------------
show databases; --查看所有的資料庫
use school; --切換資料庫
show tables; --查看資料庫中所有的表
describe student; --查看表的結構
describe student id; --查看表中欄位id的資訊
create database westos; --創建資料庫
CREATE DATABASE `school`CHARACTER SET utf8 COLLATE utf8_general_ci; --創建資料庫
操作資料庫
SQL語言的分類
SQL語言共分為四大類:資料查詢語言DQL,資料操縱語言DML,資料定義語言DDL,資料控制語言DCL,
注意事項
- 學習順序:操作資料庫>操作資料表>操作資料,
- mysql關鍵字不區分大小寫,
- 單行注釋:--
- 多行注釋:/* */
- 字符集的區別:utf8_unicode_ci、utf8_general_ci、utf8_general_cs、utf8_bin,
utf8_unicode_ci和utf8_general_ci對中、英文來說沒有實質的差別,
utf8_general_ci 校對速度快,但準確度稍差,
utf8_unicode_ci 準確度高,但校對速度稍慢,
如果你的應用有德語、法語或者俄語,請一定使用utf8_unicode_ci,一般用utf8_general_ci就夠了,
ci是 case insensitive, 即 "大小寫不敏感", a 和 A 會在字符判斷中會被當做一樣的;
bin 是二進制, a 和 A 會別區別對待,
例如你運行:
SELECT * FROM table WHERE txt = 'a'
那么在utf8_bin中你就找不到 txt = 'A' 的那一行, 而 utf8_general_ci 則可以,
utf8_general_ci 不區分大小寫,這個你在注冊用戶名和郵箱的時候就要使用,
utf8_general_cs 區分大小寫,如果用戶名和郵箱用這個 就會照成不良后果
utf8_bin:字串每個字串用二進制資料編譯存盤, 區分大小寫,而且可以存二進制的內容
- 如果表名或者欄位名是一個特殊字符,需要加反引號(tab鍵上面的符號),如:
user,
操作資料庫
- 創建資料庫
utf8_unicode_ci和utf8_general_ci對中、英文來說沒有實質的差別,
utf8_general_ci 校對速度快,但準確度稍差,
utf8_unicode_ci 準確度高,但校對速度稍慢,
如果你的應用有德語、法語或者俄語,請一定使用utf8_unicode_ci,一般用utf8_general_ci就夠了,
ci是 case insensitive, 即 "大小寫不敏感", a 和 A 會在字符判斷中會被當做一樣的;
bin 是二進制, a 和 A 會別區別對待,
例如你運行:
SELECT * FROM table WHERE txt = 'a'
那么在utf8_bin中你就找不到 txt = 'A' 的那一行, 而 utf8_general_ci 則可以,
utf8_general_ci 不區分大小寫,這個你在注冊用戶名和郵箱的時候就要使用,
utf8_general_cs 區分大小寫,如果用戶名和郵箱用這個 就會照成不良后果
utf8_bin:字串每個字串用二進制資料編譯存盤, 區分大小寫,而且可以存二進制的內容
CREATE DATABASE IF NOT EXISTS westos;
CREATE DATABASE IF NOT EXISTS westos1 CHARACTER SET utf8 COLLATE utf8_general_ci;
- 洗掉資料庫
DROP DATABASE IF EXISTS westos1;
- 使用資料庫
USE school; --切換資料庫
USE `school`; --如果表名或欄位名是一個特殊字符,需要加反引號,如:`school`
- 查看資料庫
SHOW DATABASES; --查看所有資料庫
- 查看創建資料庫的陳述句
SHOW CREATE DATABASE `school`; --查看創建資料庫的陳述句
--查詢結果
CREATE DATABASE `school` /*!40100 DEFAULT CHARACTER SET utf8 */
資料型別
數值
| 型別 | 位元組數 | 含義 | 備注 | 對應java |
|---|---|---|---|---|
| tinyint | 1個位元組 | 十分小的數 | Integer | |
| smallint | 2個位元組 | 較小的數 | Integer | |
| mediumint | 3個位元組 | 中等的數 | Integer | |
| int | 4個位元組 | 整數 | 常用 | Long |
| bigint | 8個位元組 | 較大的數 | BigInteger | |
| float | 4個位元組 | 浮點數 | 不常用,會精度丟失 | Float |
| double | 8個位元組 | 浮點數 | 不常用,會精度丟失 | Double |
| decimal | 字串形式的浮點數 | 金融計算時常用 | BigDecimal |
字串
| 型別 | 長度 | 含義 | 備注 | 對應java |
|---|---|---|---|---|
| char | 0~255 | 固定大小字串 | String | |
| varchar | 0~65535 | 可變字串 | 常用 | String |
| tinytext | 2^8 - 1 | 微型文本 | String | |
| text | 2^16 - 1 | 文本串 | 常用,保存大文本 | String |
日期時間
| 型別 | 格式 | 含義 | 備注 | 對應java |
|---|---|---|---|---|
| date | YYYY-MM-DD | 日期 | Date | |
| time | HH:mm:ss | 時間 | Time | |
| datetime | YYYY-MM-DD HH:mm:ss | 日期+時間 | 常用 | Timestamp |
| timestamp | 時間戳,1970.1.1到現在的毫秒數 | 常用 | Timestamp | |
| year | YYYY | 年份 | Date |
欄位屬性
- Unsigned
- 無符號數
- 宣告了該欄位的值不能為負數
- 如果添加負數,就會報錯
- zerofill
- 0填充
- 不足的位數,前面用0填充,如:0030
- 自增
- 默認自動在上一條記錄的基礎上+1,可以自定義起始值和步長
- 通常用來設計唯一的主鍵
- 非空
- 設定為非空not null時,如果不給它賦值且沒有設定默認值時,就會報錯
- null,如果不填寫值,默認就是null
- 默認
- 設定默認的值,如果不填值,就會設定為默認值
- 設定默認的值,如果不填值,就會設定為默認值
操作資料表
- 創建表
-- 如果表名或者欄位名是一個特殊字符,需要加反引號(tab鍵上面的符號),如:`student`
-- AUTO_INCREMENT 自增,默認+1
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '學號',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密碼',
`sex` VARCHAR(1) NOT NULL DEFAULT '女' COMMENT '性別',
`birthday` DATE DEFAULT NULL COMMENT '出生日期',
`address` VARCHAR(100) DEFAULT NULL COMMENT '地址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '學員';
-- 格式
CREATE TABLE [IF NOT EXISTS] `表名` (
`欄位名` 列型別 [屬性] [索引] [注釋],
......
`欄位名` 列型別 [屬性] [索引] [注釋],
PRIMARY KEY (`欄位名`)
) [表型別] [字符集] [校對規則] [表注釋];
- 洗掉表
DROP TABLE IF EXISTS `student`;
- 查看表
SHOW TABLES; --查看所有表
- 查看表結構
DESCRIBE `student`;
DESC `student`;
- 查看創建資料表的陳述句
SHOW CREATE TABLE `student`; --查看創建資料表的陳述句
--查詢結果
CREATE TABLE `student` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '學號',
`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密碼',
`sex` varchar(1) NOT NULL DEFAULT '女' COMMENT '性別',
`birthday` date DEFAULT NULL COMMENT '出生日期',
`address` varchar(100) DEFAULT NULL COMMENT '地址',
`email` varchar(50) DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='學員'
修改表
- 修改表名
-- ALTER TABLE `舊表名` RENAME AS `新表名`;
ALTER TABLE `student` RENAME AS `student1`;
- 增加欄位
-- ALTER TABLE `表名` ADD `欄位名` 資料型別 [約束] [注釋];
ALTER TABLE `student1` ADD `phone` INT(11) DEFAULT NULL COMMENT '電話';
- 修改欄位名及欄位型別、約束、注釋,注意:欄位名欄位型別必填,其它可選,
-- ALTER TABLE `表名` CHANGE `舊欄位名` `新欄位名` 欄位型別 [約束] [注釋];
ALTER TABLE `student1` CHANGE `phone` `tel` VARCHAR(11) NOT NULL DEFAULT '' COMMENT '聯系方式';
- 修改欄位型別、約束、注釋,注意:欄位型別必填,其它可選,不能修改欄位名,
-- ALTER TABLE `表名` MODIFY `欄位名` 欄位型別 [約束] [注釋];
ALTER TABLE `student1` MODIFY `tel` INT(11) DEFAULT NULL COMMENT '電話';
- 洗掉欄位
-- ALTER TABLE `表名` DROP `欄位名`;
ALTER TABLE `student1` DROP `tel`;
資料庫引擎
-
INNODB 5.5及之后默認使用
-
MYISAM 5.5之前默認使用
| | MYISAM | INNODB |
| --- | --- | --- |
| 事務支持 | 不支持 | 支持 |
| 資料行鎖定 | 不支持 (表鎖) | 支持 (行鎖) |
| 外鍵約束 | 不支持 | 支持 |
| 全文索引 | 支持 | 不支持 |
| 表空間的大小 | 較小 | 較大,約為2倍 | -
常規使用操作
- MYISAM 節約空間,速度較快
- INNODB 安全性高,事務的處理,多表多用戶操作
-
所有的資料庫檔案都存在data目錄下,一個目錄對應一個資料庫,本質還是檔案的存盤,
-
mysql引擎在物理檔案上的區別
- INNODB對應檔案
- *.frm 資料庫目錄下
- ibdata1 data目錄下
- MYISAM對應檔案都在資料庫目錄下
- *.frm 表結構定義檔案
- *.MYD 資料檔案(data)
- *.MYI 索引檔案(index)
- INNODB對應檔案
資料表的字符集編碼
- mysql默認的字符集編碼是Latin1,不支持中文,
- 設定資料表字符集編碼的兩種方式,兩種方式最好同時使用,防止創建表時,沒有設定字符集編碼,導致中文亂碼,
- 創建表時添加CHARSET=utf8
- 在my.ini中配置默認編碼character-set-server=utf8
CHARSET=utf8
character-set-server=utf8
MySQL資料管理
外鍵
- 創建表時,增加外鍵約束
-- 創建年級表
CREATE TABLE IF NOT EXISTS `grade` (
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` VARCHAR(100) NOT NULL COMMENT '名稱',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '年級';
-- 創建學生表,學生表的grade_id欄位參考年級表的id欄位
-- 定義外鍵key
-- 給這個外鍵添加約束(執行參考(reference))
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` VARCHAR(100) NOT NULL COMMENT '名稱',
`grade_id` INT(10) NOT NULL COMMENT '年級id',
PRIMARY KEY (`id`),
KEY `FK_grade_id` (`grade_id`),
CONSTRAINT `FK_grade_id` FOREIGN KEY (`grade_id`) REFERENCES `grade` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '學員';
- 洗掉有外鍵關系的表時,必須先洗掉參考的表(從表),再洗掉被參考的表(主表)
- 添加外鍵
-- 創建年級表
CREATE TABLE IF NOT EXISTS `grade` (
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` VARCHAR(100) NOT NULL COMMENT '名稱',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '年級';
-- 創建學員表
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` VARCHAR(100) NOT NULL COMMENT '名稱',
`grade_id` INT(10) NOT NULL COMMENT '年級id',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '學員';
-- 添加外鍵
-- ALTER TABLE `表名` ADD CONSTRAINT `FK_grade_id` FOREIGN KEY (`grade_id`) REFERENCES `grade` (`id`);
ALTER TABLE `student`
ADD CONSTRAINT `約束名` FOREIGN KEY (`作為外鍵的欄位名`) REFERENCES `被參考表名` (`被參考欄位名`);
- 物理外鍵,是資料庫級別的外鍵,不建議使用,
- 最佳實踐
- 資料庫就是單純的表,只用來存資料,只有行(資料)和列(欄位)
- 想使用多張表的資料,想使用外鍵,就用程式來實作
插入資料
-- insert into 表名(欄位1,欄位2,欄位3) values(值1,值2,值3)
-- 主鍵自增,可以不寫
INSERT INTO `grade`(`name`) VALUES('大一');
-- 插入一條資料,部分欄位
INSERT INTO `grade`(`name`) VALUES('大二');
-- 插入一條資料,全部欄位
INSERT INTO `grade`(`id`,`name`) VALUES(11,'大三');
-- 插入多條資料時,values后面的值,需要用括號和逗號隔開,如:values(),(),()
-- 插入多條資料,部分欄位
INSERT INTO `grade`(`name`) VALUES('大四'),('大五'),('大六');
-- 插入多條資料,全部資料
INSERT INTO `grade`(`id`,`name`) VALUES(100,'大旗'),(200,'大壩'),(300,'大酒');
修改資料
-- update `表名` set 欄位名1=值/其它欄位值/變數,欄位名2=值 where 條件
-- 修改一個欄位的值
UPDATE `grade` SET `name`='小一' WHERE `id`=1;
-- 修改一個欄位的值為其它欄位的值
UPDATE `grade` SET `name`=`id` WHERE `id`=11;
-- 修改多個欄位的值
UPDATE `grade` SET `id`=20,`name`='小二' WHERE `id`=2;
洗掉資料
-- delete from `表名` where 條件
DELETE FROM `grade` WHERE `id`=1;
清空表
-- truncate table `表名`
TRUNCATE TABLE `grade`;
delete和truncate的區別
- truncate重新設定自增列,計數器歸零,
- delete自增列不變;但重啟資料庫后,引擎是INNODB的,自增列會從1開始(存在記憶體中,斷電即失);引擎是MYISAM的,自增列不變(存在檔案中,不會丟失),
- truncate不會影響事務,
where子句運算子
| 運算子 | 含義 |
|---|---|
| = | 等于 |
| <> 或 != | 不等于 |
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| between ... and ... | 在某個范圍內 型別是數字時,包括頭和尾 型別是date時,包括頭和尾 型別是datetime時,帶時分秒,包括頭和尾;不帶時分秒,包頭不包尾 |
| and | 與 |
| or | 或 |
DQL資料查詢語言
DQL
- 資料庫中最核心的語言,最重要的語言,
- 使用頻率最高的語言,
簡單查詢和別名(as)
-- 查詢全部欄位
SELECT * FROM `grade`;
-- 查詢指定欄位
SELECT `name` FROM `grade`;
-- 別名 AS,欄位和表都可以用別名
SELECT `name` AS `名稱` FROM `grade`;
拼接(concat)和去重(distinct)
-- 函式 concat(a,b,c) 拼接abc,可以拼接字串或欄位值
SELECT CONCAT('名稱:',`name`) AS `名稱` FROM `grade`;
SELECT CONCAT(`id`,':',`name`) AS `id:名稱` FROM `grade`;
-- 關鍵字 distinct 去重
-- 去除select查詢出來的結果中重復的資料,重復的資料只顯示一條
-- 去重一般配合count使用,用來統計數量,因為distinct不能顯示其它不去重的欄位
-- 單個欄位去重
SELECT DISTINCT `name` FROM `grade`;
-- 多個欄位去重
SELECT DISTINCT `id`,`name` FROM `grade`;
-- 配合count使用,用來統計數量
SELECT COUNT(DISTINCT `name`) AS `count` FROM `grade`;
查詢函式/計算運算式/系統變數
資料庫中的運算式:文本值、列、null、函式、計算運算式、系統變數......
-- select 運算式 [from 表名]
-- 查詢系統版本(函式)
SELECT VERSION();
SELECT VERSION(),`name` FROM `grade`;
-- 用來計算(計算運算式)
SELECT 123*3-12 AS `結果`;
SELECT 123*3-12 AS `結果`,`name` FROM `grade`;
-- 數字型別的欄位計算,其它型別不可以
SELECT `id`/100 FROM `grade`;
-- 查詢自增的默認步長(變數)
-- @a用戶變數,@@a系統變數
SELECT @@auto_increment_increment AS '自增步長';
SELECT @@auto_increment_increment AS '自增步長',`name` FROM `grade`;
where條件字句
- 作用:檢索資料中符合條件的值,
- 檢索的條件由一個或者多個運算式組成,
邏輯運算子
運算子盡量使用英文字母
| 運算子 | 語法 | 描述 |
|---|---|---|
| and && | a and b a && b | 邏輯與 |
| or | ||
| not ! | not a ! a | 邏輯非 |
-- 查詢成績95到100分的學員
select `name`,`score` from `result` where `score`>=95 and `score`<=100;
select `name`,`score` from `result` where `score` between 95 and 100;
-- 查詢成績不是100分的學員
select `name`,`score` from `result` where `score`!=100;
select `name`,`score` from `result` where not `score`=100;
模糊查詢:比較運算子
| 運算子 | 語法 | 描述 |
|---|---|---|
| is null | a is null | 為null |
| is not null | a is not null | 不為null |
| between ... and ... | a between b and c a betwwen 5 and 10 |
在某個范圍內 型別是數字時,包括頭和尾 型別是date時,包括頭和尾 型別是datetime時,帶時分秒,包括頭和尾;不帶時分秒,包頭不包尾 |
| like | a like b a like 'b' a like '%b' a like 'b%' a like '%b%' a like '_b' alike 'b' |
a匹配b 通配符,只能用在like中 %代表0到任意個字符,_代表一個字符 |
| in | a in (a1,a2,a3...) | a是否在括號中的值中 |
-- 通配符,只能用在like中 %代表0到任意個字符,_代表一個字符
select 'name' like '%me';
select 'name' like 'na%';
select 'name' like '%am%';
select 'name' in ('name','na','me');
聯表查詢join

| 操作 | 描述 |
|---|---|
| inner join | 兩個表都必須匹配 |
| left join | 左表為主表,左表全部,右表沒有補null |
| right join | 右表為主表,右表全部,左表沒有補null |
自連接
-- 自連接:可以把一張表看成兩張一樣的表
select a.`id` as '父', b.`id` as '子'
from `menu` as a,`menu` as b
where a.`id`=b.`pid`
排序和分頁
-- 排序 order by
-- 升序 asc
-- 降序 desc
order by `number` desc
-- 分頁 limit 起始下標,條數
-- 起始下標從0開始
limit 0,5
-- 第一頁 limit 0,5
-- 第二頁 limit 5,5
-- 第三頁 limit 10,5
-- 第n頁 limit (n-1) * pageSize, pageSize
-- n:當前頁 pageSize:條數
分組和過濾
group by 分組
having 過濾
子查詢和嵌套查詢
-- 子查詢
select id,name from student
where grade_id=(select id from grade where name='大二')
MySQL函式
常用函式
-- 數學運算
SELECT ABS(-8); -- 絕對值
SELECT CEILING(9.4); -- 向上取整
SELECT FLOOR(9.4); -- 向下取整
SELECT RAND(); -- 回傳一個0到1的亂數
SELECT SIGN(-10); -- 判斷一個數的符號
-- 字串函式
SELECT CHAR_LENGTH('走在路上,,,'); -- 回傳字串長度,以字符為單位
SELECT LENGTH('走在路上,,,'); -- 回傳字串長度,以位元組為單位
SELECT CONCAT('走','在','路','上'); -- 拼接字串
SELECT INSERT('我在路上',1,2,'你好嗎') ; -- 插入替換,從某個位置開始替換指定長度
SELECT LOWER('Hello'); -- 轉小寫
SELECT UPPER('hello'); -- 轉大寫
SELECT INSTR('helloworld','l'); -- 回傳第一次出現子串的索引
SELECT REPLACE('hello','ll','ss'); -- 替換出現的指定字串
SELECT SUBSTR('helloworld',2,5); -- 回傳指定的子字串(源字串,截取的位置,截取的長度)
-- 時間和日期函式
SELECT CURDATE(); -- 獲取當前日期
SELECT CURTIME(); -- 獲取當前時間
SELECT NOW(); -- 獲取當前日期和時間
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(); -- 查詢版本
聚合函式
| 函式名稱 | 描述 |
|---|---|
| count() | 計數 |
| sum() | 求和 |
| avg() | 平均值 |
| max() | 最大值 |
| min() | 最小值 |
| ...... |
-- 聚合函式
SELECT COUNT(`name`) FROM student; -- count(欄位),會忽略所有的null值,欄位是主鍵時,效率最高
SELECT COUNT(*) FROM student; -- count(*),不會忽略null值,本質是計算行數
SELECT COUNT(1) FROM student; -- count(1),不會忽略null值,本質是計算行數
資料庫級別的MD5加密
- 什么是MD5?

- 1996年后該演算法被證實存在弱點,可以被加以破解,對于需要高度安全性的資料,專家一般建議改用其他演算法,如SHA-2,2004年,證實MD5演算法無法防止碰撞(collision),因此不適用于安全性認證,如SSL公開密鑰認證或是數字簽名等用途,
- MD5由MD4、MD3、MD2改進而來,主要增強演算法復雜度和不可逆性,MD5演算法因其普遍、穩定、快速的特點,仍廣泛應用于普通資料的加密保護領域,
- MD5不可逆,兩個相同的值加密后的值是一樣的,
- MD5破解網站的原理,就是背后有一個字典,根據MD5加密后的值找加密前的值,只能找到簡單密碼,
-- 測驗MD5加密
CREATE TABLE `testmd5`(
`id` INT(4) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`pwd` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
-- 明文加密
INSERT INTO `testmd5` VALUES(1,'zhangs','123456'),(2,'lis','123456'),(3,'wangw','123456');
-- MD5加密
INSERT INTO `testmd5` VALUES(4,'zhaol',MD5('123456')),(5,'maq',MD5('123456'));
-- 校驗密碼
SELECT * FROM `testmd5` WHERE `name`='zhaol' AND `pwd`=MD5('123456');
事務
什么是事務
- 要么都成功,要么都失敗,
- 將一組SQL放在一個批次中去執行,
事務原則ACID原則

- 原子性:多個步驟要么一起成功,要么一起失敗,不能只成功一個,(同進同退)
- 一致性:最終一致性,開始前的總值等于結束后的總值,(能量守恒)
- 隔離性:針對多個用戶同時操作,其他事務不會影響本次事務,(互不干擾)
- 持久性:事務沒有提交,恢復到原狀,事務一旦提交,不可改變,(不可逆)
隔離導致的問題
- 臟讀:一個事務讀取了另一個事務未提交的資料,
- 不可重復讀:在一個事務內讀取表中的一行資料,多次讀取結果不同,
- 虛度(幻讀):一個事務內讀取到了別的事務插入的資料,導致前后讀取不一致,
手動處理事務
-- 事務
/*
mysql默認開啟事務自動提交
set autocommit=0; -- 關閉
set autocommit=1; -- 開啟(默認)
*/
-- 手動處理事務
SET autocommit=0; -- 關閉自動提交
-- 事務開啟
START TRANSACTION -- 標記一個事務的開始,從這之后的SQL都在同一個事務內
INSERT xx;
INSERT xx;
-- 提交 commit
COMMIT;
-- 回滾 rollback
ROLLBACK;
-- 事務結束
SET autocommit=1; -- 開啟自動提交
-- 了解即可
SAVEPOINT 保存點 -- 設定一個事務的保存點
ROLLBACK TO SAVEPOINT 保存點 -- 回滾到保存點
RELEASE SAVEPOINT 保存點 -- 撤銷保存點
模擬轉賬
-- 轉賬
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 COLLATE=utf8_general_ci;
INSERT INTO `account`(`name`,`money`) VALUES('A','2000'),('B','10000');
-- 模擬轉賬:事務
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; -- 開啟自動提交
SELECT @@autocommit; -- 查詢自動提交狀態
索引
MySQL官方對索引的定義為: 索引(Index)是幫助MySQL高效獲取資料的資料結構,提取句子主干,就可以得到索引的本質:索引是資料結構,
索引的分類
- 主鍵索引(PRIMARY KEY)
- 唯一的標識,值不可重復,只能有一個列作為主鍵
- 唯一索引(UNIQUE KEY)
- 避免重復的列出現,值不可重復,可以多個列都標識為唯一索引
- 常規索引(KEY/INDEX)
- 默認的,index或key關鍵字來設定
- 全文索引(FullText)
- 在特定的資料庫引擎下才有,之前MyISAM支持,現在InnoDB也在支持,具體自查
- 快速定位資料
索引的創建
-- 顯示所有索引
SHOW INDEX FROM `student`;
-- 索引的創建
-- 1.在創建表的時候給欄位增加索引
-- 2.創建完畢后,alter增加索引
-- 3.創建完畢后,create增加索引
-- 索引命名:id_表名_欄位名
-- 添加索引:create index 索引名 on 表名 (欄位名);
CREATE INDEX `id_user_name` ON `user` (`name`); -- 15.772 sec
-- 增加一個全文索引 索引名(列名)
ALTER TABLE `student` ADD FULLTEXT INDEX `studentName` (`studentName`);
-- EXPLAIN 分析SQL執行的狀況
EXPLAIN SELECT * FROM `student`; -- 非全文索引
EXPLAIN SELECT * FROM `student` WHERE MATCH(`studentName`) AGAINST('劉'); -- 全文索引
測驗索引
插入100萬資料
CREATE TABLE `user`(
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`phone` VARCHAR(20) NOT NULL,
`pwd` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
-- 插入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 `user`(`name`,`phone`,`pwd`) VALUES(CONCAT('用戶',i),CONCAT('18',FLOOR(RAND()*1000000000)),UUID());
SET i=i+1;
END WHILE;
RETURN i;
END;
SELECT mock_data();
SELECT COUNT(`id`) FROM `user`;
分析查詢陳述句
SELECT * FROM `user` WHERE `name`='用戶9999'; -- 0.748 sec
SELECT * FROM `user` WHERE `name`='用戶9999'; -- 0.689 sec
SELECT * FROM `user` WHERE `name`='用戶9999'; -- 0.765 sec
EXPLAIN SELECT * FROM `user` WHERE `name`='用戶9999';
-- 索引命名:id_表名_欄位名
-- 添加索引:create index 索引名 on 表名 (欄位名);
CREATE INDEX `id_user_name` ON `user` (`name`); -- 15.772 sec
SELECT * FROM `user` WHERE `name`='用戶9999'; -- 0.052 sec
SHOW INDEX FROM `user`;
ALTER TABLE `user` DROP INDEX `id_user_name`;
創建索引前查詢
創建索引后查詢
結論
索引在小資料量的時候,用處不大,但是在大資料量的時候,區別十分明顯,
索引原則
- 索引不是越多越好
- 不要對經常變動資料的表加索引
- 小資料量的表不需要加索引
- 索引一般加在常用來查詢的欄位上
索引的資料結構
- InnoDB的默認索引資料結構是Btree
- Hash
權限管理和備份
用戶管理
- 用戶表:mysql.user
- 用戶管理本質是對用戶表資料的增刪改查
-- 創建用戶 CREATE USER 用戶名 IDENTIFIED BY '密碼';
CREATE USER qing IDENTIFIED BY '123456';
-- 修改當前用戶密碼
SET PASSWORD=PASSWORD('123456');
-- 修改指定用戶密碼
SET PASSWORD FOR qing=PASSWORD('123456');
-- 重命名 RENAME USER 原用戶名 TO 新用戶名;
RENAME USER qing TO qing2;
-- 用戶授權 GRANT ALL PRIVILEGES ON 庫.表 TO 用戶名;
-- ALL PRIVILEGES 除了給人授權外的其他權限
-- *.* 所有庫和表
GRANT ALL PRIVILEGES ON *.* TO qing2;
-- 查詢權限
SHOW GRANTS FOR qing2; -- 查看指定用戶的權限
-- qing2權限 GRANT ALL PRIVILEGES ON *.* TO 'qing2'@'%'
SHOW GRANTS FOR root@'%';
-- root權限 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION
-- 撤銷權限 REVOKE ALL PRIVILEGES ON 庫.表 FROM 用戶名;
REVOKE ALL PRIVILEGES ON *.* FROM qing2;
-- 洗掉用戶
DROP USER qing2;
MySQL備份
- 為什么要備份?
- 保證重要的資料不丟失
- 資料轉移
- MySQL資料庫備份的方式
- 直接拷貝物理檔案data目錄
- 使用可視化工具中的匯出功能
- 使用命令列匯出 mysqldump
# 匯出表
# mysqldump -h IP -u 用戶名 -p 密碼 資料庫 表名 >盤符/檔案名
C:\Users\Administrator>mysqldump -hlocalhost -uroot -p123456 school student >d:/a.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
# 匯出多個表
mysqldump -h192.168.10.226 -uroot -p123456 school grade >d:/a.sql
# 匯出庫
mysqldump -h192.168.10.226 -uroot -p123456 school >d:/a.sql
# 匯入
# 登錄的情況下,切換到指定的資料庫
# source 備份檔案
source d:/a.sql
D:\>mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use school;
Database changed
mysql> source d:/a.sql;
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
# 或者 mysql -u用戶名 -p密碼 庫名< 備份檔案
規范資料庫設計
為什么需要設計
- 當資料庫比較復雜的時候,我們就需要設計了
- 糟糕的資料庫設計
- 資料冗余,浪費空間
- 資料庫插入和洗掉都會麻煩、例外(屏蔽使用物理外鍵)
- 程式的性能差
- 良好的資料庫設計
- 節省記憶體空間
- 保證資料庫的完整性
- 方便我們開發系統
- 軟體開發中,關于資料庫的設計
- 分析需求:分析業務和需要處理的資料庫需求
- 概要設計:設計關系圖 E-R圖
設計資料庫的步驟(個人博客)
- 收集資訊,分析需求
- 用戶表(用戶登錄注銷,用戶的個人資訊,寫博客,創建分類)
- 分類表(文章分類,誰創建的)
- 文章表(文章資訊)
- 友鏈表(友鏈資訊)
- 自定義表(系統資訊,關鍵字,主欄位)
- 標識物體(將需求落地為具體的表、欄位)
三大范式
第一范式(1NF)-原子性
原子性:保證每一列不可再分
第二范式(2NF)
前提:滿足第一范式
每張表只描述一件事情
第三范式(3NF)
前提:滿足第一范式和第二范式
確保資料表中的每一列資料都和主鍵直接相關,而不能間接相關,
規范性和性能的問題
關聯查詢的表不得超過三張表
- 考慮商業化的需求和目標(成本,用戶體驗),資料庫的性能更加重要
- 在考慮性能的時候,需要適當的考慮一下規范性
- 故意給某些表增加一些冗余的欄位(從多表關聯查詢變為單表查詢)
- 故意增加一些統計列(從大資料量的統計降低為小資料量的查詢)
JDBC
資料庫驅動
程式通過資料庫驅動,和資料庫打交道,
JDBC
- SUN公司為了簡化開發人員對資料庫的統一操作,提供了一個Java操作資料庫的規范,俗稱JDBC,
- 這些規范的實作由具體的廠商去做,
- 對于開發人員來說,我們只需要掌握JDBC介面的操作即可,

相關jar包
- java.sql
- javax.sql
- 資料庫驅動包 mysql-connector-java-5.1.49.jar
第一個JDBC程式
- 創建測驗資料庫,
CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbcStudy;
CREATE TABLE users(
`id` INT(10) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`pwd` VARCHAR(100) NOT NULL,
`email` VARCHAR(100),
`birthday` DATE,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO `users`(`id`,`name`,`pwd`,`email`,`birthday`)
VALUES(1,'zhangsf','123456','[email protected]','1988-03-13'),
(2,'zhangwj','123456','[email protected]','1983-04-03'),
(3,'zhangyq','123456','[email protected]','1989-05-23');
- 創建一個普通專案,

- 匯入資料庫驅動,
- 創建lib目錄,拷貝mysql-connector-java-5.1.49.jar
- 添加到專案庫,右鍵點擊Add as Library



- 撰寫測驗代碼,

package com.qing.demo01;
import java.sql.*;
/**
* 第一個JDBC程式
*/
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加載驅動
Class.forName("com.mysql.jdbc.Driver");
//2.用戶資訊和url
//useUnicode=true 支持中文編碼
//characterEncoding=utf8 設定中文字符集編碼為utf8
//useSSL=true 使用安全的連接,如果服務器沒有SSL證書會報錯,使用false
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";
String user = "root";
String password = "123456";
//3.連接成功,獲取資料庫物件Connection
Connection connection = DriverManager.getConnection(url,user,password);
//4.創建執行SQL的物件
Statement statement = connection.createStatement();
//5.執行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("pwd=" + resultSet.getObject("pwd"));
System.out.println("email=" + resultSet.getObject("email"));
System.out.println("birthday=" + resultSet.getObject("birthday"));
System.out.println("=====================================");
}
//6.釋放連接
resultSet.close();
statement.close();
connection.close();
}
}
步驟總結
- 加載驅動
- 連接資料庫 DriverManager
- 創建執行SQL的物件 Statement
- 獲取回傳的結果集
- 釋放連接
DriverManager
//驅動管理
//DriverManager.registerDriver(new Driver());
//加載驅動,建議使用,Driver類中的靜態代碼塊就是執行的上面的方法
Class.forName("com.mysql.jdbc.Driver");
//連接資料庫
Connection connection = DriverManager.getConnection(url,user,password);
//Connection代表資料庫物件,可以執行資料庫層面的操作
//資料庫設定自動提交
connection.setAutoCommit(false);
connection.setAutoCommit(true);
//事務提交
connection.commit();
//事務回滾
connection.rollback();
URL
//資料庫連接資訊
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";
//String url = "jdbc:mysql://主機地址:埠號/資料庫名?引數1&引數2&引數3";
Statement

//執行SQL的物件
boolean execute = statement.execute("");//執行任何SQL,但需要判斷,效率最低
ResultSet resultSet = statement.executeQuery();//執行查詢,回傳查詢結果集
int i = statement.executeUpdate();//執行更新、插入、洗掉,回傳受影響的行數
插入示例
洗掉示例
更新示例
查詢示例
釋放資源
resultSet.close();
statement.close();
connection.close();//耗資源,用完關掉
初次優化,提取工具類

- 創建db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false
user=root
password=123456
- 提取工具類JdbcUtils:加載驅動,獲取連接,釋放連接資源
- 測驗增刪改查
package com.qing.demo02.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* JDBC工具類
*/
public class JdbcUtils {
private static String driver = null;
private static String url = null;
private static String user = 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");
user = properties.getProperty("user");
password = properties.getProperty("password");
//1.驅動只需要加載一次
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
//獲取連接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
//釋放連接資源
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
package com.qing.demo02;
import com.qing.demo02.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) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//獲取連接
conn = JdbcUtils.getConnection();
//獲取執行SQL的物件
st = conn.createStatement();
//執行SQL
String sql = "insert into `users`(`id`,`name`,`pwd`,`email`,`birthday`) values(4,'zhangyq','123456','zhangyq2163.com','1988-09-09')";
int i = st.executeUpdate(sql);
if (i > 0) {
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//釋放連接資源
JdbcUtils.release(conn,st,rs);
}
}
}
package com.qing.demo02;
import com.qing.demo02.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) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//獲取連接
conn = JdbcUtils.getConnection();
//獲取執行SQL的物件
st = conn.createStatement();
//執行SQL
String sql = "update `users` set `name`='zhangtj' where `id`=3";
int i = st.executeUpdate(sql);
if (i > 0) {
System.out.println("更新成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//釋放連接資源
JdbcUtils.release(conn,st,rs);
}
}
}
package com.qing.demo02;
import com.qing.demo02.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) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//獲取連接
conn = JdbcUtils.getConnection();
//獲取執行SQL的物件
st = conn.createStatement();
//執行SQL
String sql = "delete from `users` where `id`=4";
int i = st.executeUpdate(sql);
if (i > 0) {
System.out.println("洗掉成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//釋放連接資源
JdbcUtils.release(conn,st,rs);
}
}
}
package com.qing.demo02;
import com.qing.demo02.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) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//獲取連接
conn = JdbcUtils.getConnection();
//獲取執行SQL的物件
st = conn.createStatement();
//執行SQL
String sql = "select * from `users` where `id`=3";
rs = st.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//釋放連接資源
JdbcUtils.release(conn,st,rs);
}
}
}
SQL注入問題

//執行SQL
String id = "3 or 1=1";
String sql = "select * from `users` where `id`=" + id;
rs = st.executeQuery(sql);
String sql = "select * from user_table where username=
' "+userName+" ' and password=' "+password+" '";
--當輸入了上面的用戶名和密碼,上面的SQL陳述句變成:
SELECT * FROM user_table WHERE username=
'’or 1 = 1 -- and password='’
"""
--分析SQL陳述句:
--條件后面username=”or 1=1 用戶名等于 ” 或1=1 那么這個條件一定會成功;
--然后后面加兩個-,這意味著注釋,它將后面的陳述句注釋,讓他們不起作用,這樣陳述句永遠都--能正確執行,用戶輕易騙過系統,獲取合法身份,
--這還是比較溫柔的,如果是執行
SELECT * FROM user_table WHERE
username='' ;DROP DATABASE (DB Name) --' and password=''
--其后果可想而知…
"""
PreparedStatement
- PreparedStatement可以防止SQL注入,并且效率更高,
為什么PreparedStatement能防止sql注入呢?
因為sql陳述句是預編譯的,而且陳述句中使用了占位符,規定了sql陳述句的結構,用戶可以設定"?"的值,但是不能改變sql陳述句的結構,因此想在sql陳述句后面加上如“or 1=1”實作sql注入是行不通的,
實際開發中,一般采用PreparedStatement訪問資料庫,它不僅能防止sql注入,還是預編譯的(不用改變一次引數就要重新編譯整個sql陳述句,效率高),此外,它執行查詢陳述句得到的結果集是離線的,連接關閉后,仍然可以訪問結果集,
package com.qing.demo03;
import com.qing.demo02.utils.JdbcUtils;
import java.sql.*;
/**
* 測驗查詢
*/
public class TestSelect {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
//獲取連接
conn = JdbcUtils.getConnection();
//使用?占位符代替引數
String sql = "select * from `users` where `id`=?";
//預編譯,先寫SQL,然后不執行
st = conn.prepareStatement(sql);
//手動給引數賦值
st.setString(1,"3");
//執行
rs = st.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//釋放連接資源
JdbcUtils.release(conn,st,rs);
}
}
}
使用IDEA連接資料庫
- 連接mysql;

- 選擇mysql驅動;

- 填寫mysql用戶名,密碼,測驗連接;

- 選擇資料庫;

- 雙擊資料表,打開表;修改資料,提交;打開命令列,寫SQL;

JDBC操作事務
- 開啟事務:關閉資料庫自動提交,自動會開啟事務,
- 一組業務執行完畢,提交事務,
- 可以在catch陳述句中顯式的定義回滾陳述句,也可以不寫,默認失敗就會回滾,
- finally中開啟資料庫自動提交,然后釋放連接資源,
package com.qing.demo04;
import com.qing.demo02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 測驗事務
*/
public class TestTransaction {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();
//開啟事務:關閉資料庫自動提交,會自動開啟事務
conn.setAutoCommit(false);
String sql1 = "update `account` set `money`=`money`-100 where `name`='A'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
String sql2 = "update `account` set `money`=`money`+100 where `name`='B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
//提交事務
conn.commit();
System.out.println("成功!");
} catch (SQLException e) {
//顯式回滾,也可以不寫,默認失敗自動回滾
// try {
// conn.rollback();
// } catch (SQLException e1) {
// e1.printStackTrace();
// }
e.printStackTrace();
} finally {
JdbcUtils.release(conn,st,null);
}
}
}
資料庫連接池
- 資料庫連接--》執行完畢--》釋放連接
- 連接--釋放,十分浪費系統資源
- 池化技術:準備一些預先的資源,過來就連接預先準備好的
- 最小連接數
- 最大連接數
- 等待超時
- 撰寫連接池,實作一個介面 DataSource
常用連接池
使用了這些資料庫連接池之后,我們在專案開發中就不需要撰寫連接資料庫的代碼了!
- DBCP
- jar包:commons-dbcp,commons-pool
- 組態檔:dbcpconfig.properties
- 工廠模式創建資料源:DataSource dataSource = BasicDataSourceFactory.creatDataSource(properties);
- 從資料源獲取連接:dataSource.getConnection();
- C3P0
- jar包:c3p0,mchange-commons-java
- 組態檔:c3p0-config.xml
- 創建資料源:DataSource dataSource = new ComboPooledDataSource("MySQL");//不寫引數就是默認資料源,寫引數就是指定資料源
- 從資料源獲取連接:dataSource.getConnection();
- Druid:阿里巴巴
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/248951.html
標籤:MySQL
上一篇:用戶畫像分析與場景應用
下一篇:資料庫概論 (四)完整性
