1.mysql常用聚合函數
分類:sum求和,avg平均數,max最大值,min最小值,count計算個數
簡單使用:
sum求和: select sum(age) from test;
avg平均數:select ROUND(avg(age),2) from test;
min最小值:select min(age) from test;
max最大值:select max(age) from test;
count計算個數:select count(age) from test;
參數支持哪些類型:可以和distinct去重搭配
sum求和,avg平均數:數值類型
max最大值,min最小值:數值類型,日期類型,字符型
count計算個數:不爲null的類型
count(1)和count(*)效率問題:
Innodb:count(1)和count(*)效率差不多,比count(字段)高
Myisam: count(*)效率最高
2.事務的ACID屬性
原子性:事務不可再分割,事務的操作要麼都執行,要麼都不執行。
一致性:事務執行會使數據從一個一致狀態切換到另一個一致狀態。
隔離性:一個事務的執行不受其他事務的干擾。
持久性:事務一旦提交,無法改變。
3.事務的創建
·隱式事務:事務沒有明顯的開啓和結束標識。比如:insert update delete
·顯示事務:事務有明顯的開啓和結束標識。前提:必須先設置自動提交事務功能爲禁止
Set autocommit = 0
-----------------------------------------------------------------------------
步驟1: Set autocommit = 0; start transaction;//可選
步驟2:編寫事務的sql語句(select,insert,update,delete)
語句1,語句2......
步驟3:結束事務
set autocommit = 0;
start transaction;
Update account set balance = 500 where name=’郭襄’;
Update account set balance = 1500 where name=’張君寶’;
Commit;
-------------------------------------------------------------------------------
4.數據庫的隔離級別
對於 同時運行多個事務,當這些事務訪問數據庫相同的數據時,如果沒有采取必要的隔離機制,,將會導致各種併發問題。
髒讀:兩個事務a,b,a讀取了b更新但未提交的字段,若b回滾,a讀取的內容是臨時無效的。
不可重複讀:兩個事務a,b,a讀取了表中一個字段,然後b更新了該字段之後,a再去讀同一個字段,值就不同了。
幻讀:兩個事務a,b,a讀取了表中一個字段,然後b在該表中插入了一行數據,之後a再次去讀一個表時,就會多出幾行。
數據庫事務的隔離性:數據庫系統必須具有隔離併發運行各個事務的能力,使他們無相互影響,解決高併發問題。
----------------------------------------------------------------------------------------------------------------------------------------------
數據庫的隔離級別:
讀未提交數據(read uncommited):允許事務讀取未被其他事務提交的變更,髒讀,不可重複讀,幻讀問題都會發生。
讀已提交數據(read commited):直允許事務讀取已經被其他事務提交的變更,可避免髒讀,但不可重複讀,幻讀問題會發生。
可重複讀(repeatable read):確保事務可以多次從一個字段中讀取相同的值,在事務持續時間,禁止其他事務對這個字段更新,可避免髒讀,不可重複讀,但幻讀仍然存在
串行化(serializable):確保事務可以從一個表中讀取相同的行,在事務持續時間,禁止其他事務進行更新,插入,刪除操作,可避免所有併發問題,但效率低下。
---------------------------------------------------------------------------------------------------------------------
Oracle支持的隔離級別:讀已提交數據(read commited),串行化(serializable);默認的隔離級別:串行化(serializable)
mysql支持四種隔離級別,但默認的隔離級別爲:可重複讀(repeatable read)
---------------------------------------------------------------------------------------------------------------------------
Delete和truncate在事務使用時的區別
set autocommit = 0;
start transaction;
Delete from account;
Rollback; //數據已經刪除,支持回滾;truncate不支持回滾
----------------------------------------------------------------------------------
5.視圖:虛擬表,使通過表動態生成的數據。
創建視圖語法:create view 視圖名 as 查詢的語句
用視圖語法:select * from 視圖名 where
CREATE VIEW userandrole AS
SELECT a.username uname, r.`name` rname, p.`name` as pname FROM USER a
LEFT JOIN user_role ur ON a.id = ur.uid
LEFT JOIN role r ON ur.rid = r.id
LEFT JOIN role_permission rp ON r.id = rp.rid
LEFT JOIN permission p ON p.id = rp.pid;
注意:必須指定查詢的字段,當字段有相同時起別名。
SELECT * from userandrole WHERE uname ='zhuweilin'
------------------------------------------------------------------------------------------------
視圖的優點:重用mysql,簡化複雜sql優化,保護數據提高安全性,但是隻能用於不變的數據集
修改視圖:
·create or replace view 視圖名 as 查詢語句
·alter 視圖名 as 查詢語句
CREATE OR REPLACE VIEW userandrole AS
SELECT a.username uname, r.`name` rname, p.`name` as pname FROM USER a
LEFT JOIN user_role ur ON a.id = ur.uid
LEFT JOIN role r ON ur.rid = r.id
LEFT JOIN role_permission rp ON r.id = rp.rid
LEFT JOIN permission p ON p.id = rp.pid;
--------------------------------------------------------------------------------------------------
刪除視圖:
drop view 視圖名,視圖名...........
查看視圖:
DESC 視圖名
show create view 視圖名
視圖更新:更新視圖的數據,也適用增刪改,但是會影響其他表,視圖內數據不允許增刪改,包含以下關鍵字的sql語句不能進行操作:分組函數,distinct ,group by ,having,Union 或者 Union all
視圖只佔用少部分物理空間只是保存了sql邏輯,少於表佔的物理空間
--------------------------------------------------------------------------------------------------------
6.存儲過程和函數,類java中的方法
指一組預先編譯好的sql語句的集合,理解成批處理的語句
·提高代碼的重用性
·簡化操作
·減少了編譯次數並且減少了數據庫服務器的連接次數,提高效率
創建語法:
CREATE PROCEDURE 存儲過程名(參數列表)
BEGIN
存儲過程體
END
注意:
1.參數列表包括三部分:參數模式,參數名,參數類型。 比如:in stuname varchar(20)
參數模式:in讓參數作爲輸入,也就是該參數需要調用方法傳值
out 讓參數作爲輸出,也就是該參數可以作爲返回值
Inout 既讓參數作爲輸入也讓參數作爲輸出,既可以傳值,又可以返回值
2.如果存儲過程只有一句話,begin end 可以省略,存儲過程體中的每條sql語句的結尾必須加分號。存儲過程的結尾可以用重新設置。
語法:DELIMTER 結束標記 比如:DELIMTER $
調用語法:
Call 存儲過程名(實參列表)
#創建無參數的存儲過程
DELIMITER $
CREATE PROCEDURE myp1()
BEGIN
INSERT INTO a_table VALUES(null,'hzz','hzz'),(null,'cmm','cmm');
END $
CALL myp1();
#創建in模式參數的存儲過程,支持傳入多個參數
CREATE PROCEDURE myp12(IN teacher_name VARCHAR(20))
BEGIN
SELECT * FROM test_teacher tt WHERE tt.teacher_name = teacher_name ;
END
CALL myp12('柳巖')
支持傳入多個參數
CREATE PROCEDURE myp3(IN uname VARCHAR(20) , IN pwd VARCHAR(20))
BEGIN
SELECT COUNT(*) INTO result //賦值
FROM uesr u WHERE u.uname = uname and u.pwd = pwd ;
END
CALL myp3('admin',admin)
創建帶out模式的存儲過程
CREATE PROCEDURE myp4(IN student_name VARCHAR(20),OUT student_sex VARCHAR(20))
BEGIN
SELECT ts.student_sex INTO student_sex
FROM test_student ts WHERE ts.student_name = student_name ;
END
#定義輸出變量
set @sex;
CALL myp4('張三',@sex)
SELECT @sex
------------------------------------------------------------------------------
遊標的相關知識點:
# Cursor 遊標 遊標的標誌
# 1條sql,取出的N條資源,取出的接口/句柄,就是遊標
# 沿着遊標,可以一次取出一行
# declare 聲明;declare 遊標名 cursor for select_statement;
# open 打開; open 遊標名
# fetch 取值; fetch 遊標名 into var1,var2[,.......]
# close 關閉;close 遊標名;
-------------------------------------------------------------------------------------------------
遊標爲取一次遊一次,若沒有了則報錯
CREATE PROCEDURE test()
BEGIN
DECLARE row_t_id INT; #聲明遊標之前聲明變量
DECLARE row_t_teacher VARCHAR(20);
DECLARE getteacher CURSOR FOR #聲明遊標
SELECT tt.id,tt.teacher_name FROM test_teacher tt; #遊標所需要的sql
OPEN getteacher #打開遊標
FETCH getteacher INTO row_t_id,row_t_teacher; #取值
SELECT row_t_id,row_t_teacher; #查值
CLOSE getteacher; #關閉遊標
END
CALL test();
如何循環遊標所有行
CREATE PROCEDURE test2()
BEGIN
DECLARE cnt INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE row_t_id INT; #聲明遊標之前聲明變量
DECLARE row_t_teacher VARCHAR(20);
DECLARE getteacher CURSOR FOR #聲明遊標
SELECT tt.id,tt.teacher_name FROM test_teacher tt;
SELECT COUNT(*) FROM test_teacher; #遊標所需要的sql
OPEN getteacher ; #打開遊標
REPEAT
SET i :=i+1;
FETCH getteacher INTO row_t_id,row_t_teacher; #取值
SELECT row_t_id,row_t_teacher ; #查值
UNTIL i >= cnt END REPEAT;
CLOSE getteacher; #關閉遊標
END
CALL test2();
#在mysql curor中可以DECLARE CONTINUE HANDLER來操作一個越界標識
#DECLARE CONTINUE HANDLER FOR NOT FOUND statement;
CREATE PROCEDURE test3()
BEGIN
DECLARE row_t_id INT; #聲明遊標之前聲明變量
DECLARE row_t_teacher VARCHAR(20);
DECLARE you INT DEFAULT 1;
DECLARE getteacher CURSOR FOR #聲明遊標
SELECT tt.id,tt.teacher_name FROM test_teacher tt; #遊標所需要的sql
DECLARE CONTINUE HANDLER FOR NOT FOUND SET you :=0;
OPEN getteacher ; #打開遊標
REPEAT
FETCH getteacher INTO row_t_id,row_t_teacher; #取值
SELECT row_t_id,row_t_teacher ; #查值
UNTIL you=0 END REPEAT;
CLOSE getteacher; #關閉遊標
END
CALL test3();
爲何多出來一行呢?如何修復?
解決後的方案
#DECLARE exit HANDLER FOR NOT FOUND statement
#CONTINUE 和exit區別:exit觸發後後面的語句不再執行
#除了CONTINUE 和exit還有一個undo
#CONTINUE 是觸發後,後面語句繼續執行
#exit是觸發後,後面語句不執行
#undo是觸發後,前面語句撤銷(目前mysql不支持)
CREATE PROCEDURE test4()
BEGIN
DECLARE row_t_id INT; #聲明遊標之前聲明變量
DECLARE row_t_teacher VARCHAR(20);
DECLARE you INT DEFAULT 1;
DECLARE getteacher CURSOR FOR #聲明遊標
SELECT tt.id,tt.teacher_name FROM test_teacher tt; #遊標所需要的sql
DECLARE EXIT HANDLER FOR NOT FOUND SET you :=0;
OPEN getteacher ; #打開遊標
REPEAT #遍歷
FETCH getteacher INTO row_t_id,row_t_teacher; #取值
SELECT row_t_id,row_t_teacher ; #查值
INSERT INTO test_class VALUES(null,row_t_teacher); #插入值
UNTIL you=0 END REPEAT;
CLOSE getteacher; #關閉遊標
END
CALL test4();
------------------------------------------------------------------------------------
# 不用exit也能解決問題
------------------------------------------------------------------------------------
# 不用exit也能解決問題
CREATE PROCEDURE test5()
BEGIN
DECLARE row_t_id INT; #聲明遊標之前聲明變量
DECLARE row_t_teacher VARCHAR(20);
DECLARE you INT DEFAULT 1;
DECLARE getteacher CURSOR FOR #聲明遊標
SELECT tt.id,tt.teacher_name FROM test_teacher tt; #遊標所需要的sql
DECLARE CONTINUE HANDLER FOR NOT FOUND SET you :=0;
OPEN getteacher ; #打開遊標
FETCH getteacher INTO row_t_id,row_t_teacher;
REPEAT
SELECT row_t_id,row_t_teacher ;
FETCH getteacher INTO row_t_id,row_t_teacher; #查值
UNTIL you=0 END REPEAT;
CLOSE getteacher; #關閉遊標
END
CALL test5();
查詢後的數據插入另一張表
#在mysql curor中可以DECLARE CONTINUE HANDLER來操作一個越界標識
#DECLARE CONTINUE HANDLER FOR NOT FOUND statement
CREATE PROCEDURE test4()
BEGIN
DECLARE row_t_id INT; #聲明遊標之前聲明變量
DECLARE row_t_teacher VARCHAR(20);
DECLARE you INT DEFAULT 1;
DECLARE getteacher CURSOR FOR #聲明遊標
SELECT tt.id,tt.teacher_name FROM test_teacher tt; #遊標所需要的sql
DECLARE EXIT HANDLER FOR NOT FOUND SET you :=0;
OPEN getteacher ; #打開遊標
REPEAT
FETCH getteacher INTO row_t_id,row_t_teacher; #取值
SELECT row_t_id,row_t_teacher ; #查值
INSERT INTO test_class VALUES(null,row_t_teacher); #插入值
UNTIL you=0 END REPEAT;
CLOSE getteacher; #關閉遊標
END
CALL test4();
函數的相關理解
例:創建一個函數,函數一定要有返回值
CREATE FUNCTION select_student(student_neme VARCHAR(20)) #定義函數select_student()
RETURNS INT #定義返回值
BEGIN
DECLARE res INT; #定義變量
IF student_neme IS NULL THEN
SET res = -1;
ELSE
SET res = 1;
END IF;
RETURN res;
END
#調用函數
Select select_student(null) as res;
----------------------------------------------------------------------------------------------------------------
7.mysql鎖機制:其目的使解決因資源共享而造成的併發問題
分類
1.操作類型
·讀鎖(共享鎖):對同一數據,多個操作可以同時進行,互不干擾
·寫鎖(互斥鎖):如果當前寫操作沒有完畢,則無法進行其他的讀操作,寫操作
2.操作範圍:
·表鎖:一次性對一個表整體加鎖。如myISAM存儲引擎使用表鎖,開銷小,加鎖快,無死鎖,但鎖的範圍大,容易發生衝突,併發度低。
·行鎖:一次性對一個條數據加鎖。如innoDB存儲引擎使用行鎖,開銷大,加鎖滿,經常死鎖,但鎖的範圍小,不易發生衝突,併發度高(很小概率發生高併發問題—>髒讀,幻讀,不可重複讀,以及丟失數據問題)。
·頁鎖
加讀鎖
總結1:加讀鎖,如果一個會話 可以對錶能進行讀操作,不能進行寫操作;且該會話對其他表不能進行讀寫操作。
會話0:Lock table tablelock read;
Select * from tablelock ; //讀(查)可以
Delete from tablelock where id =1; //寫(增刪改)不可以
會話1: Select * from tablelock ; //讀(查)可以
Delete from tablelock where id =1; //寫(增刪改)等待,不可以操作,需等待釋放表鎖。
會話3:
Select * from emp; //讀(查)可以
Delete from emp where id =1; //寫(增刪改)可以
總結2:會話0給A表加鎖,其他會話的操作:可以對A表之外的表進行任何操作
對A表的操作只能讀操作,寫操作需要等待A表釋放鎖。
釋放鎖:unlock tables;
加寫鎖
會話0:lock table tablelock write;
結論:當前會話,可對該表進行任何操作(增刪改查);但不能操作其他表。
其他會話:
結論:會話0中加鎖的表,可以進行增刪改查,但需等待會話0釋放鎖。
分析表鎖定:
查看被鎖表:show open tables; 1代表加了鎖。
行鎖(INNODB)
爲了研究行鎖,需關閉自動commit。Set autocommit = 0;
對行鎖的一個小結:
·如果會話X對某條數據A進行DML操作(研究時:關閉commit的情況下),則在其他會話必須等待會話X結束事務(commit/roleback)後才能對數據a進行操作
·表鎖是通過unlock tables也可以用事務解鎖; 行鎖:通過事務解鎖;
·行鎖,寫操作不同的數據,一次鎖一行數據,因此,如果操作不同數據,不影響
行鎖注意事項
·如果沒有索引,行鎖會轉移爲表鎖
·行鎖的一種特殊情況:間隙鎖:值在範圍內,但不存在