MySQL基礎
函數
常用函數
- 數學運算
SELECT ABS(-8) -- 絕對值
SELECT CEILING(9.4) -- 向上取整
SELECT FLOOR(9.4) -- 向下取整
SELECT RAND() -- 返回一個 0~1 之間的隨機數
SELECT SIGN(10) -- 判斷一個數的符號 0-0 負數返回-1,正數返回 1
- 字符串函數
SELECT CHAR_LENGTH('啊哈哈哈哈哈') -- 字符串長度
SELECT CONCAT('我','愛','你') -- 拼接字符串
SELECT INSERT('你好世界',1,2,'Hello') -- 從某個位置開始替換某個長度 你好世界-->Hello世界
SELECT LOWER('Hello') -- 小寫字母
SELECT UPPER('Hello') -- 大寫字母
SELECT INSTR('kuangshen','h') -- 返回第一次出現的子串的索引
SELECT REPLACE('你好世界','你好','保護') -- 替換出現的指定字符串,將'你好'替換成'保護'
SELECT SUBSTR('今天天氣真的很好',4,3) -- 返回指定的子字符串 (截取的位置,截取的長度)
SELECT REVERSE('你愛我') -- 反轉
-- 查詢姓張的同學,將姓改爲李
SELECT REPLACE(studentname,'張','李') FROM student WHERE studentname LIKE '張%'
- 時間和日期函數
SELECT CURRENT_DATE() -- 獲取當前日期
SELECT CURDATE() -- 獲取當前日期
SELECT NOW() -- 獲取當前的時間
SELECT LOCALTIME() -- 本地時間
SELECT SYSDATE() -- 系統時間
SELECT YEAR(NOW())
SELECT MONTH(NOW())
SELECT DAY(NOW())
SELECT HOUR(NOW())
SELECT MINUTE(NOW())
SELECT SECOND(NOW())
- 系統
SELECT SYSTEM_USER() -- 用戶
SELECT USER()
SELECT VERSION() -- 版本號
聚合函數
- COUNT():計數
COUNT(字段):會忽略所有的 null 值
COUNT(*):不會忽略 null 值, 本質是計算行數
COUNT(1):不會忽略 null 值, 本質是計算行數 - SUM():求和
- AVG():平均值
- MAX():最大值
- MIN():最小值
-- 統計student`BornDate`字段個數
SELECT COUNT(`BornDate`) FROM student;
SELECT COUNT(*) FROM student;
SELECT COUNT(1) FROM result;
-- 計算student成績的總和、平均分、最高分、最低分
SELECT SUM(`StudentResult`) AS 總和 FROM result
SELECT AVG(`StudentResult`) AS 平均分 FROM result
SELECT MAX(`StudentResult`) AS 最高分 FROM result
SELECT MIN(`StudentResult`) AS 最低分 FROM result
數據庫級別的MD5算法加密
我們創建一個test
表
CREATE TABLE `test`(
`id` INT(4) NOT NULL,
`name` VARCHAR(20) NOT NULL,
`pwd` VARCHAR(50) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
插入數據,即明文和密碼
INSERT INTO test VALUES(1,'zhangsan','123456'),(2,'lisi','123456'), (3,'wangwu','123456')
加密
-- 加密第一個人的密碼
UPDATE test SET pwd=MD5(pwd) WHERE id = 1
-- 加密全部的密碼
UPDATE test SET pwd=MD5(pwd)
-- 插入數據時加密
INSERT INTO test VALUES(4,'xiaoming',MD5('123456'))
-- 如何校驗:將用戶傳遞進來的密碼,進行md5加密,然後比對加密後的值
SELECT * FROM test WHERE `name`='xiaoming' AND pwd=MD5('123456')
加密後:
事務
- 概述:MySQL 事務主要用於處理操作量大,複雜度高的數據。比如,在人員管理系統中,你刪除一個人員,你既需要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等,此時這些數據庫操作語句就構成一個事務!
- 條件:
事務是必須滿足4個條件(ACID):原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、持久性(Durability)。
- 原子性
一個事務要麼都成功,要麼都失敗。 - 一致性
事務開始之前和事務結束以後,數據庫的完整性沒有被破壞。 - 隔離性
事務的隔離性是多個用戶併發訪問數據庫時,數據庫爲每一個用戶開啓的事務,不能被其他事務的操作 數據所幹擾,多個併發事務之間要相互隔離。 - 持久性
事務處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。
- 執行事務
用 START、ROLLBACK, COMMIT來實現
-- 標記一個事務的開始,從這個之後的 sql 都在同一個事務內
START TRANSACTION
-- 回滾: 回到的原來的樣子 (失敗!)
ROLLBACK
-- 提交: 持久化 (成功!)
COMMIT
mysql 是默認開啓事務自動提交的
SET autocommit = 0 /* 關閉 */
SET autocommit = 1 /* 開啓 */
-- 事務開啓
其他
SAVEPOINT 保存點名 -- 設置一個事務的保存點
ROLLBACK TO SAVEPOINT 保存點名 -- 回滾到保存點
RELEASE SAVEPOINT 保存點名 -- 撤銷保存點
- 模擬事務:模擬銀行轉賬
假設A用戶有2000,B用戶有10000
轉賬成功:B成功接收
轉賬失敗:B沒有收到
-- 創建shop數據庫
CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci USE shop
-- 創建account表
CREATE TABLE `account`(
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入兩個用戶
INSERT INTO account(`name`,`money`) VALUES ('A',2000.00),('B',10000.00)
創建成功:
模擬轉賬:不提交,直接回滾
SET autocommit = 0; -- 關閉自動提交
START TRANSACTION -- 開啓一個事務 (一組事務)
UPDATE account SET money=money-500 WHERE `name` = 'A' -- A減500
UPDATE account SET money=money+500 WHERE `name` = 'B' -- B加500
ROLLBACK; -- 回滾
開啓事務,回滾前:
回滾後:
模擬轉賬:提交事務後被持久化了,回滾失效
UPDATE account SET money=money-500 WHERE `name` = 'A' -- A減500
UPDATE account SET money=money+500 WHERE `name` = 'B' -- B加500
COMMIT; -- 提交事務,就被持久化了
ROLLBACK; -- 回滾
結果:
索引
- 概述:索引(Index)是幫助MySQL高效獲取數據的數據結構,索引的建立對於MySQL的高效運行是很重要的,索引可以大大提高MySQL的檢索速度;打個比方,如果合理的設計且使用索引的MySQL是一輛蘭博基尼的話,那麼沒有設計和使用索引的MySQL就是一個人力三輪車。
- 分類:
- 主鍵索引 (PRIMARY KEY ): 唯一的標識,主鍵不可重複,只能有一個列作爲主鍵 ;
- 唯一索引 (UNIQUE KEY): 避免重複的列出現,唯一索引可以重複,多個列都可以標識爲唯一索引;
- 常規索引 (KEY / INDEX): 默認的, index 或 key 關鍵字來設置;
- 全文索引 (Full Text): 在特定的數據庫引擎下才有:MyISAM,快速定位數據。
- 索引的使用
-- 顯示所有的索引信息
SHOW INDEX FROM `student`
-- 增加一個全文索引
ALTER TABLE school.student ADD FULLTEXT INDEX `studentName`(`studentName`);
-- EXPLAIN 分析sql執行的狀況
EXPLAIN SELECT * FROM student; -- 非全文索引
EXPLAIN SELECT * FROM student WHERE MATCH(studentName) AGAINST('劉');
- 測試索引(必須大數據纔可以看出效果)
創建表:
CREATE TABLE `app_user` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) DEFAULT '' COMMENT '用戶暱稱',
`email` VARCHAR(50) NOT NULL COMMENT '用戶郵箱',
`phone` VARCHAR(20) DEFAULT '' COMMENT '手機號',
`gender` TINYINT(4) UNSIGNED DEFAULT '0' COMMENT '性別(0:男;1:女)',
`password` VARCHAR(100) NOT NULL COMMENT '密碼',
`age` TINYINT(4) DEFAULT '0' COMMENT '年齡',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`update_time` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='app用戶表'
插入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 app_user(`name`,`email`,`phone`,`gender`,`password`,`age`)
VALUES(CONCAT('用 戶',i),'[email protected]',
CONCAT('18',FLOOR(RAND()*((999999999-100000000)+100000000))),
FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100));
SET i = i+1;
END WHILE;
RETURN i;
END;
-- 先執行上面的代碼,在SELECT 這個函數
SELECT mock_data();
結果:
對比普通查詢和索引查詢:
1)普通查詢:
SELECT * FROM app_user WHERE `name` = '用戶9999'; -- 耗時:2.365 sec
SELECT * FROM app_user WHERE `name` = '用戶9999'; -- 耗時:1.959 sec
EXPLAIN SELECT * FROM app_user WHERE `name` = '用戶9999';
結果:發現普通查詢經歷了992934行,纔得到我們的結果
2)索引查詢
-- 創建索引
CREATE INDEX id_app_user_name ON app_user(`name`);
SELECT * FROM app_user WHERE `name` = '用戶9999'; -- 耗時:0.001 sec
EXPLAIN SELECT * FROM app_user WHERE `name` = '用戶9999';
結果:索引查詢精準定位,只經歷一行,就得到結果
- 注意:
1)索引不是越多越好;
2)不要對進程變動數據加索引;
3)小數據量的表不需要加索引;
4)索引一般加在常用來查詢的字段上。
// 下篇再見…謝謝