MySQL常見面試題

一、主鍵、超鍵、候選鍵、外鍵

集合關係:

舉個例子簡單說明下:

學號 身份證號 性別 年齡 身高 體重 宿舍號
             
學號 數學 語文 英語
       

超鍵(super key):在關係模式中,能唯一標識元組的屬性集。上述例子中,通過學號或者身份證號就可以找到一個學生的信息,且是一一對應的。但是通過性別、年齡等就無法找到。只要是包含學號 或者 身份證號 就可是超鍵,如R1(學號 性別) R2(身份證號 身高) R3(學號 身份證號)等。

候選鍵(candidate key):不含有多餘屬性的超鍵稱爲候選鍵。如(學號)、(身份證號)

主鍵(primary key):用戶選作元組標識的一個候選鍵程序主鍵。就是從很多個候選鍵中選擇一個作爲主鍵,如果學號爲主鍵,那麼身份證號就不能是主鍵了

外鍵(foreign key):如果關係模式R中屬性K是其它模式的主鍵,那麼k在模式R中稱爲外鍵。兩個表相關聯的那個鍵 就是外鍵 。學生號就是外鍵。

二、數據庫事物的四個特性以及含義

什麼是事物?

MySQL事物主要用於處理操作量大,複雜度高的數據。比如說A給B轉賬,A的賬戶要少錢,B的賬戶要多錢,不可能A的賬戶錢少了,但是B的賬戶的錢沒有多。A給B轉錢,先從A的賬戶轉出,再轉到B的賬戶,一整件事就是一個事物。

簡言之:

  • 在MySQL中只有使用Innodb數據庫引擎的數據表或者表才支持事物
  • 事物可以用來維護數據庫的完整性,保證成批的SQL語句要麼全部執行,要麼全部不執行。
  • 事物用來管理insert、update、delete語句

事物的四大特性: 

  1. 原子性:整個事物中的所有操作,要麼全部完成,要麼全部不完成,不會停留在某個中間環節。事物在執行過程中發生錯誤,會被回滾(rollback)到事物開始前的狀態,就像這個事物從來沒有被執行過一樣。
  2. 一致性:在事物開始之前和事物結束以後,數據庫的完整性約束沒有被破壞。
  3. 隔離性:數據庫允許多個併發事物同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事物併發執行時由於交叉執行而導致數據的不一致。事物隔離分爲不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(Serializable)
  4. 持久性:事物處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。

併發問題:

  1. 髒讀:事物1正在操作一條數據,此時事物2要獲取該條數據,如果事物1異常,回滾事物,事物2在讀取的時候的數據就是髒數據,這種現象稱爲髒讀。
  2. 不可重複讀:事物1多次讀取某條記錄,在讀取間隔中,事物2更新了該條記錄的數據,事物1再次讀取時,獲取到的數據和之前讀取的不一致,這種現象稱爲不可重複讀。產生的原因主要是數據的更新(update)導致一個事物多次查詢的記錄不一致。
  3. 幻讀:事物1批量處理多條記錄,此時事物2新增或者刪除了一條或者多條記錄,當事物1處理完成,查詢處理結果,會發現有記錄沒有處理(事物2新增的或者刪除的)或者發現記錄少了(事物2刪除的),會有一種幻覺的感覺,稱爲幻讀。主要是數據的新增(insert)或者刪除(delete)導致的。

事物的隔離級別

  1. 未提交讀(Read uncommitted):一個事物可以讀取另外一個未提交事物的數據。就是A給B轉100元,但是系統不小心轉了200給B,此時A和B分別可查看賬戶,A發現少了200,B發現多了200。此時系統發現轉錯賬了,馬上回滾事物,此時就沒有執行該轉賬功能。會產生髒讀、不可重複讀、幻讀。
  2. 提交讀(Read committed):一個事物要等另外一個事物提交後才能讀取。就是A在準備付款時顯示餘額足夠,此時信用卡還款自動扣除了一部分,結果A付款時顯示餘額不足。即若有事物對數據進行更新(update)操作時,讀操作事物要等待這個更新操作事物提交後才能讀取數據,可以解決髒讀問題。會產生不可重複讀、幻讀
  3. 可重複讀(Repeatable read):就是在開啓一個事物後,不允許修改操作。即在A準備付款時(開啓事物),信用卡無法自動扣除欠款。重複讀可以解決不可重複讀的問題。會產生幻讀
  4. 序列化(Serializable):最高的事物隔離級別,在該級別下,事物串行化順序執行,犧牲了系統的併發性。可以避免髒讀、不可重複讀與幻讀。但是這種事物隔離級別效率較低,比較消耗數據庫性能,一般不使用。

注意:大多數事物隔離級別是Read committed,如Sql Server、Oracle。MySQL的默認隔離級別是Repeatable read 

 事務常用控制語句:

  • BEGIN或者START TRANSACTION;顯示的開啓一個事物
  • COMMIT或者COMMIT WORK;提交事物,並已對數據庫進行的所有修改成爲永久性
  • ROLLBACK或者ROLLBACK WORK;在遇見異常時,回滾事務,並撤銷正在進行的所有未提交的修改,回到事務未開啓時候的狀態

MYSQL事物處理主要兩種方法: 

  1. 使用BEGIN、ROLLBACK、COMMIT實現
  2. 直接使用SET來改變MYSQL的自動提交模式:SET AUTOCOMMIT = 0;(禁止自動提交)SET AUTOCOMMIT = 1 開啓自動提交。

三、視圖的作用,視圖可以更改麼?

什麼是視圖?:簡言之,就是將一張表中經常要查詢的列和記錄創建成一張虛擬的表,實際上存放的是select語句,視圖中看到的數據會隨着原始表格的更新而動態更新。相當於是表的一種映射。

視圖與表的關係:

  • 表變化,視圖就會變化
  • 當視圖中的數據和表中的數據一一對應時,可以對視圖中的數據進行修改,那麼表中的數據也會跟着被修改

視圖的作用:

  • 簡化查詢
  • 可以對錶進行重構,比如拆成兩張表
  • 提高安全性。比如,對不同的用戶提供不同的視圖,只提供可以讓他們看到的字段信息,可不用提供整個表

視圖創建語句:

CREATE[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW 視圖名
AS SELECT語句;

四、MySQL的存儲過程

什麼是存儲過程?

SQL語句需要先編譯然後執行,而存儲過程(Stored Procedure)是一組爲了完成特定功能的SQL語句集,經編譯後存儲在數據庫中,用戶通過指定存儲過程的名字並給定參數(如果該存儲過程帶有參數)來調用執行它。存儲過程是可編程的函數,在數據庫中創建並保存,可以由SQL語句和控制結構組成。當想要在不同的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。數據庫的存儲過程可以看做是對編程中面向對象方法的模擬,它允許控制數據的訪問方式。

優點:

  1.  增強SQL語言的功能和靈活性:存儲過程可以用控制語句編寫,有很強的靈活性,可以完成複雜的判斷和較複雜的運算。
  2. 標準組件式編程:存儲過程被創建後,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。
  3. 較快的執行速度:如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那麼存儲過程要比批處理的執行速度快很多。因爲存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。

  4. 減少網絡流量:針對同一個數據庫對象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語句被組織進存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大減少網絡流量並降低了網絡負載。

  5. 作爲一種安全機制來充分利用:通過對執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。 

舉個例子說明下什麼是存儲過程,先建立一張表,並插入一些數據吧

CREATE TABLE class(
cid INT UNSIGNED PRIMARY KEY,
cname VARCHAR(30) NOT NULL DEFAULT '',
age INT UNSIGNED NOT NULL DEFAULT 0
)ENGINE INNODB CHARSET utf8;

//插入數據
INSERT INTO class VALUES (1,'張三',20),(2,'李四',22),(3,'王五',27),(4,'趙六',20),(5,'孫七',21),(6,'錢八',24);

 1、建立一個存儲過程如下:功能是計算年齡的平均值。這個是無參數的存儲過程

DELIMITER //
CREATE PROCEDURE avgofage()
BEGIN
SELECT AVG(age) AS ageaverage FROM class;
END;//

調用:

CALL avgofage();

2、也可以創建一個帶輸出OUT參數的存儲過程:功能是求最大的年齡、最小的年齡和平均年齡

DELIMITER //
CREATE PROCEDURE avgofage1(
OUT maxage DECIMAL(4,2),
OUT minage DECIMAL(4,2),
OUT avgage DECIMAL(4,2))
BEGIN
SELECT MAX(age) INTO maxage FROM class;
SELECT MIN(age) INTO minage FROM class;
SELECT AVG(age) INTO avgage FROM class;
END;//

調用avgofage1:

CALL avgofage1(@maxage,@minage,@avgage);

查詢結果:可以一次只查詢一個輸出、也可以一次查詢多個輸出

SELECT @maxage;
SELECT @minage;
SELECT @avgage;
SELECT @maxage,@minage,@avgage;

結果如下:

3、帶輸入IN和輸出OUT的存儲過程:查詢年齡大於23的人數

DELIMITER //
CREATE PROCEDURE avgofage2(
IN target INT,
OUT total INT
)
BEGIN
SELECT COUNT(*) INTO total FROM class WHERE age > target;
END;//

調用:

CALL avgofage2(23,@total);
SELECT @total;

結果如下:

還有一種稍微複雜的存儲過程:對查詢出的年齡的人數大於target的結果+20;(可能沒啥邏輯性)

DELIMITER//
CREATE PROCEDURE avgofage3(
IN target INT,
IN flag BOOLEAN,
OUT total INT)
BEGIN
DECLARE temp INT;//定義局部變量
SELECT COUNT(*) INTO temp FROM class WHERE age > target;
IF flag THEN
SELECT temp + 20 INTO temp;
END IF;
SELECT temp INTO total; 
END;//

CALL avgofage3(22,TRUE,@total);
SELECT @total;

查看存儲過程:

SHOW PROCEDURE STATUS;

 

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