檢視、索引、儲存過程簡述與優缺點
1.檢視
(1).什麼是檢視?
檢視(View)作為一種資料庫物件,為使用者提供了一個可以檢索資料表中的資料方式。使用者通過檢視來瀏覽資料表中感興趣的部分或全部資料,而資料的物理儲存位置仍然在表中。
檢視是一個虛擬表,並不代表任何物理資料,只是用來檢視資料的視窗而已。檢視並不是以一組資料的形式儲存在資料庫中,資料庫中只儲存檢視的定義,而不儲存檢視對應的資料,這些資料仍儲存在匯出檢視的基本表中。當基本表中的資料發生變化時,從檢視中查詢出來的資料也隨之改變。
檢視中的資料行和列都是來自於基本表,是在檢視被引用時動態生成的。使用檢視可以集中、簡化和制定使用者的資料庫顯示,使用者可以通過檢視來訪問資料,而不必直接去訪問該檢視的基本表。
檢視由檢視名和檢視定義兩個部分組成。檢視是從一個或多個表匯出來的表,它實際上是一個查詢結果,檢視的名字和檢視對應的查詢儲存在資料字典中。
(2).檢視的優缺點?
<1>.檢視的優點
A.資料安全性。
對不同的使用者定義不同的檢視,使使用者只能看到與自己有關的資料。資料庫授權命令可以使每個使用者對資料庫的檢索限制到特定的資料庫物件上,但不能授權到資料庫特定行和特定的列上。通過檢視,使用者可以被限制在資料的不同子集上。
B.查詢簡單化。
為複雜的查詢建立一個檢視,使用者不必輸入複雜的查詢語句,只需針對此檢視做簡單的查詢即可。那些被經常使用的查詢可以被定義為檢視,從而使使用者不必為以後的操作每次都指定全部的條件。
C.邏輯資料獨立性。
檢視可以使應用程式和資料庫表在一定程度上獨立。如果沒有檢視,應用一定是建立在表上的。有了檢視之後,程式可以建立在檢視之上,從而程式與資料庫表被檢視分割開來。
對於檢視的操作,例如,查詢只依賴於檢視的定義,當構成檢視的基本表需要修改時,只需要修改檢視定義中的子查詢部分,而基於檢視的查詢不用改變。
<2>.檢視的缺點
A.效能。
SQL Server必須把檢視的查詢轉化成對基本表的查詢,如果這個檢視是由一個複雜的多表查詢所定義,那麼,即使是檢視的一個簡單查詢,SQL Server也把它變成一個複雜的結合體,需要花費一定的時間。
B.修改限制。
當用戶試圖修改檢視的某些行時,SQL Server必須把它轉化為對基本表的某些行的修改。事實上,當從檢視中插入或者刪除時,情況也是這樣。對於簡單檢視來說,這是很方便的,但是,對於比較複雜的檢視,可能是不可修改的,這些檢視有如下特徵:
a.有UNIQUE等集合操作符的檢視。
b.有GROUP BY子句的檢視。
c.有諸如AVG\SUM\MAX等聚合函式的檢視。
d.使用DISTINCT關鍵字的檢視。
e.連線表的檢視(其中有些例外)
(3).建立檢視的限制:
在建立檢視時,還要注意試圖必須滿足以下幾點限制:
<1>.不能將規則或者DEFAULT定義關聯於檢視。
<2>.定義檢視的查詢中不能含有ORDER BY\COMPURER\COMPUTER BY 子句和INTO關鍵字
<3>.如果檢視中某一列是一個算術表示式、建構函式或者常數,而且檢視中兩個或者更多的不同列擁有一個相同的名字(這種情況通常是因為在檢視的定義中有一個連線,而且這兩個或者多個來自不同表的列擁有相同的名字),此時,使用者需要為檢視的每一列指定列的名稱。
參考部落格:
《使用SQL Server檢視的優缺點》
2.索引
(1).什麼是索引?
索引是以表列為基礎的資料庫物件,它儲存著表中排序的索引列,並且記錄了索引列在資料表中的物理儲存位置,實現了表中資料的邏輯排序,其主要目的是提高SQL Server系統的效能,加快資料的查詢速度和減少系統的響應時間。索引通過記錄表中的關鍵值指向表中的記錄,這樣資料庫引擎就不用掃描整個表而定位到相關的記錄。相反,如果沒有索引,則會導致SQL Server搜尋表中的所有記錄,以獲取匹配結果。
索引除了可以提高查詢表內資料的速度以外,還可以使表和表之間的連線速度加快。例如,在實現資料參照完整性時,可以將表的外來鍵製作為索引,這樣將加速表與表之間的連線。
(2).索引的分類
有3種索引型別:聚集索引、非聚集索引和唯一索引。如果表中存在聚集索引,則非聚集索引使用聚集索引來加快資料查詢。
<1>.聚集索引
聚集索引會對錶和檢視進行物理排序,所以這種索引對查詢非常有效,在表和檢視中只能有一個聚集索引。當建立主鍵約束時,如果表中沒有聚集索引,SQL Server會用主鍵列作為聚集索引鍵。可以在表的任何列或列的組合上建立索引,實際應用中一般定義成主鍵約束的列建立聚集索引。
<2>.非聚集索引
非聚集索引不會對錶和檢視進行物理排序。如果表中不存在聚集索引,則表示未排序的。在表或檢視中,最多可以建立250個非聚集索引,或者249個非聚集索引和1個聚集索引。
<3>.唯一索引
唯一索引不允許兩行具有相同的索引值。只要列中資料是唯一的,就可在同一個表上建立一個唯一的聚集索引。如果必須實施唯一性以確保資料的完整性,則應在列上建立UNIQUE或PRIMARY KEY約束,而不要建立唯一索引。
(3).使用索引的代價
雖然索引有很多優點,但索引的存在也讓系統付出了一定的代價。建立索引和維護索引都會消耗時間,當對錶中的資料進行增加、刪除和修改操作時,索引就要進行維護,否則索引的作用就會下降;另外,每個索引都會佔用一定的物理空間,如果佔用的物理空間過多,就會影響到整個SQL Server系統的效能。
(4).建立索引的原則
建立索引雖然可以提高查詢速度,但是它是犧牲一定的系統性能。因此,在建立時,哪些列適合建立索引,哪些列不適合建立索引,需要進行判斷,具體以下原則:
<1>.有主鍵的資料列要建立索引。因為主鍵可以加速定位到表中的某一行。
<2>.有外來鍵的資料列要建立索引。外來鍵列通常用於表與表之間的連線,在其上建立索引可以加快表間的連線。
<3>.對於經常查詢的資料列最好建立索引。
A.對於需要在指定範圍內快速或頻繁查詢的資料列,因為索引已經排序,其指定的範圍是連續的,查詢可以利用索引的排序,加快查詢的時間。
B.經常用在WHERE子句中的資料列,將索引建立在WHERE子句的集合過程中,對於需要加速或頻繁檢索的資料列,可以讓這些經常參與查詢的資料列按照索引的排序進行查詢,加快查詢的時間。
<4>.對於那些查詢中很少涉及的列、重複值比較多的列不要建立索引。
例如,在查詢中很少使用的列,有無索引並不能提高查詢的速度,相反增加了系統維護時間和消耗了系統空間。
<5>.對於定義為text、image和bit資料型別的列不要建立索引。因為這些資料型別的資料列的資料量要麼很大、要麼很小,不利於使用索引。
參考部落格:
《SQLServer索引調優實踐》
《SQL Server索引維護指導(1)》
《詳細講解SQL Server索引的效能問題》
3.儲存過程
(1).什麼是儲存過程?
當開發一個應用程式時,為了易於修改和擴充,經常會將負責不同功能的語句集中起來而且按照用途分別放置,以便能夠反覆呼叫,而這些獨立放置且擁有不同功能的語言,即是“過程”(Procedure)。
儲存過程(Stored Producedures)是一組為完整特定功能的SQL語句集,經編譯後儲存在資料庫中。使用者通過指定儲存過程的名字給出引數(如果該儲存過程帶有引數)來執行它。
它能夠包含執行各種資料庫操作的語句,並且可以呼叫其他的儲存過程;能夠接受輸入引數,並以輸出引數的形式將多個數據值返回給呼叫程式(Calling Procedure)或批處理(Batch);向呼叫程式或批處理返回一個狀態值,以表明成功或失敗(以及失敗的原因)。
(2).儲存過程的優點
<1>.儲存過程優點
A.執行速度快。
儲存過程只在創造時進行編譯,已經通過語法檢查和效能優化,以後每次執行儲存過程都不需再重新編譯,而我們通常使用的SQL語句每執行一次就編譯一次,所以使用儲存過程可提高資料庫執行速度。
B.允許元件式程式設計。
經常會遇到複雜的業務邏輯和對資料庫的操作,這個時候就會用SP來封裝資料庫操作。當對資料庫進行復雜操作時(如對多個表進行Update,Insert,Query,Delete時),可將此複雜操作用儲存過程封裝起來與資料庫提供的事務處理結合一起使用。只需建立儲存過程一次並將其儲存在資料庫中,以後即可在程式中呼叫該過程任意次。在程式碼上看,SQL語句和程式程式碼語句的分離,可以提高程式程式碼的可讀性。
儲存過程可以設定引數,可以根據傳入引數的不同重複使用同一個儲存過程,從而高效的提高程式碼的優化率和可讀性。
C.減少網路流量。
一個需要數百行Transact-SQL程式碼的操作由一條執行過程程式碼的單獨語句就可實現,而不需要在網路中傳送數百行程式碼。
對於同一個針對資料庫物件的操作,如果這一操作所涉及到的T-SQL語句被組織成一儲存過程,那麼當在客戶機上呼叫該儲存過程時,網路中傳遞的只是該呼叫語句,否則將會是多條SQL語句。從而減輕了網路流量,降低了網路負載。
D.提高系統安全性。
可將儲存過程作為使用者存取資料的管道。可以限制使用者對資料表的存取許可權,建立特定的儲存過程供使用者使用,避免非授權使用者對資料的訪問,保證資料的安全。
<2>.儲存過程缺點:
A.移植性差。依賴於資料庫廠商,難以移植(當一個小系統發展到大系統時,對資料庫的要求也會發生改變);
B.難以除錯、維護。業務邏輯大的時候,封裝性不夠,難除錯難以維護;
C.伺服器不能負載均衡。複雜的應用用儲存過程來實現,就把業務處理的負擔壓在資料庫伺服器上了。沒有辦法通過中間層來靈活分擔負載和壓力.均衡負載等。
(3).儲存過程分類
<1>.系統儲存過程
系統儲存過程(System Stored Procedures)主要儲存在master資料庫中,並以sp_為字首,並且系統儲存過程主要是從系統表中獲取資訊,從而為系統管理員管理SQL Server提供支援。
<2>.本地儲存過程
本地儲存過程(Local Stored Procedures)也就是使用者自行建立在使用者資料庫中的儲存過程。事實上一般所說的儲存過程值得就是本地儲存過程。使用者建立的儲存過程是由使用者建立並能完成某一特定功能(如查詢使用者所需的資料資訊)的儲存過程。
<3>.臨時儲存過程
臨時儲存過程(Temporary Stored Procedures)可分為以下兩種:
A.本地臨時儲存過程
如果在建立儲存過程中,以井號(#)作為其名稱的第一個字元,則該儲存過程將成為一個存放在tempdb資料庫中的本地臨時儲存過程(例如,CREATE PROCEDURE #book_proc.....)。本地臨時儲存過程只有建立它的連線的使用者才能夠執行它,而且一旦這位使用者斷開與SQL Server的連線,本地臨時儲存過程就會自動刪除,當然,這位使用者也可以在連線期間用DROP PROCEDURE命令刪除多建立的本地臨時儲存過程。
B.全域性臨時儲存過程
如果在所建立的儲存過程名稱是以兩個井號(# #)開始,則該儲存過程將成為一個儲存在tempdb資料庫中的全域性臨時儲存過程,如果沒有,便立即將全域性臨時儲存過程刪除;如果有,SQL Server會讓這些執行中的操作繼續進行,但是不允許任何使用者再執行全域性臨時儲存過程,等到所有未完成的操作執行完畢後,全域性臨時儲存過程就會自動刪除。
由於全域性臨時儲存過程能夠被所有的連線使用者使用,因此,必須注意其名稱不能和其他連線所採用的名稱相同。
<4>.遠端儲存過程
遠端儲存過程(Remote Stored Procedures)是位於遠端伺服器上的儲存過程,通常可以使用分散式查詢和EXECUTE命令執行一個遠端儲存過程。
<5>.擴充套件儲存過程
擴充套件儲存過程(Extended Stored Procedures)是使用者可以使用外部程式語言編寫的儲存過程。擴充套件儲存過程在使用和執行上與一般的儲存過程完全相同。可以將引數傳遞給擴充套件儲存過程,擴充套件儲存過程也能夠返回結果和狀態值。
為了區別,擴充套件儲存過程的名稱通常以xp_開頭。擴充套件儲存過程是以動態連結庫(DLLS)的形式存在,能讓SQL Server動態的裝載和執行。擴充套件儲存過程一定要儲存在系統資料庫master中。
參考部落格:
《SQL Server 儲存過程》
4.事務處理
(1).什麼是事務?
事務是單個的工作單元。如果某一事務成功,則在該事務中進行的所有資料更改均會提交,成為資料庫中的永久組成部分。如果事務遇到錯誤且必須取消或回滾,則所有資料更改均被清除。事務作為一個邏輯工作單元有4個屬性,稱為ACID(原子性、一致性、隔離性和永續性)屬性。
<1>.原子性:事務必須是原子工作單元,對於其資料修改,要麼全都執行,要麼全都不執行。
<2>.一致性:事務在完成時,必須使所有的資料都保持一致狀態。在相關資料庫中,所有規則都必須應用於事務的修改,以保持所有資料的完整性。事物結束時,所有的內容資料結果都必須是正確的。
<3>.隔離性:由併發事務所作的修改必須與任何其他併發事務所作的修改隔離,保證事務檢視資料時資料處於的狀態,只能是另一併發事務修改它之前的狀態或者是另一事務修改它之後的狀態,而不能中間狀態的資料。
<4>.永續性:事務完成之後對系統的影響是永久性的。
(2).事務分類
<1>.顯式事務:用begin transaction明確指定事務的開始。
<2>.隱性事務:開啟隱性事務:set implicit_transactions on,當以隱性事務模式操作時,SQL Servler將在提交或回滾事務後自動啟動新事務。無法描述事務的開始,只需要提交或回滾事務。
<3>.自動提交事務:SQL Server的預設模式,它將每條單獨的T-SQL語句視為一個事務。如果成功執行,則自動提交,否則回滾。
參見部落格:
《SQL SERVER事務處理》
5.SQL Server內部函式
內部函式的作用是用來幫助使用者獲得系統的有關資訊、執行有關計算、實現資料轉換以及統計功能等。SQL所提供的內部函式又分為系統函式、日期函式、字串函式、數學函式、集合函式等幾種。
(1).系統函式
系統函式可幫助在不直接訪問系統表的情況下,獲取SQL Server系統表中的資訊。系統函式對SQL Server伺服器和 資料庫物件進行操作,並返回伺服器配置和資料庫物件數值等資訊。系統函式可用於選擇列表、WHERE子句以及任何允許使用表示式的地方。
系統函式 | 功能 |
---|---|
APP_NAME() | 返回當前會話的應用程式名稱(如果應用程式進行了設定) |
CASE表示式 | 計算條件列表,並返回表示式的多個可能結果之一。 |
CAST(expression AS data_type) | 將表示式顯示轉換為另一種資料型別。 |
CONVERT(data_type[length],expression[,style]) | 將表示式顯示轉換為另一種資料型別。CAST和CONVERT提供相似的功能。 |
COL_LENGTH | 返回列長度而不是列中儲存的任何單個字串的長度。 |
CURRENT_TIMESTAMP | 返回當前日期和時間。此函式等價於GETDATE()。 |
CURRENT_USER | 返回當前的使用者,此函式等價於USER_NAME()。 |
DATALENGTH(expression) | 返回表示式所佔用的位元組數。 |
GETANSINULL(['database']) | 返回會話的資料庫的預設為空值。當給定資料庫為空值時允許空值並且列或資料型別為空值沒有顯示定義,GETANSINULL返回1。 |
HOST_ID() | 返回主機標識。 |
HOST_NAME() | 返回主機名稱。 |
IDENT_CURRENT('table_name') | 任何會話和任何範圍中對指定的表生成的最後標識值. |
IDENT_INCR('table_or_view') | 返回表的標識列的標識增量。 |
IDENT_SEED('table_or_view') | 返回種子值,該值是在帶有標識列的表或檢視中建立標識列時指定的值。 |
IDENTITY(data_type[,seed,increment]) AS col_name | 只在SELECT IINTO生成新表中的標識列。 |
ISDATE(expression) | 表示式為有效日期格式時返回1,否則返回0。 |
ISNULL(check_expression,replacement_value) | 表示式值為NULL,用指定的替換值進行替換 |
ISNUMERIC(expression) | 表示式為數值型別時返回1,否則返回0。 |
NEWID() | 生成全域性唯一識別符號。 |
NULLIF(expression,expression) | 如果兩個指定的表示式相等,則返回空值。 |
PARSENAME('object_name','object_part') | 返回物件名的指定部分。 |
PERMISSIONS([objectid[,'column']]) | 返回一個包含點陣圖的值,表明當前使用者的語句,物件或列許可權。 |
ROWCOUNT_BIG() | 返回執行最後一個語句所影響的行數。 |
SCOPE_IDENTITY() | 插入當前範圍IDENTITY列中的最後一個標識值。 |
SERVERPROPERTY(propertyname) | 返回伺服器屬性的資訊。 |
SESSIONPROPERTY(option) | 會話的SET選項。 |
STATS_DATE(table_id,index_id) | 對table_id和index_id更新分配頁的日期。 |
USER_NAME([id]) | 返回給指定標識號的使用者資料庫的使用者名稱。 |
(2).日期函式
日期函式用來顯示日期和時間的資訊。它們處理datatime和smalldatetime的值,並對其進行算術運算。
日期函式 | 功能 |
---|---|
GETDATE() | 返回伺服器當前的系統日期和時間。 |
DATENAME(日期元素,日期) | 返回指定日期的名字,返回字串。 |
DATERART(日期元素,日期) | 返回指定日期的一部分,返回整數。 |
DATEDIFF(日期元素,日期1,日期2) | 返回兩個日期間的差值並轉換為指定日期元素形式 |
DATEADD(日期元素,日期) | 將日期元素加上日起產生新的日期。 |
YEAR(日期) | 返回年份(整數) |
MONTH(日期) | 返回月份(整數) |
DAY(日期) | 返回某月幾號的整數值 |
GETUTCDATE() | 返回表示當前UTC時間(世界時間座標和格林尼治報紙時間)的日起值 |
日期元素參照:
日期元素 | 縮寫 | 取值 |
---|---|---|
year | yy | 1753-9999 |
month | mm | 1-12 |
day | dd | 1-31 |
Day of year | dy | 1-366 |
week | wk | 0-52 |
weekday | dw | 1-7 |
hour | hh | 0-23 |
minute | mi | 0-59 |
quarter | 1-4 | |
second | ss | 0-59 |
millisecond | ms | 0-999 |
(3).字串函式
字串函式用於對字串進行連線、擷取等操作。
字串函式 | 功能 |
---|---|
ASCII(字元表示式) | 返回字元表示式最左邊字元的ASCII碼。 |
CHAR(整型表示式) | 講一個ASCII碼轉換成字元,ASCII碼應在0-255之間。 |
SPACE(整型表示式) | 返回n個空格組成的字串,n整型表示式的值。 |
LEA(字元表示式) | 返回字元表示式的字元(而不是位元組)個數,不計算尾部空格 |
RIGHT(字元表示式,整型表示式) | 從字元表示式中返回最右邊n個字元,n為整型表示式. |
LEFT(字元表示式,整型表示式) | 從字元表示式中返回最左邊n個字元,n為 整型表示式. |
SUBSTRING(字元表示式,起始點,n) | 返回字串表示式中從“起始點”開始的n個字元. |
STR(浮點表示式[,長度[,小數]]) | 將浮點表示式轉換為所給定長度的字串,小數點後的位數由所給出的“小數”決定。 |
LTRIM(字元表示式) | 去掉字元表示式的前導空格。 |
RTEIM(字元表示式) | 去掉字元表示式的尾部空格。 |
LOWER(字元表示式) | 將字元表示式的字母轉換為小寫字母。 |
UPPER(字元表示式) | 將字元表示式的字母轉換為大寫字母。 |
REVERSE(字元表示式) | 返回字元表示式的逆序。 |
DIFFERENCES(字元表示式1,字元表示式2) | 返回兩個字元表示式發音的相似程度(0-4),4為發音最相似。 |
PATINDEX("%模式%",表示式) | 返回指定模式在表示式中的起始位置,找不到時為0。 |
PEPLICATE(字元表示式,整型表示式) | 將字元表示式重複多次,整數給出的是重複次數. |
SOUNDEX(字元表示式) | 返回字元表示式所對應的4個字元的程式碼。 |
NCHAR(整型表示式) | 返回Unicode的字元。 |
UNICODE(字元表示式) | 返回字元表示式最左側字元的Unicode程式碼。 |
STUFF(字元表示式,start,length,字元表示式2) | 字元表示式1中從start開始的length個字元換成字元表示式2。 |
CHARINDEX(字元表示式1,字元表示式2,[開始位置]) | 返回字元表示式1在字元表示式2的開始位置,可以從所給的“開始位置”進行查詢, 如果沒指定開始位置,或者指定為負數或0,則預設從字元表達2的開始位置查詢。 |
(4).數學函式
數學函式 | 功能 |
---|---|
ABS(數值表示式) | 返回表示式的絕對值(正值)。 |
ACOS(浮點表示式) | 返回浮點表示式反餘弦值(單位為弧度)。 |
ASIN(浮點表示式) | 返回浮點表示式反正弦值(單位為弧度)。 |
ATAN(浮點表示式) | 返回浮點表示式反正切值(單位為弧度)。 |
ATAN2(浮點表示式1,浮點表示式2) | 返回以弧度為單位的角度值,此值的反正切值在所給的浮點表示式1和浮點表示式2之間。 |
COS(浮點表示式) | 返回浮點表示式三角餘弦值。 |
COT(浮點表示式) | 返回浮點表示式三角餘切值。 |
CEILIGN(數值表示式) | 返回大於或等於數值表示式的最小整數。 |
DEGREES(數值表示式) | 將弧度轉換為度。 |
EXP(浮點表示式) | 返回數值的指數形式。 |
FLOOR(數值表示式) | 返回大於或等於數值表示式的最大整數,CEILIGN的反函式 |
LOG(浮點表示式) | 返回數值的自然對數值。 |
LOG10(浮點表示式) | 返回以10為底浮點數的對數。 |
PI() | 返回的值3.1415962653。 |
POWER(數值表示式,冪) | 返回數字表達式的指定次冪的值。 |
RADIANS(數值表示式) | 將度轉換為弧度,DEGREES反函式。 |
RAND(整數表示式) | 返回一個0-1之間的隨機十進位制數。 |
ROUND(數值表示式,整數表示式) | 將設定表示式四捨五入為整型表示式所給的精度。 |
SIGN(數值表示式) | 符號函式,正數返回1,負數返回-1,0返回0。 |
SQUARE(浮點表示式) | 返回浮點表示式的平方。 |
SIN(浮點表示式) | 返回浮點表示式的三角正弦值(弧度為單位)。 |
SQRT(浮點表示式) | 返回一個浮點表示式的平方根。 |
TAN(浮點表示式) | 返回浮點表示式正切值(弧度為單位)。 |
(5).集合函式
集合函式也稱為統計函式,它對一組進行計算並返回一個數值。聚合函式經常與SELECT語句的子句一起使用。
聚合函式 | 功能 |
---|---|
SUM([ALL|DISTINCT]expression) | 計算一組資料的和 |
MIN([ALL|DISTINCT]expression) | 給出一組資料的最小值 |
MAX([ALL|DISTINCT]expression) | 給出一組資料的最大值 |
COUNT([ALL|DISTINCT]expression|*) | 計算總行數。COUNT(*)返回行數,包括含有空值的行,不能與DISTINCT一起使用 |
CHECKSUM(*|expression[,...n]) | 對一組數值的和進行校驗,可探測表的變化 |
BINARY_CHECKSUM(*|expression[,...n]) | 對二進位制的和進行校驗,可探測表的變化 |
AVG([ALL|DISTINCT]expression) | 計算一組值的平均值 |