010_MySQL


初識MySQL

爲何學習數據庫

  1. 崗位需求
  2. 如今的世界,大數據時代,得數據者得天下
  3. 被迫需求:存數據
  4. 數據庫是全部軟件體系中最核心的存在

什麼是數據庫

  1. 數據庫(DB,DataBase)
  2. 概念:數據倉庫,軟件,安裝在操做系統之上。
  3. 做用:存儲數據,管理數據。

數據庫分類

  1. 關係型數據庫(SQL)
    1. MySQL,Oracle,SQLServer,DB2,SQLlite
    2. 經過表和表之間,行和列之間的關係進行數據的存儲
  2. 非關係型數據庫(NoSQL-Not Only SQL)
    1. Redis,MongoDB
    2. 對象存儲,經過對象的屬性來決定。
  3. 數據庫管理系統(DBMS)
    1. 數據庫的管理軟件,科學有效的管理數據,維護和獲取數據。
    2. MySQL,數據庫管理系統。

MySQL簡介

image.png

  1. MySQL是一個關係型數據庫管理系統。
  2. 前世:瑞典MySQL AB 公司
  3. 此生:屬於Oracle旗下產品
  4. MySQL是最好的RDBMS(Relational Database Management System,關係數據庫管理系統) 應用軟件之一。
  5. 開源的數據庫軟件。
  6. 體積小、速度快、整體擁有成本低,招人成本比較低,全部人必須會!
  7. 中小型網站或者大型網站(集羣)。
  8. 官網:https://www.mysql.com

Windows安裝MySQL

安裝建議

  1. 儘可能不要使用exe,卸載麻煩,註冊表
  2. 儘量使用壓縮包安裝

軟件下載

  1. 下載地址:https://downloads.mysql.com/archives/community/
  2. MySQL5.7.31 64位下載地址:https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.31-winx64.zip

安裝步驟

  1. 解壓到安裝的目錄,如:D:\environment\mysql-5.7.31
  2. 添加環境變量
    1. 個人電腦-》屬性-》高級-》環境變量
    2. 選擇PATH,在其後添加:MySQL安裝目錄下的bin目錄路徑,如:D:\environment\mysql-5.7.31\bin
  3. 在MySQL安裝目錄D:\environment\mysql-5.7.31下新建my.ini文件
  4. 編輯my.ini文件
    1. 注意:data目錄不須要建立,會在初始化時自動生成
    2. 注意: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
  1. 安裝MySQL服務:啓動管理員模式下的cmd,並將路徑切換到MySQL下的bin目錄,而後輸入mysqld -install,成功,返回:Service successfully installed.
cd /d D:\environment\mysql-5.7.31\bin
mysqld -install
  1. 初始化數據文件:輸入mysqld --initialize-insecure --user=mysql,成功,生成data目錄。data目錄下的目錄對應數據庫,如:mysql,sys,performance_schema。
mysqld --initialize-insecure --user=mysql

image.png

  1. 啓動MySQL:輸入net start mysql,成功,返回:MySQL 服務正在啓動 MySQL服務已經啓動成功。而且任務管理器中出現MySQL服務。
net start mysql
  1. 進入MySQL管理界面:輸入mysql -u root -p,回車,不輸密碼,再回車,成功。
    1. 注意:-p後不能加空格,空格也是字符,也會認爲是密碼。
    2. 注意:配置skip-grant-tables,會跳過密碼驗證,輸入密碼時,不須要輸入,直接回車。
    3. 注意:註釋掉skip-grant-tables後,有兩種輸入密碼方法:一是-p後直接回車,再輸入密碼;二是-p後直接輸密碼,再回車,如:mysql -u root -p123456,可是不推薦這樣。
mysql -u root -p
  1. 更改root密碼,其實就是修改mysql數據庫的user表的authentication_string字段,password()函數用於md5加密。
update mysql.user set authentication_string=password('123456') where user='root' and Host='localhost';
  1. 刷新權限:flush privileges,
flush privileges;
  1. 註釋掉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
  1. 重啓mysql:net stop mysql,net start mysql
# 退出mysql
exit
# 關閉mysql
net stop mysql
# 啓動mysql
net start mysql
  1. 測試。
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

下載安裝

  1. 下載地址:https://sqlyog.en.softonic.com/
  2. 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
  3. 按提示安裝,免費版不須要註冊,專業版須要註冊,若是註冊,能夠嘗試下面的註冊碼。
    1. 註冊名:kuangshen
    2. 註冊碼:8d8120df-a5c3-4989-8f47-5afc79c56e7c

image.png

鏈接數據庫

image.png

簡單操做

  1. 新建數據庫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:字符串每一個字符串用二進制數據編譯存儲。 區分大小寫,並且能夠存二進制的內容java

image.png

每個SQLyog的執行操做,本質就是對應了一個SQL語句,均可以在軟件的歷史記錄中查看。
如:建立數據庫,在歷史記錄中以下,本質是執行語句:CREATE DATABASE schoolCHARACTER SET utf8 COLLATE utf8_general_ci;mysql

image.png

CREATE DATABASE `school`CHARACTER SET utf8 COLLATE utf8_general_ci;
  1. 新建表student,引擎:InnoDB,字符集:utf8,覈對:utf8_general_ci。

image.png

對應語句以下算法

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;
  1. 查看錶:右鍵點擊student,打開表數據窗口,查看錶數據窗口。

image.png

  1. 添加記錄:在表數據窗口,輸入記錄,點擊保存或者點擊刷新,保存記錄。
INSERT INTO `school`.`student` (`id`, `name`, `age`) VALUES ('1003', 'zhwj', '66');

命令行鏈接數據庫

單行註釋:--
多行註釋:/* */sql

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。
數據庫

注意事項

  1. 學習順序:操做數據庫>操做數據表>操做數據。
  2. mysql關鍵字不區分大小寫。
  3. 單行註釋:--
  4. 多行註釋:/* */
  5. 字符集的區別: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:字符串每一個字符串用二進制數據編譯存儲。 區分大小寫,並且能夠存二進制的內容安全

  1. 若是表名或者字段名是一個特殊字符,須要加反引號(tab鍵上面的符號),如:user。

操做數據庫

  1. 建立數據庫

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;
  1. 刪除數據庫
DROP DATABASE IF EXISTS westos1;
  1. 使用數據庫
USE school; --切換數據庫
USE `school`; --若是表名或字段名是一個特殊字符,須要加反引號,如:`school`
  1. 查看數據庫
SHOW DATABASES; --查看全部數據庫
  1. 查看建立數據庫的語句
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

字段屬性

  1. Unsigned
    1. 無符號數
    2. 聲明瞭該字段的值不能爲負數
    3. 若是添加負數,就會報錯
  2. zerofill
    1. 0填充
    2. 不足的位數,前面用0填充,如:0030
  3. 自增
    1. 默認自動在上一條記錄的基礎上+1,能夠自定義起始值和步長
    2. 一般用來設計惟一的主鍵
  4. 非空
    1. 設置爲非空not null時,若是不給它賦值且沒有設置默認值時,就會報錯
    2. null,若是不填寫值,默認就是null
  5. 默認
    1. 設置默認的值,若是不填值,就會設置爲默認值

操做數據表

  1. 建立表
-- 若是表名或者字段名是一個特殊字符,須要加反引號(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 (`字段名`)
) [表類型] [字符集] [校對規則] [表註釋];
  1. 刪除表
DROP TABLE IF EXISTS `student`;
  1. 查看錶
SHOW TABLES; --查看全部表
  1. 查看錶結構
DESCRIBE `student`;
DESC `student`;
  1. 查看建立數據表的語句
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='學員'

修改表

  1. 修改表名
-- ALTER TABLE `舊錶名` RENAME AS `新表名`;
ALTER TABLE `student` RENAME AS `student1`;
  1. 增長字段
-- ALTER TABLE `表名` ADD `字段名` 數據類型 [約束] [註釋];
ALTER TABLE `student1` ADD `phone` INT(11) DEFAULT NULL COMMENT '電話';
  1. 修改字段名及字段類型、約束、註釋,注意:字段名字段類型必填,其它可選。
-- ALTER TABLE `表名` CHANGE `舊字段名` `新字段名` 字段類型 [約束] [註釋];
ALTER TABLE `student1` CHANGE `phone` `tel` VARCHAR(11) NOT NULL DEFAULT '' COMMENT '聯繫方式';
  1. 修改字段類型、約束、註釋,注意:字段類型必填,其它可選,不能修改字段名。
-- ALTER TABLE `表名` MODIFY `字段名` 字段類型 [約束] [註釋];
ALTER TABLE `student1` MODIFY `tel` INT(11) DEFAULT NULL COMMENT '電話';
  1. 刪除字段
-- ALTER TABLE `表名` DROP `字段名`;
ALTER TABLE `student1` DROP `tel`;

數據庫引擎

  1. INNODB 5.5及以後默認使用數據結構

  2. MYISAM 5.5以前默認使用
    |  | MYISAM | INNODB |
    | --- | --- | --- |
    | 事務支持 | 不支持 | 支持 |
    | 數據行鎖定 | 不支持    (表鎖) | 支持    (行鎖) |
    | 外鍵約束 | 不支持 | 支持 |
    | 全文索引 | 支持 | 不支持 |
    | 表空間的大小 | 較小 | 較大,約爲2倍 |數據庫設計

  3. 常規使用操做ide

    1. MYISAM 節約空間,速度較快
    2. INNODB 安全性高,事務的處理,多表多用戶操做
  4. 全部的數據庫文件都存在data目錄下,一個目錄對應一個數據庫,本質仍是文件的存儲。

  5. mysql引擎在物理文件上的區別

    1. *.frm 表結構定義文件
    2. *.MYD 數據文件(data)
    3. *.MYI 索引文件(index)
    4. *.frm 數據庫目錄下
    5. ibdata1 data目錄下
    6. INNODB對應文件
    7. MYISAM對應文件都在數據庫目錄下

數據表的字符集編碼

  1. mysql默認的字符集編碼是Latin1,不支持中文。
  2. 設置數據表字符集編碼的兩種方式,兩種方式最好同時使用,防止建立表時,沒有設置字符集編碼,致使中文亂碼。
    1. 建立表時添加CHARSET=utf8
    2. 在my.ini中配置默認編碼character-set-server=utf8
CHARSET=utf8

character-set-server=utf8

MySQL數據管理

外鍵

  1. 建立表時,增長外鍵約束
-- 建立年級表
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 '學員';
  1. 刪除有外鍵關係的表時,必須先刪除引用的表(從表),再刪除被引用的表(主表)
  2. 添加外鍵
-- 建立年級表
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 `被引用表名` (`被引用字段名`);
  1. 物理外鍵,是數據庫級別的外鍵,不建議使用。
  2. 最佳實踐
    1. 數據庫就是單純的表,只用來存數據,只有行(數據)和列(字段)
    2. 想使用多張表的數據,想使用外鍵,就用程序來實現

插入數據

-- 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的區別

  1. truncate從新設置自增列,計數器歸零。
  2. delete自增列不變;但重啓數據庫後,引擎是INNODB的,自增列會從1開始(存在內存中,斷電即失);引擎是MYISAM的,自增列不變(存在文件中,不會丟失)。
  3. truncate不會影響事務。

where子句運算符

運算符 含義
= 等於
<> 或 != 不等於
> 大於
< 小於
>= 大於等於
<= 小於等於
between ... and ... 在某個範圍內
類型是數字時,包括頭和尾
類型是date時,包括頭和尾
類型是datetime時,帶時分秒,包括頭和尾;不帶時分秒,包頭不包尾
and
or

DQL數據查詢語言

DQL

  1. 數據庫中最核心的語言,最重要的語言。
  2. 使用頻率最高的語言。

簡單查詢和別名(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條件字句

  1. 做用:檢索數據中符合條件的值。
  2. 檢索的條件由一個或者多個表達式組成。

邏輯運算符

運算符儘可能使用英文字母

運算符 語法 描述
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

image.png

操做 描述
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加密

  1. 什麼是MD5?

image.png

  1. 1996年後該算法被證明存在弱點,能夠被加以破解,對於須要高度安全性的數據,專家通常建議改用其餘算法,如SHA-2。2004年,證明MD5算法沒法防止碰撞(collision),所以不適用於安全性認證,如SSL公開密鑰認證或是數字簽名等用途。
  2. MD5由MD4MD3、MD2改進而來,主要加強算法複雜度和不可逆性。MD5算法因其廣泛、穩定、快速的特色,仍普遍應用於普通數據的加密保護領域。
  3. MD5不可逆,兩個相同的值加密後的值是同樣的。
  4. 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');

事務

什麼是事務

  1. 要麼都成功,要麼都失敗。
  2. 將一組SQL放在一個批次中去執行。

事務原則ACID原則

image.png

  1. 原子性:多個步驟要麼一塊兒成功,要麼一塊兒失敗,不能只成功一個。(同進同退)
  2. 一致性:最終一致性,開始前的總值等於結束後的總值。(能量守恆)
  3. 隔離性:針對多個用戶同時操做,其餘事務不會影響本次事務。(互不干擾)
  4. 持久性:事務沒有提交,恢復到原狀,事務一旦提交,不可改變。(不可逆)

隔離致使的問題

  1. 髒讀:一個事務讀取了另外一個事務未提交的數據。
  2. 不可重複讀:在一個事務內讀取表中的一行數據,屢次讀取結果不一樣。
  3. 虛度(幻讀):一個事務內讀取到了別的事務插入的數據,致使先後讀取不一致。

手動處理事務

-- 事務

/*
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高效獲取數據的數據結構。提取句子主幹,就能夠獲得索引的本質:索引是數據結構。

索引的分類

  1. 主鍵索引(PRIMARY KEY)
    1. 惟一的標識,值不可重複,只能有一個列做爲主鍵
  2. 惟一索引(UNIQUE KEY)
    1. 避免重複的列出現,值不可重複,能夠多個列都標識爲惟一索引
  3. 常規索引(KEY/INDEX)
    1. 默認的,index或key關鍵字來設置
  4. 全文索引(FullText)
    1. 在特定的數據庫引擎下才有,以前MyISAM支持,如今InnoDB也在支持,具體自查
    2. 快速定位數據

索引的建立

-- 顯示全部索引
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`;

建立索引前查詢
image.png
建立索引後查詢
image.png

結論

索引在小數據量的時候,用處不大,可是在大數據量的時候,區別十分明顯。

索引原則

  1. 索引不是越多越好
  2. 不要對常常變更數據的表加索引
  3. 小數據量的表不須要加索引
  4. 索引通常加在經常使用來查詢的字段上

索引的數據結構

  1. InnoDB的默認索引數據結構是Btree
  2. Hash

權限管理和備份

用戶管理

  1. 用戶表:mysql.user
  2. 用戶管理本質是對用戶表數據的增刪改查
-- 建立用戶 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備份

  1. 爲何要備份?
    1. 保證重要的數據不丟失
    2. 數據轉移
  2. MySQL數據庫備份的方式
    1. 直接拷貝物理文件data目錄
    2. 使用可視化工具中的導出功能
    3. 使用命令行導出 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密碼 庫名< 備份文件

規範數據庫設計

爲何須要設計

  1. 當數據庫比較複雜的時候,咱們就須要設計了
  2. 糟糕的數據庫設計
    1. 數據冗餘,浪費空間
    2. 數據庫插入和刪除都會麻煩、異常(屏蔽使用物理外鍵)
    3. 程序的性能差
  3. 良好的數據庫設計
    1. 節省內存空間
    2. 保證數據庫的完整性
    3. 方便咱們開發系統
  4. 軟件開發中,關於數據庫的設計
    1. 分析需求:分析業務和須要處理的數據庫需求
    2. 概要設計:設計關係圖 E-R圖

設計數據庫的步驟(我的博客)

  1. 收集信息,分析需求
    1. 用戶表(用戶登陸註銷,用戶的我的信息,寫博客,建立分類)
    2. 分類表(文章分類,誰建立的)
    3. 文章表(文章信息)
    4. 友鏈表(友鏈信息)
    5. 自定義表(系統信息,關鍵字,主字段)
  2. 標識實體(將需求落地爲具體的表、字段)

三大範式

第一範式(1NF)-原子性

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

第二範式(2NF)

前提:知足第一範式
每張表只描述一件事情
image.png

第三範式(3NF)

前提:知足第一範式和第二範式
確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。
image.png

規範性和性能的問題

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

  1. 考慮商業化的需求和目標(成本,用戶體驗),數據庫的性能更加劇要
  2. 在考慮性能的時候,須要適當的考慮一下規範性
  3. 故意給某些表增長一些冗餘的字段(從多表關聯查詢變爲單表查詢)
  4. 故意增長一些統計列(從大數據量的統計下降爲小數據量的查詢)

JDBC

數據庫驅動

程序經過數據庫驅動,和數據庫打交道。
image.png

JDBC

  1. SUN公司爲了簡化開發人員對數據庫的統一操做,提供了一個Java操做數據庫的規範,俗稱JDBC。
  2. 這些規範的實現由具體的廠商去作。
  3. 對於開發人員來講,咱們只須要掌握JDBC接口的操做便可。

image.png

相關jar包

  1. java.sql
  2. javax.sql
  3. 數據庫驅動包 mysql-connector-java-5.1.49.jar

第一個JDBC程序

  1. 建立測試數據庫。
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','zhangsf@163.com','1988-03-13'),
(2,'zhangwj','123456','zhangwj@163.com','1983-04-03'),
(3,'zhangyq','123456','zhangtj@163.com','1989-05-23');
  1. 建立一個普通項目。

image.png

  1. 導入數據庫驅動。
    1. 建立lib目錄,拷貝mysql-connector-java-5.1.49.jar
    2. 添加到項目庫,右鍵點擊Add as Library

image.pngimage.png
image.png

  1. 編寫測試代碼。

image.png

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();
    }
}

步驟總結

  1. 加載驅動
  2. 鏈接數據庫 DriverManager
  3. 建立執行SQL的對象 Statement
  4. 獲取返回的結果集
  5. 釋放鏈接

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

image.png

//執行SQL的對象
boolean execute = statement.execute("");//執行任何SQL,但須要判斷,效率最低
ResultSet resultSet = statement.executeQuery();//執行查詢,返回查詢結果集
int i = statement.executeUpdate();//執行更新、插入、刪除,返回受影響的行數

插入示例
image.png
刪除示例
image.png
更新示例
image.png
查詢示例
image.png

釋放資源

resultSet.close();
statement.close();
connection.close();//耗資源,用完關掉

初次優化,提取工具類

image.png

  1. 建立db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false
user=root
password=123456
  1. 提取工具類JdbcUtils:加載驅動,獲取鏈接,釋放鏈接資源
  2. 測試增刪改查
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注入問題

image.png

//執行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

  1. 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鏈接數據庫

  1. 鏈接mysql;

image.png

  1. 選擇mysql驅動;

image.png

  1. 填寫mysql用戶名,密碼,測試鏈接;

image.png

  1. 選擇數據庫;

image.png

  1. 雙擊數據表,打開表;修改數據,提交;打開命令行,寫SQL;

image.png

JDBC操做事務

  1. 開啓事務:關閉數據庫自動提交,自動會開啓事務。
  2. 一組業務執行完畢,提交事務。
  3. 能夠在catch語句中顯式的定義回滾語句,也能夠不寫,默認失敗就會回滾。
  4. 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);
        }
    }
}

數據庫鏈接池

  1. 數據庫鏈接--》執行完畢--》釋放鏈接
  2. 鏈接--釋放,十分浪費系統資源
  3. 池化技術:準備一些預先的資源,過來就鏈接預先準備好的
  4. 最小鏈接數
  5. 最大鏈接數
  6. 等待超時
  7. 編寫鏈接池,實現一個接口 DataSource

經常使用鏈接池

使用了這些數據庫鏈接池以後,咱們在項目開發中就不須要編寫鏈接數據庫的代碼了!

  1. DBCP
    1. jar包:commons-dbcp,commons-pool
    2. 配置文件:dbcpconfig.properties
    3. 工廠模式建立數據源:DataSource dataSource = BasicDataSourceFactory.creatDataSource(properties);
    4. 從數據源獲取鏈接:dataSource.getConnection();
  2. C3P0
    1. jar包:c3p0,mchange-commons-java
    2. 配置文件:c3p0-config.xml
    3. 建立數據源:DataSource dataSource = new ComboPooledDataSource("MySQL");//不寫參數就是默認數據源,寫參數就是指定數據源
    4. 從數據源獲取鏈接:dataSource.getConnection();
  3. Druid:阿里巴巴
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息