摘要:數(shù)據(jù)庫常見面試題開發(fā)者篇什么是存儲過程有哪些優(yōu)缺點什么是存儲過程有哪些優(yōu)缺點存儲過程就像我們編程語言中的函數(shù)一樣,封裝了我們的代碼。
數(shù)據(jù)庫常見面試題(開發(fā)者篇) 什么是存儲過程?有哪些優(yōu)缺點?
什么是存儲過程?有哪些優(yōu)缺點?
存儲過程就像我們編程語言中的函數(shù)一樣,封裝了我們的代碼(PLSQL、T-SQL)。
存儲過程的優(yōu)點:
能夠?qū)⒋a封裝起來
保存在數(shù)據(jù)庫之中
讓編程語言進(jìn)行調(diào)用
存儲過程是一個預(yù)編譯的代碼塊,執(zhí)行效率比較高
一個存儲過程替代大量T_SQL語句 ,可以降低網(wǎng)絡(luò)通信量,提高通信速率
存儲過程的缺點:
每個數(shù)據(jù)庫的存儲過程語法幾乎都不一樣,十分難以維護(hù)(不通用)
業(yè)務(wù)邏輯放在數(shù)據(jù)庫上,難以迭代
三個范式是什么三個范式是什么
第一范式(1NF):數(shù)據(jù)庫表中的字段都是單一屬性的,不可再分。這個單一屬性由基本類型構(gòu)成,包括整型、實數(shù)、字符型、邏輯型、日期型等。
第二范式(2NF):數(shù)據(jù)庫表中不存在非關(guān)鍵字段對任一候選關(guān)鍵字段的部分函數(shù)依賴(部分函數(shù)依賴指的是存在組合關(guān)鍵字中的某些字段決定非關(guān)鍵字段的情況),也即所有非關(guān)鍵字段都完全依賴于任意一組候選關(guān)鍵字。
第三范式(3NF):在第二范式的基礎(chǔ)上,數(shù)據(jù)表中如果不存在非關(guān)鍵字段對任一候選關(guān)鍵字段的傳遞函數(shù)依賴則符合第三范式。所謂傳遞函數(shù)依賴,指的是如果存在"A → B → C"的決定關(guān)系,則C傳遞函數(shù)依賴于A。因此,滿足第三范式的數(shù)據(jù)庫表應(yīng)該不存在如下依賴關(guān)系: 關(guān)鍵字段 → 非關(guān)鍵字段x → 非關(guān)鍵字段y
上面的文字我們肯定是看不懂的,也不愿意看下去的。接下來我就總結(jié)一下:
首先要明確的是:滿足著第三范式,那么就一定滿足第二范式、滿足著第二范式就一定滿足第一范式
第一范式:字段是最小的的單元不可再分
學(xué)生信息組成學(xué)生信息表,有年齡、性別、學(xué)號等信息組成。這些字段都不可再分,所以它是滿足第一范式的
第二范式:滿足第一范式,表中的字段必須完全依賴于全部主鍵而非部分主鍵。
其他字段組成的這行記錄和主鍵表示的是同一個東西,而主鍵是唯一的,它們只需要依賴于主鍵,也就成了唯一的
學(xué)號為1024的同學(xué),姓名為Java3y,年齡是22歲。姓名和年齡字段都依賴著學(xué)號主鍵。
第三范式:滿足第二范式,非主鍵外的所有字段必須互不依賴
就是數(shù)據(jù)只在一個地方存儲,不重復(fù)出現(xiàn)在多張表中,可以認(rèn)為就是消除傳遞依賴
比如,我們大學(xué)分了很多系(中文系、英語系、計算機(jī)系……),這個系別管理表信息有以下字段組成:系編號,系主任,系簡介,系架構(gòu)。那我們能不能在學(xué)生信息表添加系編號,系主任,系簡介,系架構(gòu)字段呢?不行的,因為這樣就冗余了,非主鍵外的字段形成了依賴關(guān)系(依賴到學(xué)生信息表了)!正確的做法是:學(xué)生表就只能增加一個系編號字段。
參考鏈接:
https://www.zhihu.com/question/24696366
http://www.cnblogs.com/CareySon/archive/2010/02/16/1668803.html
什么是視圖?以及視圖的使用場景有哪些?什么是視圖?以及視圖的使用場景有哪些?
視圖是一種基于數(shù)據(jù)表的一種虛表
(1)視圖是一種虛表
(2)視圖建立在已有表的基礎(chǔ)上, 視圖賴以建立的這些表稱為基表
(3)向視圖提供數(shù)據(jù)內(nèi)容的語句為 SELECT 語句,可以將視圖理解為存儲起來的 SELECT 語句
(4)視圖向用戶提供基表數(shù)據(jù)的另一種表現(xiàn)形式
(5)視圖沒有存儲真正的數(shù)據(jù),真正的數(shù)據(jù)還是存儲在基表中
(6)程序員雖然操作的是視圖,但最終視圖還會轉(zhuǎn)成操作基表
(7)一個基表可以有0個或多個視圖
有的時候,我們可能只關(guān)系一張數(shù)據(jù)表中的某些字段,而另外的一些人只關(guān)系同一張數(shù)據(jù)表的某些字段...
那么把全部的字段都都顯示給他們看,這是不合理的。
我們應(yīng)該做到:他們想看到什么樣的數(shù)據(jù),我們就給他們什么樣的數(shù)據(jù)...一方面就能夠讓他們只關(guān)注自己的數(shù)據(jù),另一方面,我們也保證數(shù)據(jù)表一些保密的數(shù)據(jù)不會泄露出來...
我們在查詢數(shù)據(jù)的時候,常常需要編寫非常長的SQL語句,幾乎每次都要寫很長很長....上面已經(jīng)說了,視圖就是基于查詢的一種虛表,也就是說,視圖可以將查詢出來的數(shù)據(jù)進(jìn)行封裝。。。那么我們在使用的時候就會變得非常方便...
值得注意的是:使用視圖可以讓我們專注與邏輯,但不提高查詢效率
drop、delete與truncate分別在什么場景之下使用?drop、delete與truncate分別在什么場景之下使用?
我們來對比一下他們的區(qū)別:
drop table
1)屬于DDL
2)不可回滾
3)不可帶where
4)表內(nèi)容和結(jié)構(gòu)刪除
5)刪除速度快
truncate table
1)屬于DDL
2)不可回滾
3)不可帶where
4)表內(nèi)容刪除
5)刪除速度快
delete from
1)屬于DML
2)可回滾
3)可帶where
4)表結(jié)構(gòu)在,表內(nèi)容要看where執(zhí)行的情況
5)刪除速度慢,需要逐行刪除
不再需要一張表的時候,用drop
想刪除部分?jǐn)?shù)據(jù)行時候,用delete,并且?guī)蟱here子句
保留表而刪除所有數(shù)據(jù)的時候用truncate
索引是什么?有什么作用以及優(yōu)缺點?索引是什么?有什么作用以及優(yōu)缺點?
什么是索引【Index】
(1)是一種快速查詢表中內(nèi)容的機(jī)制,類似于新華字典的目錄
(2)運(yùn)用在表中某個些字段上,但存儲時,獨立于表之外
索引表把數(shù)據(jù)變成是有序的....
快速定位到硬盤中的數(shù)據(jù)文件...
rowid特點rowid的特點
(1)位于每個表中,但表面上看不見,例如:desc emp是看不見的
(2)只有在select中,顯示寫出rowid,方可看見
(3)它與每個表綁定在一起,表亡,該表的rowid亡,二張表rownum可以相同,但rowid必須是唯一的
(4)rowid是18位大小寫加數(shù)字混雜體,唯一表代該條記錄在DBF文件中的位置
(5)rowid可以參與=/like比較時,用""單引號將rowid的值包起來,且區(qū)分大小寫
(6)rowid是聯(lián)系表與DBF文件的橋梁
索引特點索引的特點
(1)索引一旦建立, Oracle管理系統(tǒng)會對其進(jìn)行自動維護(hù), 而且由Oracle管理系統(tǒng)決定何時使用索引
(2)用戶不用在查詢語句中指定使用哪個索引
(3)在定義primary key或unique約束后系統(tǒng)自動在相應(yīng)的列上創(chuàng)建索引
(4)用戶也能按自己的需求,對指定單個字段或多個字段,添加索引
需要注意的是:Oracle是自動幫我們管理索引的,并且如果我們指定了primary key或者unique約束,系統(tǒng)會自動在對應(yīng)的列上創(chuàng)建索引..
什么時候【要】創(chuàng)建索引
(1)表經(jīng)常進(jìn)行 SELECT 操作
(2)表很大(記錄超多),記錄內(nèi)容分布范圍很廣
(3)列名經(jīng)常在 WHERE 子句或連接條件中出現(xiàn)
什么時候【不要】創(chuàng)建索引
(1)表經(jīng)常進(jìn)行 INSERT/UPDATE/DELETE 操作
(2)表很小(記錄超少)
(3)列名不經(jīng)常作為連接條件或出現(xiàn)在 WHERE 子句中
索引優(yōu)缺點:
索引加快數(shù)據(jù)庫的檢索速度
索引降低了插入、刪除、修改等維護(hù)任務(wù)的速度(雖然索引可以提高查詢速度,但是它們也會導(dǎo)致數(shù)據(jù)庫系統(tǒng)更新數(shù)據(jù)的性能下降,因為大部分?jǐn)?shù)據(jù)更新需要同時更新索引)
唯一索引可以確保每一行數(shù)據(jù)的唯一性,通過使用索引,可以在查詢的過程中使用優(yōu)化隱藏器,提高系統(tǒng)的性能
索引需要占物理和數(shù)據(jù)空間
索引分類:
唯一索引:唯一索引不允許兩行具有相同的索引值
主鍵索引:為表定義一個主鍵將自動創(chuàng)建主鍵索引,主鍵索引是唯一索引的特殊類型。主鍵索引要求主鍵中的每個值是唯一的,并且不能為空
聚集索引(Clustered):表中各行的物理順序與鍵值的邏輯(索引)順序相同,每個表只能有一個
非聚集索引(Non-clustered):非聚集索引指定表的邏輯順序。數(shù)據(jù)存儲在一個位置,索引存儲在另一個位置,索引中包含指向數(shù)據(jù)存儲位置的指針??梢杂卸鄠€,小于249個
深入理解索引可參考:
https://kb.cnblogs.com/page/45712/
https://www.cnblogs.com/drizzlewithwind/p/5707058.html
什么是事務(wù)?什么是事務(wù)?
事務(wù)簡單來說:一個Session中所進(jìn)行所有的操作,要么同時成功,要么同時失敗
ACID — 數(shù)據(jù)庫事務(wù)正確執(zhí)行的四個基本要素
包含:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。
一個支持事務(wù)(Transaction)中的數(shù)據(jù)庫系統(tǒng),必需要具有這四種特性,否則在事務(wù)過程(Transaction processing)當(dāng)中無法保證數(shù)據(jù)的正確性,交易過程極可能達(dá)不到交易。
舉個例子:A向B轉(zhuǎn)賬,轉(zhuǎn)賬這個流程中如果出現(xiàn)問題,事務(wù)可以讓數(shù)據(jù)恢復(fù)成原來一樣【A賬戶的錢沒變,B賬戶的錢也沒變】。
事例說明:
/* * 我們來模擬A向B賬號轉(zhuǎn)賬的場景 * A和B賬戶都有1000塊,現(xiàn)在我讓A賬戶向B賬號轉(zhuǎn)500塊錢 * * */ //JDBC默認(rèn)的情況下是關(guān)閉事務(wù)的,下面我們看看關(guān)閉事務(wù)去操作轉(zhuǎn)賬操作有什么問題 //A賬戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //B賬戶多了500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
從上面看,我們的確可以發(fā)現(xiàn)A向B轉(zhuǎn)賬,成功了??墒?strong>如果A向B轉(zhuǎn)賬的過程中出現(xiàn)了問題呢?下面模擬一下
//A賬戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //這里模擬出現(xiàn)問題 int a = 3 / 0; String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
顯然,上面代碼是會拋出異常的,我們再來查詢一下數(shù)據(jù)。A賬戶少了500塊錢,B賬戶的錢沒有增加。這明顯是不合理的。
我們可以通過事務(wù)來解決上面出現(xiàn)的問題
//開啟事務(wù),對數(shù)據(jù)的操作就不會立即生效。 connection.setAutoCommit(false); //A賬戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //在轉(zhuǎn)賬過程中出現(xiàn)問題 int a = 3 / 0; //B賬戶多500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate(); //如果程序能執(zhí)行到這里,沒有拋出異常,我們就提交數(shù)據(jù) connection.commit(); //關(guān)閉事務(wù)【自動提交】 connection.setAutoCommit(true); } catch (SQLException e) { try { //如果出現(xiàn)了異常,就會進(jìn)到這里來,我們就把事務(wù)回滾【將數(shù)據(jù)變成原來那樣】 connection.rollback(); //關(guān)閉事務(wù)【自動提交】 connection.setAutoCommit(true); } catch (SQLException e1) { e1.printStackTrace(); }
上面的程序也一樣拋出了異常,A賬戶錢沒有減少,B賬戶的錢也沒有增加。
注意:當(dāng)Connection遇到一個未處理的SQLException時,系統(tǒng)會非正常退出,事務(wù)也會自動回滾,但如果程序捕獲到了異常,是需要在catch中顯式回滾事務(wù)的。
事務(wù)隔離級別數(shù)據(jù)庫定義了4個隔離級別:
Serializable【可避免臟讀,不可重復(fù)讀,虛讀】
Repeatable read【可避免臟讀,不可重復(fù)讀】
Read committed【可避免臟讀】
Read uncommitted【級別最低,什么都避免不了】
分別對應(yīng)Connection類中的4個常量
TRANSACTION_READ_UNCOMMITTED
TRANSACTION_READ_COMMITTED
TRANSACTION_REPEATABLE_READ
TRANSACTION_SERIALIZABLE
臟讀:一個事務(wù)讀取到另外一個事務(wù)未提交的數(shù)據(jù)
例子:A向B轉(zhuǎn)賬,A執(zhí)行了轉(zhuǎn)賬語句,但A還沒有提交事務(wù),B讀取數(shù)據(jù),發(fā)現(xiàn)自己賬戶錢變多了!B跟A說,我已經(jīng)收到錢了。A回滾事務(wù)【rollback】,等B再查看賬戶的錢時,發(fā)現(xiàn)錢并沒有多。
不可重復(fù)讀:一個事務(wù)讀取到另外一個事務(wù)已經(jīng)提交的數(shù)據(jù),也就是說一個事務(wù)可以看到其他事務(wù)所做的修改
注:A查詢數(shù)據(jù)庫得到數(shù)據(jù),B去修改數(shù)據(jù)庫的數(shù)據(jù),導(dǎo)致A多次查詢數(shù)據(jù)庫的結(jié)果都不一樣【危害:A每次查詢的結(jié)果都是受B的影響的,那么A查詢出來的信息就沒有意思了】
虛讀(幻讀):是指在一個事務(wù)內(nèi)讀取到了別的事務(wù)插入的數(shù)據(jù),導(dǎo)致前后讀取不一致。
注:和不可重復(fù)讀類似,但虛讀(幻讀)會讀到其他事務(wù)的插入的數(shù)據(jù),導(dǎo)致前后讀取不一致
簡單總結(jié):臟讀是不可容忍的,不可重復(fù)讀和虛讀在一定的情況下是可以的【做統(tǒng)計的肯定就不行】。
數(shù)據(jù)庫的樂觀鎖和悲觀鎖是什么?數(shù)據(jù)庫的樂觀鎖和悲觀鎖是什么?
確保在多個事務(wù)同時存取數(shù)據(jù)庫中同一數(shù)據(jù)時不破壞事務(wù)的隔離性和統(tǒng)一性以及數(shù)據(jù)庫的統(tǒng)一性,樂觀鎖和悲觀鎖是并發(fā)控制主要采用的技術(shù)手段。
悲觀鎖:假定會發(fā)生并發(fā)沖突,屏蔽一切可能違反數(shù)據(jù)完整性的操作
在查詢完數(shù)據(jù)的時候就把事務(wù)鎖起來,直到提交事務(wù)
實現(xiàn)方式:使用數(shù)據(jù)庫中的鎖機(jī)制
樂觀鎖:假設(shè)不會發(fā)生并發(fā)沖突,只在提交操作時檢查是否違反數(shù)據(jù)完整性。
在修改數(shù)據(jù)的時候把事務(wù)鎖起來,通過version的方式來進(jìn)行鎖定
實現(xiàn)方式:使用version版本或者時間戳
悲觀鎖:
樂觀鎖:
參考資料:
http://www.open-open.com/lib/view/open1452046967245.html
超鍵、候選鍵、主鍵、外鍵分別是什么?超鍵、候選鍵、主鍵、外鍵分別是什么?
超鍵:在關(guān)系中能唯一標(biāo)識元組的屬性集稱為關(guān)系模式的超鍵。一個屬性可以為作為一個超鍵,多個屬性組合在一起也可以作為一個超鍵。超鍵包含候選鍵和主鍵。
候選鍵(候選碼):是最小超鍵,即沒有冗余元素的超鍵。
主鍵(主碼):數(shù)據(jù)庫表中對儲存數(shù)據(jù)對象予以唯一和完整標(biāo)識的數(shù)據(jù)列或?qū)傩缘慕M合。一個數(shù)據(jù)列只能有一個主鍵,且主鍵的取值不能缺失,即不能為空值(Null)。
外鍵:在一個表中存在的另一個表的主鍵稱此表的外鍵。
候選碼和主碼:
例子:郵寄地址(城市名,街道名,郵政編碼,單位名,收件人)
它有兩個候選鍵:{城市名,街道名} 和 {街道名,郵政編碼}
如果我選取{城市名,街道名}作為唯一標(biāo)識實體的屬性,那么{城市名,街道名} 就是主碼(主鍵)
SQL 約束有哪幾種?SQL 約束有哪幾種?
NOT NULL: 用于控制字段的內(nèi)容一定不能為空(NULL)。
UNIQUE: 控件字段內(nèi)容不能重復(fù),一個表允許有多個 Unique 約束。
PRIMARY KEY: 也是用于控件字段內(nèi)容不能重復(fù),但它在一個表只允許出現(xiàn)一個。
FOREIGN KEY: 用于預(yù)防破壞表之間連接的動作,也能防止非法數(shù)據(jù)插入外鍵列,因為它必須是它指向的那個表中的值之一。
CHECK: 用于控制字段的值范圍。
數(shù)據(jù)庫運(yùn)行于哪種狀態(tài)下可以防止數(shù)據(jù)的丟失?數(shù)據(jù)庫運(yùn)行于哪種狀態(tài)下可以防止數(shù)據(jù)的丟失?
在archivelog mode(歸檔模式)只要其歸檔日志文件不丟失,就可以有效地防止數(shù)據(jù)丟失。
Mysql存儲引擎Mysql的存儲引擎有以下幾種:
我的是5.7.15版本,默認(rèn)使用的是Innodb版本!
常用的存儲引擎有以下:
Innodb引擎,Innodb引擎提供了對數(shù)據(jù)庫ACID事務(wù)的支持。并且還提供了行級鎖和外鍵的約束。它的設(shè)計的目標(biāo)就是處理大數(shù)據(jù)容量的數(shù)據(jù)庫系統(tǒng)。
MyIASM引擎(原本Mysql的默認(rèn)引擎),不提供事務(wù)的支持,也不支持行級鎖和外鍵。
MEMORY引擎:所有的數(shù)據(jù)都在內(nèi)存中,數(shù)據(jù)的處理速度快,但是安全性不高。
同一個數(shù)據(jù)庫也可以使用多種存儲引擎的表。如果一個表修改要求比較高的事務(wù)處理,可以選擇InnoDB。這個數(shù)據(jù)庫中可以將查詢要求比較高的表選擇MyISAM存儲。如果該數(shù)據(jù)庫需要一個用于查詢的臨時表,可以選擇MEMORY存儲引擎。
參考資料:
https://www.cnblogs.com/xiaohaillong/p/6079551.html
http://blog.csdn.net/ls5718/article/details/52248040
http://blog.csdn.net/t146lla128xx0x/article/details/78737290
MyIASM和Innodb兩種引擎所使用的索引的數(shù)據(jù)結(jié)構(gòu)是什么?MyIASM和Innodb兩種引擎所使用的索引的數(shù)據(jù)結(jié)構(gòu)是什么?
答案:都是B+樹!
MyIASM引擎,B+樹的數(shù)據(jù)結(jié)構(gòu)中存儲的內(nèi)容實際上是實際數(shù)據(jù)的地址值。也就是說它的索引和實際數(shù)據(jù)是分開的,只不過使用索引指向了實際數(shù)據(jù)。這種索引的模式被稱為非聚集索引。
Innodb引擎的索引的數(shù)據(jù)結(jié)構(gòu)也是B+樹,只不過數(shù)據(jù)結(jié)構(gòu)中存儲的都是實際的數(shù)據(jù),這種索引有被稱為聚集索引。
varchar和char的區(qū)別varchar和char的區(qū)別
Char是一種固定長度的類型,varchar是一種可變長度的類型
mysql有關(guān)權(quán)限的表都有哪幾個mysql有關(guān)權(quán)限的表都有哪幾個
MySQL服務(wù)器通過權(quán)限表來控制用戶對數(shù)據(jù)庫的訪問,權(quán)限表存放在mysql數(shù)據(jù)庫里,由mysql_install_db腳本初始化。這些權(quán)限表分別user,db,table_priv,columns_priv和host。下面分別介紹一下這些表的結(jié)構(gòu)和內(nèi)容:
user權(quán)限表:記錄允許連接到服務(wù)器的用戶帳號信息,里面的權(quán)限是全局級的。
db權(quán)限表:記錄各個帳號在各個數(shù)據(jù)庫上的操作權(quán)限。
table_priv權(quán)限表:記錄數(shù)據(jù)表級的操作權(quán)限。
columns_priv權(quán)限表:記錄數(shù)據(jù)列級的操作權(quán)限。
host權(quán)限表:配合db權(quán)限表對給定主機(jī)上數(shù)據(jù)庫級操作權(quán)限作更細(xì)致的控制。這個權(quán)限表不受GRANT和REVOKE語句的影響。
數(shù)據(jù)表損壞的修復(fù)方式有哪些?數(shù)據(jù)表損壞的修復(fù)方式有哪些?
使用 myisamchk 來修復(fù),具體步驟:
1)修復(fù)前將mysql服務(wù)停止。
2)打開命令行方式,然后進(jìn)入到mysql的/bin目錄。
3)執(zhí)行myisamchk –recover 數(shù)據(jù)庫所在路徑/*.MYI
使用repair table 或者 OPTIMIZE table命令來修復(fù),REPAIR TABLE table_name 修復(fù)表 OPTIMIZE TABLE table_name 優(yōu)化表 REPAIR TABLE 用于修復(fù)被破壞的表。
OPTIMIZE TABLE 用于回收閑置的數(shù)據(jù)庫空間,當(dāng)表上的數(shù)據(jù)行被刪除時,所占據(jù)的磁盤空間并沒有立即被回收,使用了OPTIMIZE TABLE命令后這些空間將被回收,并且對磁盤上的數(shù)據(jù)行進(jìn)行重排(注意:是磁盤上,而非數(shù)據(jù)庫)
MySQL中InnoDB引擎的行鎖是通過加在什么上完成
InnoDB是基于索引來完成行鎖
例: select * from tab_with_index where id = 1 for update;
for update 可以根據(jù)條件來完成行鎖鎖定,并且 id 是有索引鍵的列,
如果 id 不是索引鍵那么InnoDB將完成表鎖,,并發(fā)將無從談起
數(shù)據(jù)庫優(yōu)化的思路 SQL優(yōu)化在我們書寫SQL語句的時候,其實書寫的順序、策略會影響到SQL的性能,雖然實現(xiàn)的功能是一樣的,但是它們的性能會有些許差別。
因此,下面就講解在書寫SQL的時候,怎么寫比較好。
①選擇最有效率的表名順序數(shù)據(jù)庫的解析器按照從右到左的順序處理FROM子句中的表名,F(xiàn)ROM子句中寫在最后的表將被最先處理
在FROM子句中包含多個表的情況下:
如果三個表是完全無關(guān)系的話,將記錄和列名最少的表,寫在最后,然后依次類推
也就是說:選擇記錄條數(shù)最少的表放在最后
如果有3個以上的表連接查詢:
如果三個表是有關(guān)系的話,將引用最多的表,放在最后,然后依次類推。
也就是說:被其他表所引用的表放在最后
例如:查詢員工的編號,姓名,工資,工資等級,部門名
emp表被引用得最多,記錄數(shù)也是最多,因此放在form字句的最后面
select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname from salgrade,dept,emp where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)②WHERE子句中的連接順序
數(shù)據(jù)庫采用自右而左的順序解析WHERE子句,根據(jù)這個原理,表之間的連接必須寫在其他WHERE條件之左,那些可以過濾掉最大數(shù)量記錄的條件必須寫在WHERE子句的之右。
emp.sal可以過濾多條記錄,寫在WHERE字句的最右邊
select emp.empno,emp.ename,emp.sal,dept.dname from dept,emp where (emp.deptno = dept.deptno) and (emp.sal > 1500)③SELECT子句中避免使用*號
我們當(dāng)時學(xué)習(xí)的時候,“*”號是可以獲取表中全部的字段數(shù)據(jù)的。
但是它要通過查詢數(shù)據(jù)字典完成的,這意味著將耗費(fèi)更多的時間
使用*號寫出來的SQL語句也不夠直觀。
④用TRUNCATE替代DELETE這里僅僅是:刪除表的全部記錄,除了表結(jié)構(gòu)才這樣做。
DELETE是一條一條記錄的刪除,而Truncate是將整個表刪除,保留表結(jié)構(gòu),這樣比DELETE快
⑤多使用內(nèi)部函數(shù)提高SQL效率例如使用mysql的concat()函數(shù)會比使用||來進(jìn)行拼接快,因為concat()函數(shù)已經(jīng)被mysql優(yōu)化過了。
⑥使用表或列的別名如果表或列的名稱太長了,使用一些簡短的別名也能稍微提高一些SQL的性能。畢竟要掃描的字符長度就變少了。。。
⑦多使用commitcomiit會釋放回滾點...
⑧善用索引索引就是為了提高我們的查詢數(shù)據(jù)的,當(dāng)表的記錄量非常大的時候,我們就可以使用索引了。
⑨SQL寫大寫我們在編寫SQL 的時候,官方推薦的是使用大寫來寫關(guān)鍵字,因為Oracle服務(wù)器總是先將小寫字母轉(zhuǎn)成大寫后,才執(zhí)行
⑩避免在索引列上使用NOT因為Oracle服務(wù)器遇到NOT后,他就會停止目前的工作,轉(zhuǎn)而執(zhí)行全表掃描
①①避免在索引列上使用計算WHERE子句中,如果索引列是函數(shù)的一部分,優(yōu)化器將不使用索引而使用全表掃描,這樣會變得變慢
①②用 >= 替代 >低效: SELECT * FROM EMP WHERE DEPTNO > 3 首先定位到DEPTNO=3的記錄并且掃描到第一個DEPT大于3的記錄 高效: SELECT * FROM EMP WHERE DEPTNO >= 4 直接跳到第一個DEPT等于4的記錄①③用IN替代OR
select * from emp where sal = 1500 or sal = 3000 or sal = 800; select * from emp where sal in (1500,3000,800);①④總是使用索引的第一個列
如果索引是建立在多個列上,只有在它的第一個列被WHERE子句引用時,優(yōu)化器才會選擇使用該索引。 當(dāng)只引用索引的第二個列時,不引用索引的第一個列時,優(yōu)化器使用了全表掃描而忽略了索引
create index emp_sal_job_idex on emp(sal,job); ---------------------------------- select * from emp where job != "SALES"; 上邊就不使用索引了。數(shù)據(jù)庫結(jié)構(gòu)優(yōu)化
1)范式優(yōu)化: 比如消除冗余(節(jié)省空間。。)
2)反范式優(yōu)化:比如適當(dāng)加冗余等(減少join)
3)拆分表: 垂直拆分和水平拆分
服務(wù)器硬件優(yōu)化這個么多花錢咯!
SQL練習(xí)題下列練習(xí)題參考自公眾號Java知音:
https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247483693&idx=1&sn=9fa301b0076778cd854a924e96cc356e&chksm=ebd63e01dca1b71745dca1f7e1c2aa2b7c80a393185db690b4fdfba22bb10ca87ea2cd6fa774&scene=21#wechat_redirect
https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247483696&idx=1&sn=5f472ce7720aede89e2e15ea64bed1bc&chksm=ebd63e1cdca1b70ad18dec268c9903b2cbe11f9ce7b0633980c78a28bd5b1b57c4efbe7a3411&scene=21#wechat_redirect
基本表結(jié)構(gòu):
student(sno,sname,sage,ssex)學(xué)生表 course(cno,cname,tno) 課程表 sc(sno,cno,score) 成績表 teacher(tno,tname) 教師表
題目:
101,查詢課程1的成績比課程2的成績高的所有學(xué)生的學(xué)號 select a.sno from (select sno,score from sc where cno=1) a, (select sno,score from sc where cno=2) b where a.score>b.score and a.sno=b.sno 102,查詢平均成績大于60分的同學(xué)的學(xué)號和平均成績 select a.sno as "學(xué)號", avg(a.score) as "平均成績" from (select sno,score from sc) a group by sno having avg(a.score)>60 103,查詢所有同學(xué)的學(xué)號、姓名、選課數(shù)、總成績 select a.sno as 學(xué)號, b.sname as 姓名, count(a.cno) as 選課數(shù), sum(a.score) as 總成績 from sc a, student b where a.sno = b.sno group by a.sno, b.sname 或者: selectstudent.sno as 學(xué)號, student.sname as 姓名, count(sc.cno) as 選課數(shù), sum(score) as 總成績 from student left Outer join sc on student.sno = sc.sno group by student.sno, sname 104,查詢姓“張”的老師的個數(shù) selectcount(distinct(tname)) from teacher where tname like "張%‘ 或者: select tname as "姓名", count(distinct(tname)) as "人數(shù)" from teacher where tname like"張%" group by tname 105,查詢沒學(xué)過“張三”老師課的同學(xué)的學(xué)號、姓名 select student.sno,student.sname from student where sno not in (select distinct(sc.sno) from sc,course,teacher where sc.cno=course.cno and teacher.tno=course.tno and teacher.tname="張三") 106,查詢同時學(xué)過課程1和課程2的同學(xué)的學(xué)號、姓名 select sno, sname from student where sno in (select sno from sc where sc.cno = 1) and sno in (select sno from sc where sc.cno = 2) 或者: selectc.sno, c.sname from (select sno from sc where sc.cno = 1) a, (select sno from sc where sc.cno = 2) b, student c where a.sno = b.sno and a.sno = c.sno 或者: select student.sno,student.sname from student,sc where student.sno=sc.sno and sc.cno=1 and exists( select * from sc as sc_2 where sc_2.sno=sc.sno and sc_2.cno=2) 107,查詢學(xué)過“李四”老師所教所有課程的所有同學(xué)的學(xué)號、姓名 select a.sno, a.sname from student a, sc b where a.sno = b.sno and b.cno in (select c.cno from course c, teacher d where c.tno = d.tno and d.tname = "李四") 或者: select a.sno, a.sname from student a, sc b, (select c.cno from course c, teacher d where c.tno = d.tno and d.tname = "李四") e where a.sno = b.sno and b.cno = e.cno 108,查詢課程編號1的成績比課程編號2的成績高的所有同學(xué)的學(xué)號、姓名 select a.sno, a.sname from student a, (select sno, score from sc where cno = 1) b, (select sno, score from sc where cno = 2) c where b.score > c.score and b.sno = c.sno and a.sno = b.sno 109,查詢所有課程成績小于60分的同學(xué)的學(xué)號、姓名 select sno,sname from student where sno not in (select distinct sno from sc where score > 60) 110,查詢至少有一門課程與學(xué)號為1的同學(xué)所學(xué)課程相同的同學(xué)的學(xué)號和姓名 select distinct a.sno, a.sname from student a, sc b where a.sno <> 1 and a.sno=b.sno and b.cno in (select cno from sc where sno = 1) 或者: select s.sno,s.sname from student s, (select sc.sno from sc where sc.cno in (select sc1.cno from sc sc1 where sc1.sno=1)and sc.sno<>1 group by sc.sno)r1 where r1.sno=s.sno 111、把“sc”表中“王五”所教課的成績都更改為此課程的平均成績 update sc set score = (select avg(sc_2.score) from sc sc_2 wheresc_2.cno=sc.cno) from course,teacher where course.cno=sc.cno and course.tno=teacher.tno andteacher.tname="王五" 112、查詢和編號為2的同學(xué)學(xué)習(xí)的課程完全相同的其他同學(xué)學(xué)號和姓名 這一題分兩步查: 1, select sno from sc where sno <> 2 group by sno having sum(cno) = (select sum(cno) from sc where sno = 2) 2, select b.sno, b.sname from sc a, student b where b.sno <> 2 and a.sno = b.sno group by b.sno, b.sname having sum(cno) = (select sum(cno) from sc where sno = 2) 113、刪除學(xué)習(xí)“王五”老師課的sc表記錄 delete sc from course, teacher where course.cno = sc.cno and course.tno = teacher.tno and tname = "王五" 114、向sc表中插入一些記錄,這些記錄要求符合以下條件: 將沒有課程3成績同學(xué)的該成績補(bǔ)齊, 其成績?nèi)∷袑W(xué)生的課程2的平均成績 insert sc select sno, 3, (select avg(score) from sc where cno = 2) from student where sno not in (select sno from sc where cno = 3) 115、按平平均分從高到低顯示所有學(xué)生的如下統(tǒng)計報表: -- 學(xué)號,企業(yè)管理,馬克思,UML,數(shù)據(jù)庫,物理,課程數(shù),平均分 select sno as 學(xué)號 ,max(case when cno = 1 then score end) AS 企業(yè)管理 ,max(case when cno = 2 then score end) AS 馬克思 ,max(case when cno = 3 then score end) AS UML ,max(case when cno = 4 then score end) AS 數(shù)據(jù)庫 ,max(case when cno = 5 then score end) AS 物理 ,count(cno) AS 課程數(shù) ,avg(score) AS 平均分 FROM sc GROUP by sno ORDER by avg(score) DESC 116、查詢各科成績最高分和最低分: 以如下形式顯示:課程號,最高分,最低分 select cno as 課程號, max(score) as 最高分, min(score) 最低分 from sc group by cno select course.cno as "課程號" ,MAX(score) as "最高分" ,MIN(score) as "最低分" from sc,course where sc.cno=course.cno group by course.cno 117、按各科平均成績從低到高和及格率的百分?jǐn)?shù)從高到低順序 SELECT t.cno AS 課程號, max(course.cname)AS 課程名, isnull(AVG(score),0) AS 平均成績, 100 * SUM(CASE WHEN isnull(score,0)>=60 THEN 1 ELSE 0 END)/count(1) AS 及格率 FROM sc t, course where t.cno = course.cno GROUP BY t.cno ORDER BY 及格率 desc 118、查詢?nèi)缦抡n程平均成績和及格率的百分?jǐn)?shù)(用"1行"顯示): 企業(yè)管理(001),馬克思(002),UML (003),數(shù)據(jù)庫(004) select avg(case when cno = 1 then score end) as 平均分1, avg(case when cno = 2 then score end) as 平均分2, avg(case when cno = 3 then score end) as 平均分3, avg(case when cno = 4 then score end) as 平均分4, 100 * sum(case when cno = 1 and score > 60 then 1 else 0 end) / sum(casewhen cno = 1 then 1 else 0 end) as 及格率1, 100 * sum(case when cno = 2 and score > 60 then 1 else 0 end) / sum(casewhen cno = 2 then 1 else 0 end) as 及格率2, 100 * sum(case when cno = 3 and score > 60 then 1 else 0 end) / sum(casewhen cno = 3 then 1 else 0 end) as 及格率3, 100 * sum(case when cno = 4 and score > 60 then 1 else 0 end) / sum(casewhen cno = 4 then 1 else 0 end) as 及格率4 from sc 119、查詢不同老師所教不同課程平均分, 從高到低顯示 select max(c.tname) as 教師, max(b.cname) 課程, avg(a.score) 平均分 from sc a, course b, teacher c where a.cno = b.cno and b.tno = c.tno group by a.cno order by 平均分 desc 或者: select r.tname as "教師",r.rname as "課程" , AVG(score) as "平均分" from sc, (select t.tname,c.cno as rcso,c.cname as rname from teacher t ,course c where t.tno=c.tno)r where sc.cno=r.rcso group by sc.cno,r.tname,r.rname order by AVG(score) desc 120、查詢?nèi)缦抡n程成績均在第3名到第6名之間的學(xué)生的成績: -- [學(xué)生ID],[學(xué)生姓名],企業(yè)管理,馬克思,UML,數(shù)據(jù)庫,平均成績 select top 6 max(a.sno) 學(xué)號, max(b.sname) 姓名, max(case when cno = 1 then score end) as 企業(yè)管理, max(case when cno = 2 then score end) as 馬克思, max(case when cno = 3 then score end) as UML, max(case when cno = 4 then score end) as 數(shù)據(jù)庫, avg(score) as 平均分 from sc a, student b where a.sno not in (select top 2 sno from sc where cno = 1 order by score desc) and a.sno not in (select top 2 sno from sc where cno = 2 order by scoredesc) and a.sno not in (select top 2 sno from sc where cno = 3 order by scoredesc) and a.sno not in (select top 2 sno from sc where cno = 4 order by scoredesc) and a.sno = b.sno group by a.snoOracle和Mysql的區(qū)別
在Mysql中,一個用戶下可以創(chuàng)建多個庫:
而在Oracle中,Oracle服務(wù)器是由兩部分組成
數(shù)據(jù)庫實例【理解為對象,看不見的】
數(shù)據(jù)庫【理解為類,看得見的】
一個數(shù)據(jù)庫實例可擁有多個用戶,一個用戶默認(rèn)擁有一個表空間。
表空間是存儲我們數(shù)據(jù)庫表的地方,表空間內(nèi)可以有多個文件。
當(dāng)我們使用Oracle作為我們數(shù)據(jù)庫時,我們需要指定用戶、表空間來存儲我們所需要的數(shù)據(jù)!
最后參考資料:
http://blog.csdn.net/xlgen157387/article/details/46899031
http://blog.csdn.net/beauty_1991/article/details/51209107
https://zhuanlan.zhihu.com/p/23713529
http://blog.csdn.net/wickedvalley/article/details/51527551
http://blog.csdn.net/zhugewendu/article/details/73550414
如果文章有錯的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號:Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/68673.html
Web前端開發(fā)是創(chuàng)建Web頁面或app等前端界面呈現(xiàn)給用戶的過程。第一階段:前端基礎(chǔ)(HTML / CSS / JavaScript / jQuery)初識HTML+CSS【學(xué)習(xí)筆記】HTML基礎(chǔ)完結(jié)篇html基礎(chǔ)知識——標(biāo)簽詳解html基礎(chǔ)知識——與用戶交互!(表單標(biāo)簽)html基礎(chǔ)知識——css樣式①史上最全Html和CSS布局技巧面試題匯總 HTML+CSS篇CSS 最核心的幾個概念純HTM...
Web前端開發(fā)是創(chuàng)建Web頁面或app等前端界面呈現(xiàn)給用戶的過程。第一階段:前端基礎(chǔ)(HTML / CSS / JavaScript / jQuery)初識HTML+CSS【學(xué)習(xí)筆記】HTML基礎(chǔ)完結(jié)篇html基礎(chǔ)知識——標(biāo)簽詳解html基礎(chǔ)知識——與用戶交互!(表單標(biāo)簽)html基礎(chǔ)知識——css樣式①史上最全Html和CSS布局技巧面試題匯總 HTML+CSS篇CSS 最核心的幾個概念純HTM...
Web前端開發(fā)是創(chuàng)建Web頁面或app等前端界面呈現(xiàn)給用戶的過程。第一階段:前端基礎(chǔ)(HTML / CSS / JavaScript / jQuery)初識HTML+CSS【學(xué)習(xí)筆記】HTML基礎(chǔ)完結(jié)篇html基礎(chǔ)知識——標(biāo)簽詳解html基礎(chǔ)知識——與用戶交互!(表單標(biāo)簽)html基礎(chǔ)知識——css樣式①史上最全Html和CSS布局技巧面試題匯總 HTML+CSS篇CSS 最核心的幾個概念純HTM...
Web前端開發(fā)是創(chuàng)建Web頁面或app等前端界面呈現(xiàn)給用戶的過程。第一階段:前端基礎(chǔ)(HTML / CSS / JavaScript / jQuery)初識HTML+CSS【學(xué)習(xí)筆記】HTML基礎(chǔ)完結(jié)篇html基礎(chǔ)知識——標(biāo)簽詳解html基礎(chǔ)知識——與用戶交互!(表單標(biāo)簽)html基礎(chǔ)知識——css樣式①史上最全Html和CSS布局技巧面試題匯總 HTML+CSS篇CSS 最核心的幾個概念純HTM...
閱讀 2270·2023-04-25 14:56
閱讀 2764·2021-11-16 11:44
閱讀 2804·2021-09-22 15:00
閱讀 1965·2019-08-29 16:55
閱讀 2244·2019-08-29 14:04
閱讀 2395·2019-08-29 11:23
閱讀 3744·2019-08-26 10:46
閱讀 1977·2019-08-22 18:43