MySQL基礎學習筆記

MySQL規定:

MySQL不區分大小寫

生產數據庫要備份,執行要分步操作,避免錯誤。

概述

為什么要學數據庫

  • 大數據時代,所有最后落地最普遍的便是數據庫
  • 數據庫是所有軟件體系中最核心的存在

什么是數據庫

數據庫——DataBase——DB,數據倉庫,用于存儲和管理數據。

數據庫分類

關系型數據庫——SQL

  • MySQL,Oracle,Sql Server,DB2,SQLlite
  • 通過表和表、行與列之間的關系進行數據存儲

非關系型數據庫——NoSQL

  • Redis,MongoDB
  • 存儲的是鍵值對。

DBMS——數據庫管理系統——Database Management System

  • 數據庫管理軟件
  • MySQL是數據庫管理系統

MySQL簡介

穩定版本:5.7 ,8.0

體積小、速度快,成本底、招人成本底

安裝建議:盡量不使用exe安裝,因為刪除麻煩,且會進注冊表,盡可能使用壓縮包安裝

壓縮包安裝步驟

MySQL 8.0 壓縮包版安裝方法

  1. 解壓
  2. 在環境變量path上配置解壓后bin所在的目錄地址
  3. 在mysql解壓后目錄下新建my.ini文件——配置文件
  4. 管理員模式運行cmd,用于注冊注冊表
  5. 初始化MySQL數據庫 mysqld --initialize-insecure
  6. 安裝MySQL服務 mysqld install
  7. 啟動MySQL服務 net start mysql
  8. 跳過登錄密碼驗證注釋掉 #skip-grant-tables
  9. 停止MySQL服務 net stop mysql

配置文件如下:

[mysql]
# 設置mysql客戶端默認字符集
default-character-set=utf8
[mysqld]
# 設置3306端口
port = 3306
# 設置mysql的安裝目錄
basedir=D:\Program Files (x86)\mysql\mysql-8.0.19-winx64  
# 設置mysql數據庫的數據的存放目錄,數據庫會自動生成,不需要我們創建文件夾
datadir= D:\Program Files (x86)\mysql\mysql-8.0.19-winx64\data
# 允許最大連接數
max_connections=20
# 服務端使用的字符集默認為8比特編碼的latin1字符集
character-set-server=utf8
# 創建新表時將使用的默認存儲引擎
default-storage-engine=INNODB
# 跳過登錄密碼驗證 在修改完密碼后要把這句注釋掉
#skip-grant-tables
skip-grant-tables

修改root密碼

mysql 5.7
update mysql.user set password=PASSWORD('123456')where User='root';
flush privileges;
mysql 8.0
alter user 'root'@'localhost' identified by '123456'; 
#注意-p后不能加空格直接輸入密碼
mysql -u root -p123456
mysql -u root -p
#再輸入密碼

SQLyog

SQLyog驗證碼
sqlyog驗證碼.png

SQLyog/Navicat

可以查看歷史執行記錄,包括創建表,數據庫等記錄,比navicat詳細。

sc delete mysql 清空服務,即刪除mysql

Mysql定義結構

創建數據庫

默認創建數據庫字符集編碼和排序規則如下

創建數據庫.png

創建表

創建表.png

連接數據庫

當執行命令行連接數據庫報錯'mysql' 不是內部或外部命令,也不是可運行的程序時,是因為我們沒有配置好mysql的環境變量,這時候就需要我們往path上添加mysql的安裝地址到bin文件夾路徑到path上。

-- 在客戶端查看mysql安裝目錄的語句
show variables like "%char%";
mysql配置環境變量.png
#有以下兩種命令行連接數據庫的方法,第一種需要我們回車后輸入密碼
mysql -u root -p
mysql -u root -p123456
命令行執行sql語句注意事項
命令行注意事項.png

基本數據庫連接操作

-- 5.7.29-log 查看mysql版本
SELECT VERSION();

-- 創建數據庫
CREATE DATABASE `my_test` CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 第二種
CREATE DATABASE `my_test` CHARSET= utf8 COLLATE utf8_general_ci;

-- 展示所有的數據庫
SHOW DATABASES;

-- 切換數據庫
USE school;

-- 創建表sql 我們一般通過navicat等定義創建表,上生產時再執行創建表的sql語句
CREATE TABLE `t_student` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(30) NOT NULL COMMENT '學生姓名',
  `age` int(3) NOT NULL COMMENT '學生年齡',
  `create_user` varchar(30) DEFAULT NULL COMMENT '創建人',
  `crreate_time` datetime DEFAULT NULL COMMENT '創建時間',
  `update_user` varchar(30) DEFAULT NULL COMMENT '修改人',
  `update_time` datetime DEFAULT NULL COMMENT '修改時間',
  `delete_flag` tinyint(1) DEFAULT NULL COMMENT '是否刪除 0-否 1-是',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='學生表';

-- 修改用戶密碼
USE mysql;
UPDATE user SET password=PASSWORD('123456') WHERE user='root';
-- 刷新權限
FLUSH PRIVILEGES;

show variables like "%char%";

-- 查看數據庫所有的表
SHOW TABLES;

-- 查看數據庫中指定表的表結構信息
DESCRIBE t_student;

-- 退出數據庫連接
exit;

-- 單行注釋

/*
多行
注釋
*/

utf8和utf8mb4的區別

utf8mb4的編碼,mb4就是most bytes 4的意思,專門用來兼容四字節的unicode。 為了節省空間,一般情況下使用utf8也就夠了。 但是為了獲取更好的兼容性,應該總是使用 utf8mb4 而非 utf8. 對于 CHAR 類型數據,utf8mb4 會多消耗一些空間,根據 Mysql 官方建議,使用 VARCHAR 替代 CHAR。

參考

Mysql中的排序規則utf8_unicode_ci、utf8_general_ci的區別總結

首先,ci是 case insensitive, 即 "大小寫不敏感", a 和 A 會在字符判斷中會被當做一樣的; bin 是二進制, a 和 A 會別區別對待。所以我們在用sql進行匹配查找的時候,如果是ci,則無論大小寫都可以匹配出來,而如果是utf8_bin中的bin是二進制,則會區分大小寫,這時候就只能唯一匹配到精確的那個值。

參考

SQL語言分類

參考

DDL—— 數據定義語言DDL,(data definition language)

用來創建數據庫中的各種對象-----表、視圖,DDL操作是隱性提交的!不能rollback 。

CREATE,ALTER,DROP,TRUNCATE,COMMENT ,RENAME
DML—— 數據操縱語言(DML:Data Manipulation Language)

數據的增刪改。

INSERT,UPDATE,DELETE,EXPLAIN, PLAN
DQL——數據查詢語言(DQL: Data Query Language)

數據的查詢

SELECT
DCL—— 數據庫控制語言(Database Control Language)

用來設置或更改數據庫用戶或角色權限的語句,包括(grant,deny,revoke等)語句 。

GRANT,REVOKE
TCL——存儲過程控制預言(Transaction Control Language)

數據庫事務的控制語言。

COMMIT,SAVEPOINT,ROLLBACK,SET TRANSACTION

操作數據庫

操作數據庫> 操作數據庫中的表> 操作數據庫中的表的數據

數據庫操作示例

-- 創建數據庫 IF NOT EXISTS 表示不存在則創建,存在則跳過
CREATE DATABASE IF NOT EXISTS `my_test` CHARACTER SET utf8 COLLATE utf8_general_ci;

-- 刪除數據庫
DROP DATABASE IF EXISTS `my_test`;

-- 使用數據庫
USE school;

-- 查看數據庫
SHOW DATABASES;

數據庫中表的列類型

數值類型

數據庫數值類型 描述 大小(字節) 對應Java中的類型
tinyint 特別小的數據 1Byte byte
smallint 較小的整數 2Byte short
mediumint 中等大小的整數 3Byte
int 標準的整數 4Byte int
bigint 較大的整數 8Byte long
float 浮點數(單精度) 4Byte float
double 浮點數(雙精度) 8Byte double
decimal 字符串形式的浮點數 BigDecimal

注:在金融等金額計算時,一般使用decimal來表示金額大小,因為使用double會有精度問題,而使用字符串形式的浮點數則可以完整得表示出金額的大小。

字符串

數據庫數值類型 描述 大小(字節) 對應Java中的類型
char 固定大小的字符串 0-255 String
varchar 可變字符串 0-65535 String
tinytext 微型文本 2^8 -1 =255 String
text 文本串 2^16 -1 =65535 String

日期時間

數據庫數值類型 描述 對應Java中的類型
date 日期格式 Date,LocalDate
time 時間格式 LocalTime
datetime 日期時間格式 Date,LocalDateTime
timestamp 時間戳,1970.1.1到現在的毫秒數 Timestamp
year 年份 Year

注:yyyy-MM-dd HH:mm:ss 表示年月日時分秒。月:用MM大寫表示是與時間單位的mm作為區別,而時:HH用大寫表示24小時制,用小寫hh則是12小時制。

VARCHAR 和 TEXT 長度問題

VARCHAR :varchar在mysql中滿足最大行限制,也就是 65535(16k)字節,在mysql中使用 uft-8(mysql中的 utf-8 和我們正 常的編碼utf-8不同)字符集一個字符占用三個字節。

①使用 utf-8 字符編碼集 varchar 最大長度是 (65535-1)/3=21844 個字符(由于會有1字節的額外占用空間開銷, 所以減1)。
使用 utf-8mb4 字符集(mysql中 utf-8mb4 字符集也就是我們通常使用的 utf-8 字符集),mysql中使用 utf8mb4 字符集一個字符占用4個字節,所以 varchar 最大長度是(65535-1)/4=16383 個字符(由于1字節額外占用空間開銷,所以減1)。

TEXT :最大限制是64k, 采用 utf-8 字符集,(262144-1)/3=87381 個字符。采用 utf-8mb4字符集,(262144-1)/4=65535 個字符。
參考

數據庫中表的字段屬性——重要

無符號——Unsigned

  • 無符號整數
  • 聲明了該列不能聲明為負數,比如主鍵id這個列

0填充——zerofill

  • 0填充
  • 列聲明的位數,沉淀的值如果不足聲明的位數則用0來填充,比如:int(3),沉淀3則在數據庫里為003

自增——AUTO_INCREMENT

  • 即數據庫幫我們做自增,自動在上一條記錄的基礎上+1(默認)
  • 通常用來設置唯一的主鍵,必須為整數類型,效率高
  • 可以自定義設置主鍵自增的起始值和步長,比如AUTO_INCREMENT=11表示從11開始自增。

非空 NULL NOT NULL

  • 設置為 NOT NULL表示非空,如果不設置值則會報錯
  • 設置為NULL表示可以為空,不填寫值則默認為NULL

默認——DEFAULT

  • 設置默認值
  • 當不指定該列的值時,則會有默認值填充

表設計時必須存在的字段

id 主鍵
version 版本號,用于樂觀鎖
delete_flag 刪除狀態,用于偽刪除
gmt_create 創建時間
gmt_update 修改時間

MySQL中數據類型的長度問題總結

Q:int(5)以及varchar(20)長度表示的是什么?

A:int數據類型是固定的4個字節;

但是int(5)和int(11)區別在于,顯示的數據位數一個是5位一個是11位,在開啟zerofill(填充零)情況下,若int(5)存儲的數字長度是小于5的則會在不足位數的前面補充0,但是如果int(5)中存儲的數字長度大于5位的話,則按照實際存儲的顯示(數據大小在int類型的4個字節范圍內即可),也就是說int(M)的M不代表數據的長度;varchar(20)中的20表示的是varchar數據的數據長度最大是20,超過則數據庫不會存儲,直接報錯;

總結:

int(M) M表示的不是數據的最大長度,只是數據寬度,跟0填充有關,并不影響存儲多少位長度的數據;

varchar(M) M表示的是varchar類型數據在數據庫中存儲的最大長度,超過則不存;
參考

DECIMAL(M,D) 中,M就是總長度,D就是小數點后面的長度,超出范圍或者長度不夠會被截斷或補位 。比如: DECIMAL(5,4)=>總長度不超過5位數字,并且小數點后頭必須要4位數字:1.2345 DECIMAL(14,9)=>總長度5位數字,整數5位,小數點后9位:12345.123456789

創建數據庫表——重要

創建表示例

-- 注意點
-- 表內容在英文()里,表名、字段名和索引名盡量用``括起來
-- AUTO_INCREMENT 自增
-- 字符串使用時用 ''括起來
-- 所有語句后面都要加英文逗號 ,最后一句不用加
-- PRIMARY KEY 主鍵,一張表一般一個唯一主鍵
CREATE TABLE IF NOT EXISTS `t_student` (
 `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
 `name` VARCHAR(20) NOT NULL DEFAULT '佚名' COMMENT '姓名',
 `age` INT(3) DEFAULT NULL COMMENT '年齡',
    `gender` TINYINT(2) DEFAULT NULL COMMENT '性別',
    `birthday` DATETIME DEFAULT NULL COMMENT '出生日期', 
    PRIMARY KEY(`id`),
    KEY `idx_name`(`name`)
) ENGINE= INNODB AUTO_INCREMENT=1000 DEFAULT CHARACTER SET utf8mb4 COLLATE = utf8mb4_general_ci COMMENT '學生表';

CREATE TABLE IF NOT EXISTS `t_student` (
 `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
 `name` VARCHAR(20) NOT NULL DEFAULT '佚名' COMMENT '姓名',
 `age` INT(3) DEFAULT NULL COMMENT '年齡',
    `gender` TINYINT(2) DEFAULT NULL COMMENT '性別',
    `birthday` DATETIME DEFAULT NULL COMMENT '出生日期', 
    PRIMARY KEY(`id`),
    KEY `idx_name`(`name`)
) ENGINE= INNODB AUTO_INCREMENT=1000 DEFAULT charset=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='學生表';

格式

注:[表類型][字符集設置] [表名注釋]通常不寫默認是數據庫的默認配置

CREATE TABLE IF NOT EXISTS `表名` (
`字段名` 列類型 [屬性] [注釋],
 `字段名` 列類型 [屬性] [注釋]
) [表類型] [字符集設置] [表名注釋]

查看建表

-- 查看t_student表的創建語句
SHOW CREATE TABLE t_student;

-- 查看創建數據庫的語句
SHOW CREATE DATABASE school;

-- 顯示表結構
DESC t_student;

數據庫數據表的存儲引擎

存儲引擎是針對表的,每張表都可以設置自己的存儲引擎。我們對數據庫會設置默認的存儲引擎,當我們建表時沒有明確指定表的存儲引擎時默認就是數據庫設置的存儲引擎。比較常見的存儲引擎有:

  • InnoDB——一般默認選擇使用
  • MyISAM

InnoDB與MyISAM的區別

InnoDB MyISAM
事務支持 支持 不支持
數據行鎖定(行鎖) 支持 不支持(表鎖)
外鍵約束 支持(一般不喜歡在數據庫使用外鍵) 不支持
全文索引 不支持(5.7版本后支持) 支持
表空間大小 較大,約是MyISAM表空間的2倍 較小

MyISAM——節約空間,速度較快

InnoDB——安全性高,支持事務和多表多用戶操作

在物理空間的位置

Mysql數據庫的文件存儲在裝目錄下的data文件夾下,一個數據庫對應一個文件夾,如數據庫school對應data目錄下的school文件夾,因此數據庫本質還是文件的存儲

#mysql數據存儲位置,安裝目錄下的data文件夾下
C:\ProgramData\MySQL\MySQL Server 5.7\Data

Mysql存儲引擎在物理文件下的區別

InnoDB

一張表對應兩個文件分別是:

  • *.frm——表結構定義文件
  • *.ibd——表數據和索引的存儲文件
MyISAM

一張表對應兩個文件分別是:

  • *.frm——表結構定義文件
  • *.myd——表數據文件data
  • *.myi——表索引文件index

設置數據庫表的字符集編碼

在創建表結構時設置如下,建議使用這個:

DEFAULT CHARSET=utf8mb4

不設置會是mysql默認的字符集編碼,Mysql默認字符集編碼是Latin1,不支持中文。

第二種設置字符集編碼是在mysql的配置文件my.ini中設置默認的字符集編碼為utf8mb4。建議使用第一種在表結構文件中設置,這樣在其他服務器的mysql中就一定是我們設置的字符集編碼,因為別人不一定在配置文件中設置了默認的字符集編碼為utf8mb4。

character-set-server=utf8mb4

修改刪除表

修改

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

-- 增加表字段 ALTER TABLE 表名 ADD 字段名 列屬性
ALTER TABLE student ADD address VARCHAR(30) DEFAULT NULL COMMENT '地址';

-- 修改表字段 ALTER TABLE 表名 MODIFY 字段名  [列屬性];
ALTER TABLE student     MODIFY address  TIMESTAMP ;
-- CHANGE 字段可以重命名和修改約束, MODIFY 只能修改約束
ALTER TABLE student CHANGE update_time update_date date ;
-- 刪除表字段 ALTER TABLE 表名 DROP 字段名;
ALTER TABLE student DROP address;

刪除

--刪除表 如果存在則刪除
DROP TABLE IF EXISTS student;

MySQL的數據管理

外鍵


CREATE TABLE IF NOT EXISTS `t_grade` (
    id BIGINT(10) NOT NULL AUTO_INCREMENT COMMENT '年級id',
    grade_name VARCHAR(30)  NOT NULL COMMENT '年級名',
    PRIMARY KEY (`id`)
) ENGINE=INNODB CHARSET=utf8mb4 COMMENT '年級表';

-- 創建外鍵方式1 
-- 1、學生表的grade_id字段要添加年級表的外鍵索引
-- 2、給這個外鍵添加約束(執行引用)
CREATE TABLE IF NOT EXISTS `t_student` (
    `id` BIGINT ( 10 ) NOT NULL AUTO_INCREMENT COMMENT 'id',
    `name` VARCHAR ( 30 ) NOT NULL COMMENT '學生姓名',
    `age` INT ( 3 ) NOT NULL COMMENT '學生年齡',
    `grade_id` BIGINT ( 10 ) NOT NULL COMMENT '年級id',
    `create_user` VARCHAR ( 30 ) DEFAULT NULL COMMENT '創建人',
    `crreate_time` datetime DEFAULT NULL COMMENT '創建時間',
    `update_user` VARCHAR ( 30 ) DEFAULT NULL COMMENT '修改人',
    `update_time` datetime DEFAULT NULL COMMENT '修改時間',
    `delete_flag` TINYINT ( 1 ) DEFAULT NULL COMMENT '是否刪除 0-否 1-是',
    `address` VARCHAR ( 30 ) DEFAULT NULL COMMENT '地址',
    PRIMARY KEY ( `id` ) ,
    KEY (`fk_grade_id`) ,
    CONSTRAINT `fk_grade_id` FOREIGN KEY    `grade_id` REFERENCES `t_grade`(`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '學生表';


-- 創建外鍵方式2
ALTER TABLE t_student ADD CONSTRAINT `fk_grade_id` FOREIGN KEY(`grade_id`) REFERENCES `t_grade`(`id`);

注意:外鍵是物理外鍵,屬于數據庫級別的外鍵,必須管理關系導致的問題。每次做delete或update時都要考慮外檢約束,導致開發和測試都不方便。因此強制不得使用外鍵和級聯,一切外鍵概念必須在應用層解決。

最佳實踐

  • 數據庫只是單純的表,只存放數據和字段
  • 通過代碼層面實現外鍵功能

索引sql示例

使用sql語句創建唯一索引,格式如下:
create unique index 索引名 on 表名(列名1,列名2……)

示例;在表GoodsMade_Labour的SID列上創建唯一索引IX_GoodsMade_Labour,代碼如下:
create unique index IX_GoodsMade_Labour on GoodsMade_Labour(SID)

這樣情況下創建的是非聚集索引,它和使用nonclustered關鍵效果是一樣的。
create unique nonclustered index IX_GoodsMade_Labour on GoodsMade_Labour(SID)

如果要創建聚集索引,可使用關鍵字clustered,代碼如下:
create unique clustered index IX_GoodsMade_Labour on GoodsMade_Labour(SID)

1.添加PRIMARY KEY(主鍵索引) 
mysql>ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 
2.添加UNIQUE(唯一索引) 
mysql>ALTER TABLE `table_name` ADD UNIQUE ( 
`column` 
) 
3.添加INDEX(普通索引) 
mysql>ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) 
4.添加FULLTEXT(全文索引) 
mysql>ALTER TABLE `table_name` ADD FULLTEXT ( `column`) 
5.添加多列索引 
mysql>ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )

ALTER TABLE  `publicity`.`publicity_recruit`` MODIFY `recruit_code` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '招聘需求編碼';
ALTER TABLE `publicity`.`publicity_recruit` ADD UNIQUE INDEX `uk_recruit_code`(`recruit_code`);

刪除索引
DROP INDEX index_name ON talbe_name
推薦:
ALTER TABLE table_name DROP INDEX index_name
ALTER TABLE table_name DROP PRIMARY KEY

參考

Insert——插入語句

示例

-- 插入語句 
-- 格式 insert into 表名([字段名1,字段名2,字段名3...]) values (值1,值2,值3...), (值1,值2,值3...);
-- 插入表的字段如果省略不寫則需要在傳入值時要所以字段值都填上并且與字段順序一一對應匹配
-- Column count doesn't match value count at row 1 
INSERT INTO t_student VALUES (null,'艾米');
INSERT INTO t_student VALUES (6,'艾米2',18,1,'2002-10-10');
-- 對于自增主鍵我們在插入時可以使用null代替,這樣數據庫會自增幫我們插入
INSERT INTO t_student VALUES (null,'艾米2',18,1,'2002-10-10');

insert into t_student(`name`,age) values('大青山',19);
-- 插入多條數據用(),()隔開
insert into t_student(`name`,age) values('池傲天',20),('霍恩斯',200);

注意

  • 語法都是英文的,包括英文標的符號
  • 插入字段省略則后面valus值必須一一對應
  • 插入多條語句用括號和英文逗號隔開。

Update——修改語句

示例

-- 修改
-- 語法 UPDATE 表名 SET column_name=value,[column_name=value] where [條件]
UPDATE t_student SET `name`= '年輕的艾米',`age`=6 WHERE id =1;
UPDATE t_student SET `name`= '年輕的艾米',`age`=6 WHERE id = null;
-- 不加where條件的話則更新全部數據,所以要注意
UPDATE t_student SET `name`= '年輕的艾米',`age`=6 ;
-- 修改id=2到5之間的數據,是閉區間
update t_student set grade_id = '7' where id between 2 and 5;
-- or 或
update t_student set grade_id='8' where id=1 or id =6;
-- and 和
update t_student set grade_id='9' where id=1 and age=20;
-- 設置的value值可以是一個具體的值,也可以是變量
update t_student set crreate_time = CURRENT_TIME where id=1 and age=20;
update t_student set update_time = t_student.crreate_time where id=1 and age=20;

注意

  • column表的列名最好都帶上``,防止數據庫保留的關鍵字問題
  • where條件沒有加入則會修改表全部的數據
  • 設置的value值可以是一個具體的值,也可以是變量,如now(),current_time
  • set=value設置值之間用逗號隔開

Delete、TRUNCATE——刪除語句

示例

-- 語法 DELETE FROM 表名 [WHERE 條件]
-- 刪除指定條件下的數據
DELETE FROM t_student WHERE id =2;
-- 刪除所有數據,避免使用
DELETE FROM t_student ;

-- 更好的表數據刪除使用TRUNCATE語句
-- TRUNCATE 表名 
-- TRUNCATE 完全清空數據庫表
truncate t_student;

Delete和TRUNCATE的區別

  • 相同點:都可以刪除數據,不會影響表結構
  • 不同點:
    • TRUNCATE會重新設置自增列,自增計數器會歸零,而Delete自增計數器不會變
    • TRUNCATE不受事務影響,而Delete可以在事務中回滾rollback

Delete刪除的問題

當重啟數據庫時,InnoDB的自增列會歸零,因為計數器存在內存中,斷電即失;而MyISAM計數器存放在文件中,不會斷電或者重啟丟失。

Select——查詢(DQL)

select語法.png
select.png

簡單查詢示例

-- 查詢表全部字段全部數據 
SELECT * from student;
-- 查詢指定字段
SELECT studentno,studentname FROM student;
-- 字段和表都可以起別名,可以用as 或者空格
SELECT studentno as 學號,studentname 姓名 FROM student s;
-- 拼接函數 concat
-- 姓名:張偉前來報到,聯系號碼:13800001234
SELECT CONCAT('姓名:',studentname,'前來報到,聯系號碼:',phone) FROM student;
-- DISTINCT去重
SELECT DISTINCT r.studentno FROM result r;

通過SELECT進行函數、表達式、變量使用示例

-- 查看系統版本,(函數)形式
-- 5.7.17-log
SELECT VERSION();
-- 用于計算,(表達式) 
-- 300
SELECT 100*5-200 AS 結果;
SELECT 100*5-200 AS total;

-- 查看自增的步長,即每次自增多少,(變量)
-- 1
SELECT @@auto_increment_increment;
-- 篩選出成績加1分查看 
SELECT s.studentno `no` , s.studentresult + 1 score FROM result s;
SELECT s.studentno , s.studentresult/10 as score FROM result s;

MySQL5.7官網方法與函數操作符地址

where條件子句示例

where條件結果問布爾值,由一個或多個表達式組成。

邏輯運算符 與或非可以使用下面兩種語句都行,盡量使用第一種英文。

  • and or not
  • && || !
-- 與或非的其他寫法展示
-- and 與
SELECT *  FROM result s where s.studentresult >1 && s.studentresult <80;
-- or 或
SELECT *  FROM result s where s.studentresult =70 || s.studentresult =68;
-- not 非
SELECT *  FROM result s where not s.studentresult =70;

模糊查詢示例

運算符 語法 描述
IS NULL age is null age為null則結果為true
IS NOT NULL age is not null age不為null則結果為true
BETWEEN AND age between a and b age在a和b之間則結果為true
Like name like '%a%' 模糊匹配,name包含a則為真
IN age in(a,b,c) age在其中某一個值則結果為真
-- 模糊查詢 like %表示0到任意個字符, _表示一個字符
-- 查詢姓張,名字為2個字的學生
SELECT *  FROM student s where s.studentname like '張_';
-- 查詢名字中帶偉的學生
SELECT *  FROM student s where s.studentname like '%偉%';
--  in 查詢
SELECT *  FROM student s where s.studentno in(1000,1001);

聯表查詢

聯表示例

-- 左聯、右聯等外聯是要用on來關聯否則報錯,on確定主表,無論條件如何主表數據都會返回然后進行篩選。
SELECT *  FROM student s LEFT JOIN result r on s.studentno = r.studentno where s.studentname='張偉';
-- 內聯時用on或者where進行關聯都可以
SELECT *  FROM student s  INNER JOIN result r where s.studentno = r.studentno and s.studentname='張偉';
SELECT *  FROM student s  JOIN result r where s.studentno = r.studentno and s.studentname='張偉';

-- 聯表查詢思路
/*
1、分析需求要的字段來自哪些表
2、確定使用哪種連接查詢
3、確定交叉點,比如訂單號id
4、判斷的條件
*/
-- 學生年級聯表查詢
select s.studentno,s.studentname,g.gradename,r.studentresult,sub.subjectname from student s 
INNER JOIN grade g ON s.gradeid = g.gradeid 
INNER JOIN result r ON s.studentno = r.studentno 
left JOIN `subject` sub ON sub.subjectno = r.subjectno;

-- 自連接,設計表時把有父子關系的兩種層級表合并成一張表
-- 進行查詢時自己和自己關聯查詢
SELECT a.categoryname 父類別,b.categoryname 子類別 from category a,category b where a.categoryid= b.pid;
1000    張偉  大二  85  高等數學-1
1000    張偉  大二  70  高等數學-2
1000    張偉  大二  68  高等數學-3
1000    張偉  大二  98  高等數學-4
1000    張偉  大二  58  C語言-1

七種join理論

參考

七種join理論.png

mysql進行關聯Join時where和on的區別

Join時where和on的區別關鍵在于left join,right join,full join(inner join)的特殊性,不管on上的條件是否為真都會返回left或right表中的記錄,full則具有left和right的特性的并集。 而inner jion沒這個特殊性,則條件放在on中和where中,返回的結果集是相同的。

在使用mysql數據庫時,使用left join或者right join都必須要使用關鍵字on,否則就sql執行就報錯。可以這樣理解:on是建立外連的橋,兩張表如何連接就靠on后面的條件。因為外連分主次表,數據以主表為基礎,次表對應連接,如果沒有on來建立連接,那么次表的數據就不知道如何對應上主表。而內連,又稱為直連,不存在主次表之分,取得是兩者的交集,因此不需要on。

外連接時,on條件是在生成臨時表時使用的條件,它不管on中的條件是否為真,都會返回左邊表中的記錄。而where條件是在臨時表生成好后,再對臨時表進行過濾的條件。

參考

參考2

分頁和排序

分頁示例

分頁的意義

緩解數據庫壓力,體驗更好,返回數據更快,瀑布流方式分頁

-- 排序 ORDER BY 字段名 DESC 
-- 升序 ASC ,降序 DESC
SELECT *  FROM result r ORDER BY r.studentresult DESC;

-- 分頁 limit offset,pagesize 參數描述:(起始值,從0開始),(頁面大小) 
SELECT *  FROM result r ORDER BY r.studentresult DESC LIMIT 0,2;
SELECT *  FROM result r ORDER BY r.studentresult DESC LIMIT 2,2;
分頁思路.png

Java分頁實現

    /**
     * 當前分頁總頁數
     */
    default long getPages() {
        if (getSize() == 0) {
            return 0L;
        }
        long pages = getTotal() / getSize();
        if (getTotal() % getSize() != 0) {
            pages++;
        }
        return pages;
    }

    /**
     * 計算當前分頁偏移量
     */
    default long offset() {
        long current = getCurrent();
        if (current <= 1L) {
            return 0L;
        }
        return (current - 1) * getSize();
    }

子查詢和嵌套查詢

示例

-- 子查詢關聯查詢
SELECT DISTINCT s.studentno,s.studentname FROM student s INNER JOIN result r on s.studentno=r.studentno
WHERE r.studentresult >=80 and r.subjectno=(SELECT subjectno from `subject` sub where sub.subjectname='高等數學-4');

-- 多張表聯表查詢 
SELECT DISTINCT s.studentno,s.studentname FROM student s INNER JOIN result r on s.studentno=r.studentno
INNER JOIN `subject` sub 
ON sub.subjectno=r.subjectno
WHERE r.studentresult >=80 and sub.subjectname='高等數學-4';

-- 嵌套查詢
SELECT DISTINCT s.studentno,s.studentname FROM student s where s.studentno IN(
SELECT  r.studentno FROM result r WHERE r.studentresult >=80  and r.subjectno =(
SELECT subjectno from `subject` sub where sub.subjectname='高等數學-4'
)
)

函數

常用函數

函數1.png

函數2.png

函數3.png

聚合函數

函數 描述
count() 計數
sum() 求和
avg() 平均值
max() 最大值
min() 最小值

where的條件不能用聚合函數,要改用having過濾。

聚合函數.png
-- 通過分組查詢各個科目的最高分平均分等聚合統計
-- GROUP BY r.subjectno 通過什么字段來分組,該字段 不需要是在展示的列名上
SELECT s.subjectname , MAX(r.studentresult) max, min(r.studentresult) min, avg(r.studentresult) avg FROM result r INNER JOIN
`subject` s ON r.subjectno = s.subjectno 
GROUP BY r.subjectno 
HAVING avg >=80;
執行count(1)、count(*) 與 count(列名) 的區別

count(列名)會忽略字段中數據為null的值,這時候不會計入總數,而count(1)、count(*) 不會忽略null值,只要這一行有數據就會計數,本質是計算行數。

執行效果上:

  • count(*)包括了所有的列,相當于行數,統計結果時不會忽略列值為null的記錄。
  • count(1)會忽略所有的列,用1代表一行數據,統計結果時不會忽略列值為null的記錄。
  • count(列名)值包括列名那一列,統計結果時當列值數據為null時會忽略計數,不統計。

執行效率上:

  • 列名為主鍵,count(列名)會比count(1)快
  • 列名不為主鍵,count(1)會比count(列名)快
  • 如果表多個列并且沒有主鍵,則 count(1) 的執行效率優于 count(*)
  • 如果有主鍵,則 select count(主鍵)的執行效率是最優的
  • 如果表只有一個字段,則 select count(*)最優。

https://zhuanlan.zhihu.com/p/89299468

MD5加密

什么是MD5?

MD5信息摘要算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼散列函數,可以產生出一個128位(16字節)的散列值(hash value),用于確保信息傳輸完整一致。

MD5不可逆,加鹽相同的情況下相同的密碼值MD5是一樣的,因此MD5破解網站的原理是后臺存儲了MD5的字典,用于匹配MD5加密后的值和加密前的值。

MD5加鹽:鹽被稱作“Salt值”,這個值是由系統隨機生成的,并且只有系統知道。即便兩個用戶使用了同一個密碼,由于系統為它們生成的salt值不同,散列值也是不同的。

-- 創建用戶表,測試md5加密
CREATE table `user`(
`id` BIGINT(8) UNSIGNED auto_increment NOT null COMMENT 'id',
`name` varchar(20) NOT null COMMENT '姓名',
`pwd` VARCHAR(50) NOT null COMMENT '密碼',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT charset=utf8mb4;
-- 明文密碼
insert into `user`(`name`,`pwd`)VALUES('艾米','123456'),('大青山','123456'),('霍恩斯','123456'),('雷葛','123456');
-- 使用MD5加密
-- 指定用戶加密
update `user` set pwd=MD5(pwd) where `name`='艾米';

-- 更新所有用戶加密 
-- 注意加密后的MD5值是一樣的,之所以艾米用戶的值不一樣是因為更新所有導致二次加密了
update `user` set pwd=MD5(pwd) ;

-- 插入時加密
insert into  `user`(`name`,`pwd`)VALUES('綠兒',MD5('123456'));

-- 校驗加密,相當于用戶登錄
-- 將用戶登錄的密碼用md5加密后與數據庫的值比對
SELECT * FROM `user` u where u.`name`='綠兒' and u.pwd = MD5('123456');

事務

ACID

原子性(Atomicity)

原子性是指事務是一個不可分割的工作單位,事務中的操作要么都發生,要么都不發生。

一致性(Consistency)

事務前后數據的完整性必須保持一致。

隔離性(Isolation)

事務的隔離性是多個用戶并發訪問數據庫時,數據庫為每一個用戶開啟的事務,不能被其他事務的操作數據所干擾,多個并發事務之間要相互隔離。

持久性(Durability)

持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響

事務的隔離級別

因為隔離性導致的臟讀、幻讀、不可重復讀。

臟讀:

指一個事務讀取了另外一個事務未提交的數據。

虛讀(幻讀)

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

不可重復讀:

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

數據庫隔離級別設置

set transaction isolation level 設置事務隔離級別
select @@tx_isolation 查詢當前事務隔離級別

設置描述:
Serializable 可避免臟讀、不可重復讀、幻讀情況的發生。(串行化)
Repeatable read 可避免臟讀、不可重復讀情況的發生。(可重復讀)
Read committed 可避免臟讀情況發生(讀已提交)。
Read uncommitted 最低級別,以上情況均無法保證。(讀未提交)

數據庫ACID參考

數據庫操作事務示例

-- 關閉事務自動提交
SET autocommit =0;
--  mysql默認開啟事務自動提交 
SET autocommit =1;

START TRANSACTION;
insert into `user`(`name`,`pwd`)VALUES('艾米','123456'),('大青山','123456'),('霍恩斯','123456'),('雷葛','123456');
-- 成功提交事務持久化
COMMIT;
-- 回滾,一般用于失敗后回滾數據
ROLLBACK;

-- 保存點
SAVEPOINT a;
-- 回滾到一個事務的保存點
ROLLBACK TO SAVEPOINT a;
-- 釋放保存點
RELEASE SAVEPOINT a;

索引

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

索引的本質:索引是數據結構。

索引的分類

  • 主鍵索引——PRIMARY KEY
  • 唯一索引——UNIQUE KEY
  • 普通索引——INDEX 、KEY
  • 全文索引——FULLTEXT
索引分類.png

MySQL索引背后的數據結構及算法原理

如何用EXPLAIN優化sql查詢效率

一張圖徹底搞懂MySQL的 explain

explain.png

索引示例——測試百萬數據的索引效果

-- 測試表 
CREATE TABLE `t_user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(20) NOT NULL COMMENT '姓名',
    `email` varchar(50) DEFAULT NULL COMMENT '郵箱',
    `phone` varchar(20) DEFAULT NULL COMMENT '手機號碼',
  `pwd` varchar(50) DEFAULT NULL COMMENT '密碼',
    `age` TINYINT(3) DEFAULT NULL COMMENT '年齡',
    `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHAstudent.gradeidRSET=utf8mb4 COMMENT='測試用戶表';
 
-- 插入100w數據函數
-- 寫函數前先更改mysql分隔符為$$ ,寫函數標記
DELIMITER $$
 CREATE FUNCTION 100w_data()
 RETURNS INT
 BEGIN
    DECLARE num INT DEFAULT 1000000;
    DECLARE i INT DEFAULT 1;
    WHILE i<num DO
    INSERT INTO t_user(`name`,`email`,`phone`,`pwd`,`age`)VALUES(CONCAT('VIP客戶',i),'884849324@qq.com',CONCAT('15',FLOOR(RAND()*1000000000)),UUID(),FLOOR(RAND()*100));
    SET i =i+1;
END WHILE;
RETURN i;
END

-- 執行函數
SELECT  100w_data();
-- 刪除函數
DROP FUNCTION 100w_data;
-- mysql8.0才能并行
SELECT /*+PARALLEL(8)*/ 100w_data();
 -- 未加索引前耗時1s。加索引后耗時0.01-0.02s
SELECT * from t_user u where u.`name`='VIP客戶100000';
 -- 增加索引
ALTER TABLE t_user ADD INDEX idx_name(`name`);

索引原則

  • 索引不是越多越好
  • 不要對經常變動的數據加索引
  • 小數據量的表不需要加索引
  • 索引一般用在經常查詢的字段上

索引的數據結構

  • Hash
  • Btree

權限管理和備份

權限添加和刪除

可視化工具——navicat

首選我們可以通過可視化工具進行用戶的創建,權限的添加和刪除。

用戶.png

用戶創建和權限授予sql預覽.png

SQL

但在Linux服務器上我們沒有可視化界面因此要使用sql語句執行。

 -- % 是允許所有的主機都可以連接
 CREATE USER `roy`@`localhost` IDENTIFIED BY '123456';
 
GRANT Alter, Alter Routine, Create, Create Routine, Create Temporary Tables, Create User, Create View, Delete, Drop, Event, Execute, File, Grant Option, Index, Insert, Lock Tables, Process, References, Reload, Replication Client, Replication Slave, Select, Show Databases, Show View, Shutdown, Super, Trigger, Update ON *.* TO `roy`@`localhost`;
-- 創建用戶
  CREATE USER develop IDENTIFIED by '123456';
 
創建用戶.png
創建用戶2.png

數據庫備份

為什么要備份:

  • 保證數據庫數據不丟失
  • 用于數據的遷移

MySQL數據庫備份的方式

  • 直接copy物理文件/data目錄下的物理文件
  • 在可視化工具Navicat等上導出
  • 使用命令行導出

可視化工具備份

右擊要導出的數據庫或表轉存數據,可以轉存表結構或者表結構及數據。

導入就直接把文件執行即可。

命令行導出——linux中使用

#mysqldump -h主機 -u用戶名 -p密碼 數據庫 表名 >物理磁盤位置/文件名
mysqldump -hlocalhost -uroot -p123456 school student >D:a.sql
#導出整個數據庫
mysqldump -hlocalhost -uroot -p123456 school >D:a.sql
#多張表導出,用空格隔開,命令行是用空格
#mysqldump -h主機 -u用戶名 -p密碼 數據庫 表1 表2 表3 >物理磁盤位置/文件名
mysqldump -hlocalhost -uroot -p123456 school student >D:a.sql

命令行導入——linux中使用

#登錄的情況下導入,先切換到指定的數據庫
#source 備份文件
source d:a.sql

#未登錄狀態 <表示導入 >表示導出
#mysql -u用戶名 -p密碼 庫名< 備份文件
mysql -uroot -p123456 school student <D:a.sql

項目數據庫設計

數據庫設計對比

數據庫設計.png
博客數據庫設計.png

數據庫三大范式——數據庫設計規范

找技術的知識的話比如博客要找有例子的,這樣看比較清楚簡單一點。

第一范式(1NF—— First Normal Form)

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

第二范式(2NF)

前提:滿足第一范式

單一職責原則:每張表只描述一件事情。

第三范式(3NF)

前提:滿足第一、第二范式

確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。

也就是訂單表里只能關聯商品id,而不能把商品價格、商品種類、商品名稱等商品表信息都加進來。

規范性和性能的問題

  • 關聯查詢最多不得超過三張表
  • 考慮商業化的需求和目標,數據庫的性能更重要
  • 考慮查詢性能問題故意給某些表增加冗余字段。(從多表查詢變為單表查詢)

其他

保存或更新操作的原理

原理如下代碼,先判斷出傳入的保存/更新對象是否包含主鍵id,包含的話執行根據id查詢語句,如果得到數據則走更新操作,否則執行插入操作。

    public boolean saveOrUpdate(T entity) {
        if (null == entity) {
            return false;
        } else {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
            Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
            String keyProperty = tableInfo.getKeyProperty();
            Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
            Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
            return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
        }
    }

參考

狂神MySQL基礎

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容