MySQL函數&事務

MySQL函數

爲了簡化使用,MySQL提供了大量的函數給程序員使用,使用與大多數的語句中

字符串函數

  1. 函數:CONCAT(s1,s2…sn)
    描述:字符串 s1,s2 等多個字符串合併爲一個字符串
    實例:select concat(‘我愛’,’-’,‘中國’);

  2. 函數:CHAR_LENGTH(str)
    描述:返回字符串 str 的字符數
    實例:select char_length(‘你好,樹先生’);

  3. 函數:LENGTH(str)
    描述:返回字符串 s 的字節數
    編碼:UTF8(一箇中文字符佔3個字節)
    實例:select length(‘你好,樹先生h’);

  4. 函數:UCASE(s) | UPPER(s)
    描述:將字符串轉換爲大寫
    實例:select ucase(‘itcast’);

  5. 函數:LCASE(s) | LOWER(s)
    描述:將字符串轉換爲小寫
    實例:select lcase(‘ITCAST’);

  6. 函數:LOCATE(s1,s)
    描述:從字符串 s 中獲取 s1 的開始位置
    注意:從1開始
    實例:select locate(‘hei’,‘itheima’);

  7. 函數:TRIM(str) | LTRIM(str) | RTRIM(str)
    描述:字符串去空格
    實例:select trim(’ 莘莘學子 ');

  8. 函數:REPLACE(s,s1,s2)
    描述:將字符串 s2 替代字符串 s 中的字符串 s1
    實例:select replace(‘abc’,‘b’,‘x’);

  9. 函數:SUBSTR(s, start, length)
    描述:從字符串 s 的 start 位置截取長度爲 length 的子字符串
    注意:從1開始
    實例:select substr(‘itcast’,‘2’,‘3’);

  10. 函數:STRCMP(str1,str2)
    描述:比較字符串大小,左大於右時返回1,左等於右時返回0,,左小於於右時返回-1,
    實例:select strcmp(‘a’,‘b’);

-- 字符串函數
-- 1.將所有員工的暱稱改爲大寫
SELECT UCASE(nickname) FROM emp;
-- 2.顯示所有員工的姓氏,截取
SELECT ename, SUBSTR(ename,1,1) AS 姓氏 FROM emp;
-- 3.顯示所有員工姓名字符長度
SELECT CHAR_LENGTH(ename) FROM emp;
-- 4.顯示所有員工姓名字節長度
SELECT LENGTH(ename) FROM emp;
-- 5.將所有姓李的員工,姓氏替換爲li
SELECT REPLACE(ename,'李','li') FROM emp;
-- 6.將所有員工的姓名和暱稱拼接在一起
SELECT CONCAT(ename,nickname)FROM emp;

日期函數

  1. 函數:NOW() | CURDATE() | CURTIME()
    描述:獲取系統當前日期時間、日期、時間
    實例:select now();

  2. 函數:YEAR(DATE) | MONTH(DATE) | DAY(DATE)
    描述:從日期中選擇出年、月、日
    實例:select year(now());

  3. 函數:LAST_DAY(DATE)
    描述:返回月份的最後一天
    實例:select last_day(now());

  4. 函數:ADDDATE(DATE,n) | SUBDATE(DATE,n)
    描述:計算起始日期 DATE 加(減) n 天的日期
    實例:select subdate(now(),10);

  5. 函數:QUARTER(DATE)
    描述:返回日期 DATE 是第幾季節,返回 1 到 4
    實例:select quarter(now());

  6. 函數:DATEDIFF(d1,d2)
    描述:計算日期 d1->d2 之間相隔的天數
    實例:select datediff(now(),‘1999-1-1’);

  7. 函數:DATE_FORMAT(d,f)
    描述:按表達式 f的要求顯示日期 d
    實例:select date_format(now(),’%Y-%m-%d’);

-- 日期函數
-- 1.統計每個員工入職的天數
SELECT ename,DATEDIFF(NOW(),joindate)FROM emp;
-- 2.統計每個員工的工齡
SELECT ename,DATEDIFF(NOW(),joindate)/365 FROM emp;
-- 3.查詢2011年入職的員工
SELECT * FROM emp WHERE YEAR(joindate)='2011';
-- 4.統計入職10年以上的員工信息
SELECT *FROM emp WHERE DATEDIFF(NOW(),joindate)/365 > 10;

數字函數

  1. 函數:ABS(x)
    描述:返回 x 的絕對值  
    實例:select abs(-10);

  2. 函數:CEIL(x) | FLOOR(x)
    描述:向上(下)取整
    實例:select ceil(1.5);

  3. 函數:MOD(x,y)
    描述:返回x mod y的結果,取餘
    實例:select mod(5,4);

  4. 函數:RAND()
    描述:返回 0 到 1 的隨機數
    實例:select rand();

  5. 函數:ROUND(x)
    描述:四捨五入
    實例:select round(1.2345);

  6. 函數:TRUNCATE(x,y)
    描述:返回數值 x 保留到小數點後 y 位的值
    實例:select truncate(5633.123324,2);

-- 數字函數
-- 1.統計每個員工的工齡,超過半年的算一年
SELECT ename,ROUND(DATEDIFF(NOW(),joindate)/365) FROM emp;
-- 2.統計每個部門的平均薪資,保留2位小數
SELECT dept_id,TRUNCATE(AVG(salary),2) FROM emp GROUP BY dept_id;
-- 3.統計每個部門的平均薪資,小數向上取整
SELECT dept_id,CEIL(AVG(salary)) FROM emp GROUP BY dept_id;
-- 4.統計每個部門的平均薪資,小數向下取整
SELECT dept_id,FLOOR(AVG(salary)) FROM emp GROUP BY dept_id;

高級函數

CASE表達式

  • 相當於java中的switch語句
  • 語法:
SELECT 
		CASE [字段,] 
			WHEN 判斷條件1 
				THEN 希望的到的值1
			WHEN 判斷條件2 
				THEN 希望的到的值2
			ELSE 前面條件都沒有滿足情況下得到的值 
		END
	FROM
		table_name;
-- CASE表達式
-- 查詢每個員工的工資等級並排序
-- 工資等級在1顯示爲 '努力賺錢'
-- 工資等級在2顯示爲 '小康生活'
-- 工資等級在3顯示爲 '可以找女朋友'
-- 工資等級在4顯示爲 '可以買車'
-- 工資等級在5顯示爲 '可以買房'
-- 工資等級不在以上列表中顯示爲  '土豪'

-- 1.確定幾張表
SELECT *FROM emp e INNER JOIN salarygrade sg;
-- 2.確定連接條件
SELECT *FROM emp e INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 3.確定顯示字段
SELECT e.ename,e.salary,sg.grade FROM emp e INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 4.確定業務條件
SELECT e.ename,e.salary,
    CASE sg.grade
    WHEN 1 THEN '努力賺錢'
    WHEN 2 THEN '小康生活'
    WHEN 3 THEN '可以找女朋友'
    WHEN 4 THEN '可以買車'
    WHEN 5 THEN '可以買房'
    ELSE '土豪'
    END AS '生活狀態'
FROM emp e INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary ORDER BY sg.grade ASC;

IF表達式

  • 相當於java中三元運算符
  • 語法:SELECT IF(1 > 0,'真','假') from 表名;
-- IF表達式
-- 工資+獎金大於20000的員工 顯示家有嬌妻,否則顯示單身狗
SELECT ename, IF(salary+IFNULL(bonus,0)>20000,'有女朋友','單身狗')AS 個人狀態 FROM emp;

綜合練習

-- MYSQL綜合案例
-- 1.計算員工的日薪(按30天),保留二位小數
SELECT ename,TRUNCATE(salary/30,2) FROM emp;
-- 2.計算出員工的年薪(12月),並且以年薪排序 降序
SELECT ename,(salary+IFNULL(bonus,0))*12 AS 年薪 FROM emp ORDER BY 年薪 DESC;
-- 3.找出獎金少於5000或者沒有獲得獎金的員工的信息
SELECT * FROM emp WHERE IFNULL(bonus,0)< 5000;
-- 4.返回員工職務名稱及其從事此職務的最低工資
-- 4.1確定幾張表
SELECT *FROM emp e INNER JOIN job j;
-- 4.2確定連接條件
SELECT * FROM emp e INNER JOIN job j ON e.job_id=j.id;
-- 4.3確定顯示字段
SELECT j.jname FROM emp e INNER JOIN job j ON e.job_id=j.id;
-- 4.4確定業務條件(分組+最低工資)
SELECT j.jname,MIN(e.salary) AS 最低工資 FROM emp e INNER JOIN job j ON e.job_id=j.id GROUP BY j.jname;
-- 5.返回工齡超過10年,且2月份入職的員工信息
SELECT *FROM emp WHERE DATEDIFF(NOW(),joindate)/365 >10 AND MONTH(joindate)=2;
-- 6.返回與 林沖 同一年入職的員工
-- 6.1查詢名字是林沖的員工
SELECT YEAR(joindate) FROM emp WHERE ename='林沖';
-- 6.2查詢同一年的員工
SELECT * FROM emp WHERE YEAR(joindate)=(SELECT YEAR(joindate) FROM emp WHERE ename='林沖');
-- 7.返回每個員工的名稱及其上級領導的名稱(自關聯)
SELECT a.ename,b.ename FROM emp a LEFT OUTER JOIN emp b ON a.mgr=b.id;

-- 8.返回工資爲二等級(工資等級表)的職員名字(員工表)、部門名稱(部門表)
-- 8.1確定幾張表
SELECT * FROM emp e 
INNER JOIN dept d
INNER JOIN salarygrade sg;
-- 8.2確定連接條件
SELECT * FROM emp e 
INNER JOIN dept d ON e.dept_id=d.id
INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 8.3確定顯示字段
SELECT sg.grade,e.ename,d.dname FROM emp e 
INNER JOIN dept d ON e.dept_id=d.id
INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 8.4確定業務條件
SELECT sg.grade,e.ename,d.dname FROM emp e 
INNER JOIN dept d ON e.dept_id=d.id
INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary WHERE sg.grade = 2;

-- 9.漲工資:董事長2000 經理1500 其他800
-- 1.確定幾張表
SELECT *FROM emp e INNER JOIN job j ON e.job_id=j.id;
-- 2.確定顯示字段(case表達式)
SELECT e.ename,j.jname,e.salary AS 漲前工資,
CASE j.jname
WHEN '董事長' THEN e.salary+2000
WHEN '經理' THEN e.salary +1500
ELSE e.salary +800
END AS 漲後工資
FROM emp e INNER JOIN job j ON e.job_id=j.id;


事務安全與TCL

概述

如果一個包含多個步驟的業務操作,被事務管理,那麼這些操作要麼同時成功,要麼同時失敗

操作事務

手動提交事務

  1. 開啓事務:begin
  2. 提交事務:commit
  3. 回滾事務:rollback
  • 示例:轉賬場景
  1. 轉賬成功
-- 1. 開啓事務
	begin;
-- 2. 小明釦錢
	UPDATE account SET money = money -100 WHERE  id = 2;
-- 3. 小紅加錢
	UPDATE account SET money = money + 100 WHERE id = 1;
-- 4. 提交事務
	commit;
  1. 轉賬失敗
-- 1.開啓事務
	begin;
-- 2.小明釦錢
	UPDATE account SET money = money -100 WHERE  id = 2;
-- 3.機器故障

-- 4.回滾事務
	rollback;

自動提交事務【在JDBC將自動提交關閉】

  • 默認情況下,在MySQL中每一條DML(增刪改)語句,就是一個獨立的事務

  • 查看MySQL是否開啓自動提交
    show variables like ‘autocommit’;

  • 臨時關閉自動提交(手動)
    set autocommit=off;

  • 模擬轉賬

-- 1.小明釦錢
	UPDATE account SET money = money -100 WHERE  id = 2;
	
-- 2.改爲手動提交/回滾
	commit / rollback ;

事務的工作原理

在同一個事務中,出現bug(異常),必須執行rollback命令,不然會影響同一個事務中下一次提交

保存(回滾)點

當事務開啓後,一部分sql執行成功,添加一個保存點,後續操作報錯了,回滾到保存點,保證之前的操作可以成功提交

  1. 設置保存點
    savepoint 保存點名;

  2. 回滾到保存點
    rollback to 保存點名;

事務特性ACID(面試題)

  1. 原子性:A atomicity
    如果一個包含多個步驟的業務操作,被事務管理,那麼這些操作要麼同時成功,要麼同時失敗

  2. 一致性:C consistency
    事務在執行前後,保證數據的一致性

  3. 隔離性:I isolation【重點】
    多個事務之間,相互獨立,互不干擾…

  4. 持久性:D durability
    事務一旦成功提交,保存到磁盤文件,不可逆…

事務隔離性

多個事務之間隔離的,相互獨立的。但是如果多個事務操作同一批數據,則會引發一些問題,設置不同的隔離級別就可以解決這些問題

MySQL數據庫隔離級別

級別 名字 隔離級別 髒讀 不可重複讀 幻讀 數據庫默認隔離級別
1 讀未提交 read uncommitted
2 讀已提交 read committed Oracle和SQL Server
3 可重複讀 repeatable read MySQL
4 串行化 serializable

演示隔離級別產生的問題

  1. 查看當前數據庫隔離級別
    show variables like ‘%isolation%’;

  2. 臨時修改隔離級別
    set session transaction isolation level 級別字符串;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章