mysql相關理解與提高

 

 

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也可以用事務解鎖; 行鎖:通過事務解鎖;

·行鎖,寫操作不同的數據,一次鎖一行數據,因此,如果操作不同數據,不影響

行鎖注意事項

·如果沒有索引,行鎖會轉移爲表鎖

·行鎖的一種特殊情況:間隙鎖:值在範圍內,但不存在

 

 

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