一份超長的MySQL學習筆記


前言

  • 最近系統地學習了一邊MySQL數據庫的基礎知識,鞏固了一下以前學習的數據庫查詢基礎,又新學習了關於索引、事務等的新內容,做了一些學習筆記。因為MySQL的學習,實操性比較強,所以筆記內容也比較簡單,主要是關於常用語句的操作的整理和練習。

  • 本文包括一些學習資源和教程,可以根據個人情況來按照教程學習,學習過程中也可以參考本筆記,如有錯誤,歡迎指正。

學習資源

數據庫

備份數據庫

mysqldump -u root -p -B 數據庫名 > d:\\文件名.sql

恢復數據庫

SOURCE d:\\bak.sql

備份數據庫表

mysqldump -u root -p  數據庫名 表1 表2 > d:\\文件名.sql

數據表

創建

#創建
CREATE TABLE `user`(
	id INT,
	`name` VARCHAR(255),
	`password` VARCHAR(255),
	`birthday` DATE)
	CHARACTER SET utf8 COLLATE utf8_bin ENGINE INNODB;

刪除

drop table `actor`;

修改

--在password后面添加salary列
ALTER TABLE `user`
	ADD salary VARCHAR(32) NOT NULL DEFAULT '' 
	AFTER PASSWORD;
	
--修改列birthday字段的結構
ALTER TABLE `user`
	MODIFY birthday VARCHAR(60) NOT NULL DEFAULT '';

--刪除name字段
ALTER TABLE `user`
	DROP NAME;

--重命名表
RENAME TABLE `user` TO `student`;

--修改表的字符集為utf8
ALTER TABLE student CHARACTER SET utf8;

--修改列名salary為user_name
ALTER TABLE student 
	CHANGE salary user_name VARCHAR(32) NOT NULL DEFAULT '';

DESC `user`;--顯示表結構,查看所有的列

CRUD(增刪改查)

insert

INSERT INTO `goods`(id,good_name,price)
	VALUES (1,'華為手機',2000);
INSERT INTO `goods`(id,good_name,price)
	VALUES (2,'蘋果手機',3000);

update

UPDATE `goods`SET price = 1000;
UPDATE `goods`SET price = 2000 WHERE good_name='華為手機';
UPDATE `goods`SET price=price+5000 WHERE good_name='蘋果手機';
#如果需要修改多個字段,可以通過 set 字段1=值1,字段2=值2...

delete

DELETE FROM `goods` WHERE price=2000;

select

#查找表內所有內容
SELECT * FROM student;
#按列查找表內容
SELECT id FROM student;
SELECT `id`,english FROM student;
#去除重復數據(只有這一行每一列的數據相同的時候才會去重)
SELECT DISTINCT english FROM student;
#使用表達式對查詢的列進行運算
#在select語句中可使用as語句
SELECT `name`AS`名字`,(chinese+english+math) AS `COUNT` FROM student;
#條件查詢
SELECT * FROM student 
	WHERE `name` = '趙雲';
SELECT * FROM student 
	WHERE `english` > 90;
SELECT * FROM student 
	WHERE (chinese + english + math) > 200;
#order by
	#升序
SELECT `name`,(chinese + english + math)AS`count` FROM student 
	WHERE (chinese+english+math)>200 
	ORDER BY math ASC;
	#降序
SELECT `name`,(chinese + english + math)AS`count` FROM student 
	WHERE (chinese+english+math)>200 
	ORDER BY math DESC;
#多條件升降序查詢
SELECT `name`,(chinese+english+math)AS`count` FROM student 
	WHERE `name` LIKE '張%'
	ORDER BY `count` DESC;

where語句中常用到的運算符

MySQL函數

合計/統計函數

#count(返回查詢結果的行數)
#統計滿足條件的某列有多少個,但是會排除為null的情況
SELECT COUNT(*) FROM student;

SELECT COUNT(*) FROM student
	WHERE (math+chinese+english)>200;
	
SELECT COUNT(chinese) FROM student
	WHERE chinese>90;
	

#SUM函數
#僅對數值起作用,否則會報錯
SELECT SUM(math) FROM student;
SELECT SUM(math),SUM(chinese),SUM(english) FROM student;
SELECT SUM(chinese+english+math) FROM student;
SELECT SUM(chinese)/COUNT(*) FROM student;

#AVG函數
SELECT AVG(math) FROM student;
SELECT AVG(math+english+chinese) FROM student;

#MAX函數
SELECT MAX(math) FROM student;
#MIN函數
SELECT MIN(math) FROM student;

分組統計

--按照部門查詢工資平均值和最大值
SELECT AVG(sal),MAX(sal),deptno FROM emp GROUP BY deptno; 

--多條件分組
SELECT AVG(sal),MAX(sal),deptno , job FROM emp GROUP BY deptno , job;

--查找平均工資低於2000的部門
SELECT  AVG(sal) , deptno FROM emp GROUP BY deptno HAVING AVG(sal) < 2000;

字符串函數


加密和系統函數

--演示加密函數和系統函數

查詢增強

WHERE

-- 查詢增強
-- 	使用where子句
-- 	在MySQL中,日期類型可以直接比較
SELECT * FROM emp WHERE hiredate <= '1991-12-11'; -- 需要注意格式

-- 模糊查詢like
--	%表示0~多個任意字符
--	_表示單個任意字符
SELECT ename,sal FROM emp WHERE ename LIKE 'S%' ;
SELECT ename,sal FROM emp WHERE ename LIKE '__o%';

-- 顯示沒有上級的員工信息
SELECT * FROM emp WHERE mgr IS NULL;

-- 查詢表結構
DESC emp;

ORDER BY

-- 使用ORDER BY
--	按照工資從低到高顯示信息
SELECT * FROM emp ORDER BY sal; -- 默認降序
SELECT * FROM emp ORDER BY deptno ASC; -- 升序
SELECT * FROM emp ORDER BY deptno ASC , sal DESC;

分頁查詢

-- 分頁查詢
SELECT * FROM emp ORDER BY empno LIMIT 0,3;-- 第一頁
SELECT * FROM emp ORDER BY empno LIMIT 3,3;-- 第二頁

分組增強

-- 增強 GROUP BY 的使用
SELECT COUNT(*) FROM emp GROUP BY job;-- 各個崗位的人數
SELECT COUNT(*),COUNT(comm) FROM emp;-- 雇員總數、獲得補助的雇員數

多子句查詢

--統計各部門平均工資,並且大於1000的按照平均工資降序排序,取出前兩行數據
SELECT deptno,AVG(sal) AS avg_sal
	FROM emp
	GROUP BY deptno
	HAVING avg_sal > 1000
	ORDER BY avg_sal DESC
	LIMIT 0,2;

多表查詢

多表笛卡爾集

-- 多表查詢
SELECT * FROM emp,dept; 
SELECT * FROM emp;
SELECT * FROM dept;

-- 顯示雇員名稱和雇員所在部門的名稱
-- 從第一張表取出一行,與第二張表中的每一行進行組合,返回結果包含兩張表的所有列
SELECT ename,sal,dname,emp.deptno FROM emp,dept WHERE emp.deptno = dept.deptno;

-- 顯示部門10的部門名、員工名、工資
SELECT ename,sal,dname,emp.deptno FROM emp,dept WHERE emp.deptno = dept.deptno AND emp.deptno = 10;

-- 顯示各個員工的姓名、工資和工資級別
SELECT ename,sal,grade FROM emp,salgrade WHERE sal BETWEEN losal AND hisal;

自連接

自連接是指在同一張表的連接查詢,即將同一張表看成兩張表

-- 自連接
SELECT worker.ename AS '職員名',boss.ename AS '上級名' 
	FROM emp worker,emp boss
	WHERE worker.mgr = boss.empno;

子查詢

單/多行子查詢

子查詢是指嵌入在其他SQL語句中的select語句,也叫嵌套查詢

  • 單行子查詢

    單行子查詢是指只返回同一行數據的子查詢語句

    例:如何顯示與SMITH同一部門的所有員工

  • 多行子查詢

    多行子查詢指返回多行數據的子查詢,使用關鍵字in

-- 子查詢

-- 單行子查詢
SELECT deptno FROM emp WHERE ename = 'SMITH'; -- 子查詢語句

SELECT * FROM emp
	WHERE deptno = (
		SELECT deptno FROM emp WHERE ename = 'SMITH'
	);


-- 多行子查詢
SELECT DISTINCT job FROM emp WHERE deptno = 10; -- 子查詢語句

SELECT ename,job,sal,deptno FROM emp 
	WHERE job IN (
		SELECT DISTINCT job FROM emp WHERE deptno = 10
	) AND deptno != 10;

子查詢臨時表

可以將子查詢結果當做一張臨時表使用


all any

-- all 和 any

-- 顯示工資比部門30所有員工的工資都高的員工的姓名、工資和部門號
SELECT ename,sal,deptno FROM emp 
	WHERE sal > ALL(
		SELECT sal FROM emp WHERE deptno = 30
		);

SELECT ename,sal,deptno FROM emp 
	WHERE sal > (
		SELECT MAX(sal) FROM emp WHERE deptno = 30
		);
		
-- 顯示工資比30號部門的其中一個員工工資高的員工的姓名、工資和部門號
SELECT ename,sal,deptno FROM emp 
	WHERE sal > ANY(
		SELECT sal FROM emp WHERE deptno = 30
		);
		
SELECT ename,sal,deptno FROM emp 
	WHERE sal > (
		SELECT MIN(sal) FROM emp WHERE deptno = 30
		);ss

多列子查詢

多列子查詢是指查詢返回多個列數據的子查詢語句

-- 多列子查詢

-- 查詢與 SMITH 的部門和和崗位完全相同的所有雇員(不包含SMITH本人)
SELECT deptno,job FROM emp
	WHERE ename = 'SMITH'; -- 子查詢語句

-- 把上面的子查詢語句與下面的多列子查詢語句進行匹配
SELECT ename FROM emp
	WHERE (deptno,job) = (
		SELECT deptno,job FROM emp
		WHERE ename = 'SMITH'
	) AND ename != 'SMITH';

表復制和去重

  • 自我復制數據(蠕蟲復制)

    為了對某個SQL語句進行效率測試,我們需要海量數據時,可以使用此方法為表創建海量數據

-- 表復制

CREATE TABLE my_tab01
	(
		id INT,
		`name` VARCHAR(32),
		sal DOUBLE,
		job VARCHAR(32),
		deptno INT
	);

DESC my_tab01;

-- 演示如何自我復制
-- 先把emp表的記錄復制進 my_tab01
INSERT INTO my_tab01 
	(id,`name`,sal,job,deptno)
	SELECT empno,ename,sal,job,deptno FROM emp; -- 相當於數據遷移
	
-- 自我復制
INSERT INTO my_tab01
	SELECT * FROM my_tab01;
	
-- 去重
DELETE FROM my_tab01;

合並查詢

-- 合並查詢
SELECT ename,sal,job FROM emp WHERE sal > 2500;
SELECT ename,sal,job FROM emp WHERE job = 'MANAGER';

-- UNION不會去重
SELECT ename,sal,job FROM emp WHERE sal > 2500
UNION ALL
SELECT ename,sal,job FROM emp WHERE job = 'MANAGER';

外連接

-- 左外連接
-- 右外連接

主鍵

MySQL約束

約束用於確保數據庫滿足特定的商業規則,在MySQL中,約束包括:

NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK

主鍵的指定

-- 主鍵的使用

CREATE TABLE t17 (
	id INT PRIMARY KEY,
	`name` VARCHAR(32),
	email VARCHAR(32)	
	);
	
INSERT INTO t17
	VALUE(1,'jack','shuaiwang2019@126.com');
INSERT INTO t17
	VALUE(2,'wangshuai','jack2019@126.com');
INSERT INTO t17
	VALUE(3,'jack','shuaiwang2019@126.com');
	
-- 主鍵使用的細節

-- PRIMARY KEY 不能重復,而且不能為 NULL
-- 一張表中只能有一個主鍵,但可以是復合主鍵
CREATE TABLE t18 (
	id INT,
	`name` VARCHAR(32),
	email VARCHAR(32),
	PRIMARY KEY (id,`name`) -- 復合主鍵	
	);
-- 主鍵指定方式有兩種:
-- 在字段名后指定
-- 在SQL語句后面指定

DESC t18;

UNIQUE

-- unique的使用

CREATE TABLE t21 (
	id INT UNIQUE, -- 表示id列是唯一的
	`name` VARCHAR(32),
	email VARCHAR(32)	
	);
	
-- unique的使用細節
-- 如果沒有指定not null,則unique字段可以有多個null
-- 一張表可以有多個unique字段

FOREIGN KEY(外鍵)

用於定義主表和從表之間的關系:外鍵約束要定義在從表上,主表則必須有主鍵約束或是unique約束,當定義外鍵約束之后,要求外鍵列數據必須在主表的主鍵列存在或是為null

-- 外鍵的使用

-- 創建班級表
CREATE TABLE class(
	id INT PRIMARY KEY,
	`name` VARCHAR(32) NOT NULL DEFAULT ''
)
-- 創建學生表
CREATE TABLE stu(
	id INT PRIMARY KEY,
	`name` VARCHAR(32) NOT NULL DEFAULT '',
	class_id INT,
	-- 下面指定外鍵關系
	FOREIGN KEY (class_id) REFERENCES class (id)
);
DESC stu;

-- 測試數據
INSERT INTO class
	VALUES (100,'java'),(200,'web');
INSERT INTO stu
	VALUES (1,'張三',100),(2,'張三',200);
	
	
-- 外鍵細節
-- 外鍵指向的表的字段,要求是primary key或者是unique
-- 表的類型是innodb,這樣的表才支持外鍵
-- 外鍵字段類型主要和主鍵字段類型一致(長度可以不同)
-- 外鍵字段的值,必須在之間字段中出現過,或者為null(前提是外鍵字段允許null)
-- 一旦建立主外鍵的關系,數據就不能隨意刪除了

CHECK

用於強制型數據必須滿足的條件,假如在sal列上定義了check約束,並要求sal列值在100~200之間,不在的話就會報錯

-- CHECK的使用
CREATE TABLE t23 (
	id INT PRIMARY KEY,
	`name` VARCHAR(32),
	sex VARCHAR(6) CHECK(sex IN ('man','woman')),
	sal DOUBLE CHECK(sal>1000 AND sal<2000)
	);
	
INSERT INTO t23 VALUES
	(1,'jack','man',1500);

練習

-- 商店表設計
CREATE TABLE goods(
	goods_id INT PRIMARY KEY,
	goods_name VARCHAR(32) NOT NULL DEFAULT '',
	unitprice DOUBLE CHECK(unitprice>1.0 AND unitprice<9999.99)
);

CREATE TABLE customer(
	customer_id INT PRIMARY KEY,
	`name` VARCHAR(32) NOT NULL DEFAULT '',
	address VARCHAR(32),
	email VARCHAR(32) UNIQUE,
	sex VARCHAR(6) CHECK(sex IN ('man','woman')),
	card_id INT
);

CREATE TABLE purchase(
	order_id INT PRIMARY KEY,
	customer_id INT NOT NULL,
	goods_id INT NOT NULL,
	nums INT NOT NULL DEFAULT 0,
	FOREIGN KEY (customer_id) REFERENCES customer (customer_id),
	FOREIGN KEY (goods_id) REFERENCES goods(goods_id)
);

自增

-- 自增使用
CREATE TABLE t24(
	id INT PRIMARY KEY AUTO_INCREMENT,
	`name` VARCHAR(32) NOT NULL DEFAULT''
);

INSERT INTO t24 VALUES (NULL,'jack');

MySQL索引

索引優化速度

說起提高數據庫性能,索引最為物美價廉,不需要加內存,不需要改程序,不需要調SQL,查詢速度就可能提高百倍千倍


索引機制

索引原理

  • 當表中沒有索引的時候,SQL語句查詢過程是按照 WHERE 條件進行全表掃描,與每一條數據進行對比,效率非常低下;
  • 在某一個字段的列創建索引之后,會創建二叉樹,提高查找數據的效率;
  • 生成的索引會占用磁盤;
  • 對表進行dml操作(修改,刪除,添加),會對索引進行維護,對速度有影響。

創建索引

主鍵索引

主鍵就是一種索引 PRIMARY KEY,即主鍵索引。

唯一索引

UNIQUE 的字段的索引被稱為唯一索引。

普通索引

全文索引

適用於 MyISAM 存儲引擎,開發中考慮使用:全文索引 Solr 和 ElasticSearch(ES)

-- 索引的使用

-- 主鍵索引
CREATE TABLE t25(
	id INT,
	`name` VARCHAR(32)
);

-- 查詢表是否有索引
SHOW INDEXES FROM t25;

-- 添加索引
-- 添加唯一索引
CREATE UNIQUE INDEX id_index ON t25 (id);
-- 添加普通索引
CREATE INDEX id_index ON t25 (id);
ALTER TABLE t25 ADD INDEX id_index (id);
-- 添加主鍵索引
ALTER TABLE t25 ADD PRIMARY KEY id_index (id);

-- 刪除索引
DROP INDEX id_index ON t25;
-- 刪除主鍵索引
ALTER TABLE t25 DROP PRIMARY KEY;

-- 修改索引(先刪除,再添加新的索引)

-- 查詢索引
SHOW INDEX FROM t25;
SHOW INDEXES FROM t25;
SHOW KEYS FROM t25;
#不推薦
DESC t25;


創建索引規則

在哪些列上適合使用索引?

  • 較頻繁的作為查詢條件字段應該創建索引;
  • 唯一性太差的字段不適合單獨創建索引,即使頻繁作為查詢條件;
  • 更新非常頻繁的字段不適合創建索引;
  • 不會出現在WHERE子句中的字段不該創建索引。

事務

事務概念

事務用於保證數據的一致性,它由一組相關的dml語句組成,該組的dml語句要么全部成功,要么全部失敗。如:轉賬就要用事務來處理,用以保證數據的一致性。

事務和鎖

當執行事務操作時(dml語句),MySQL會在表上加鎖,防止其他用戶修改表的數據,這對用戶來講是非常重要的。

MySQL數據庫控制台事務的幾個重要操作

-- 創建測試表
CREATE TABLE t27(
	id INT,
	`name` VARCHAR(32)
);

-- 開啟事務
START TRANSACTION;
-- 設置保存點
SAVEPOINT a;
-- 執行dml操作
INSERT INTO t27 VALUES (100,'jack');
SELECT * FROM t27;
-- 設置保存點
SAVEPOINT b;
INSERT INTO t27 VALUES(200,'ben');

-- 數據回滾
ROLLBACK TO b;
ROLLBACK TO a;

-- 回退全部事務
ROLLBACK;

-- 提交事務,所有的操作生效,不能回退
COMMIT

事務注意事項

-- 事務注意事項

-- 如果不開啟事務,默認情況下,dml操作是自動提交的,不能回滾;
-- 如果開啟一個事務,沒有創建保存點,可以執行rollback,默認就是回退到事務開始的狀態;
-- 可以在事務沒有提交的時候,創建多個保存點;
-- 可以在事務沒有提交之前,選擇回退到哪個保存點;
-- MySQL的事務機制需要innodb的存儲引擎才能使用;
-- 開始一個事務 
START TRANSACTION ,
SET autocommit = off;

隔離級別

4種隔離級別

  • 多個連接開啟各自事務操作數據庫中數據時,數據庫系統要負責隔離操作,以保證各個連接在獲取數據時的准確性
  • 如果不考慮隔離性,可能會引發如下問題
    • 臟讀
    • 不可重復讀
    • 幻讀
-- 臟讀:當一個事務讀取另一個事務尚未提交的修改時,會產生臟讀

-- 不可重復讀:同一查詢在同一事務中多次進行,由於其他提交事務所做的修改或刪除,每次返回不同的結果集,此時發生不可重復讀

-- 幻讀:同一查詢在同一事務中多次進行,由於其他提交事務所做的插入操作,每次返回不同的結果集,此時發生幻讀
-- 演示MySQL的事務隔離級別

-- 開啟兩個MySQL控制台
-- 查看當前MySQL的隔離級別
SELECT @@tx_isolation;
SELECT @@transaction_isolation;
-- mysql> select @@transaction_isolation;
-- +-------------------------+
-- | @@transaction_isolation |
-- +-------------------------+
-- | REPEATABLE-READ         |
-- +-------------------------+
-- 1 row in set (0.00 sec)

-- 把其中一個控制台的隔離級別設置 Read uncommitted
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 創建表
CREATE TABLE ACCOUNT(
	id INT,
	`name` VARCHAR(32),
	money INT
);

-- 把其中一個控制台的隔離級別設置 Read committed
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- mysql> SELECT @@transaction_isolation;
-- +-------------------------+
-- | @@transaction_isolation |
-- +-------------------------+
-- | READ-COMMITTED          |
-- +-------------------------+
-- 1 row in set (0.00 sec)

-- 把其中一個控制台的隔離級別設置 Repeatable read
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 把其中一個控制台的隔離級別設置 Serializable
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

設置隔離

-- 設置隔離

-- 查看當前會話隔離級別
SELECT @@transaction_isolation;
-- 查看系統當前隔離級別
SELECT @@global.transaction_isolation;
-- 設置當前會話隔離級別
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 設置系統當前隔離級別
SET GLOBAL TRANSACTION ISOLATION LEVEL [級別];
-- MySQL的默認級別
REPEATABLE READ;

-- 事務的acid特性

-- 原子性:原子性是指事務是一個不可分割的工作單位,事務中的操作要么都發生,要么都不發生
-- 一致性:事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態
-- 隔離性:事務的隔離性是多個用戶並發訪問數據庫時,數據庫為每一個用戶開啟的一個事務,不能被其他事務的操作數據所干	 擾,多個並發事務之間要相互隔離
-- 持久性:持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其    有任何影響

MySQL表類型和存儲引擎

  • MySQL的表類型由存儲引擎(Storage Engines)決定,主要包括MyISAM、innoDB、Memory等
  • MySQL數據表主要支持6種類型,分別是:CSV、Memory、ARCHIVE、MRG_MYISAM、MYISAM、InnoBDB。
  • 這六種類型分為兩類,一類是“事務安全型”(transaction-safe):InnoDB;其余都屬於第二類,稱為“非事務安全型”(non-transaction-safe)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM