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) | 計算一組值的平均值 |