SQL SERVER7应用
生活随笔
收集整理的這篇文章主要介紹了
SQL SERVER7应用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
交互式SQL(Transact SQL,TSQL)
它是SQL Server的查詢語言。提供以下命令:
· 創建和數據庫對象。
· 訪問和修改數據。
· 數據聚合(aggregation,又稱聚集)。
· 實施安全措施。
數據庫對象
???????數據庫對象是數據庫中的物理對象。這些對象擁有唯一的名字,并保存數據和數據關系信息。SQL Server定義了如下幾種對象:
1、 表(table)
表是用來存儲數據的兩維數組,它有行和列。列也稱為表屬性或字段,表中的每一列擁有唯一的名字,每一列包含具體的數據類型,這個數據類型由列中的數據類型定義。
2、 視圖(view)
視圖是虛擬的表,它只包含表的一部分。與表不同的是,保存在視圖中的數據并不是物理存儲的數據,它是由表派生的,派生表被稱為視圖的基本表。視圖的定義存儲在數據庫中。
3、 約束條件(constraint)
約束條件定義數據的完整性和有效性。約束條件為列中的值建立規則。換而言之,如果在某一列上定義了結束條件,則插入這一列的每一個值需要通過約束條件檢查。約束條件是在觸發器和規則上保證數據完整性和有效性的較佳選擇。SQL Server Query Optimizer利用約束條件產生出低成本的查詢計劃。約束條件有如下類型:
· NOT NULL 這個約束條件要求列中不能有NULL值。
· CHECK 為列指定能擁有的值的集合后,檢查約束條件。列中任何在定義之外的數據都為無效數據。有效值集合稱為列的域。
· PRIMARY KEY 主關鍵字是列或列組合,它用來唯一標識一行。
· FOREIGN KEY 用來定義兩個表之間的父子關系。如果一個關鍵字既是一個表的主關鍵字的一部分,同時又是另一個表的主關鍵字,則稱它為外來關鍵字。外來關鍵字用來定義數據的引用完整性。
· UNIQUE 唯一約束條件是指無任何兩行在列中有相同的NON-NULL值。唯一性由主關鍵字保證,但他們不允許NULL值,并且每一個表只能有一個關鍵字。
4、 默認值(default)
默認值是為列定義的值,如果在插入一行時沒有提供某一列的值,則此列使用默認值,默認值可以是以下的一種:
· 常量
· 數學表達式
· 內部函數(Built-in function)
5、 規則(rule)
規則執行和CHECK約束條件同樣的功能。但規則和約束條件不同的是:規則作為獨立的對象存在,它可以用于多個表,而約束條件作為表的一部分存儲。然而,規則是作為向后兼容特點而提供的,建議用戶使用約束條件。
6、 觸發器和存儲過程
觸發器和存儲過程是一個TSQL命令集,它們作為一個對象存儲在數據庫中。
對象命名約定
SQL Server用三段式(three-part)名字標識對象:
<數據庫名>.<所有者名>.<對象名>
前兩部分可以省略,系統有一個默認值。數據庫名的默認值是當前數據庫,所有者名的默認值是數據庫所有者(dbo)。
數據類型
???????任何包含數據的對象都有一個數據類型和它關聯。數據類型是指定對象能包含何種數據的屬性。
???????SQL Server數據類型
數據類型
說??明
同??義
Bit
1位,值為0或1
Int
Integer
4字節,值為-2^31~2^31-1
Smallint
2字節,值為-2^15~2^15-1
Tinyint
1字節,值為0~255
Decimal (p,s)
數字數據,固定精度為P,寬度為S
Numeric
Money
8字節,存放貨幣類型,值為-2^63~2^63-1
Small money
4字節,存放貨幣類型,值為-214748.3648~+214748.3647近似數值數據類型
Float (n)
N在1~24之間,4字節,7位精度
N=1~7為real
N在25~53之間,8字節,15位精度
=8~15為float
Datetime
8字節,描述某天的日期和時刻,值的精確度為1/300秒
Smalldatetime
4字節,描述某天的日期和時刻,精度為分鐘
Cursor
對游標的引用
Timestamp
8字節,存放在數據庫內唯一的數據
Uniqueidentifier
16字節,存放全局唯一標識(GUID)
Char (n)
非unicode字符串的固定長度,n=1~8000
Character (n)
Varchar (n)
可變長度,非unicode字符串n=1~8000
Char varying(n)
Text
服務器代碼頁中可變長度非unicode數據。最大長度為231-1個字符
Nchar
固定長度unicode字符串n=1~4000
National character (n),
National char(n)
Nvarchar
固定長度unicode字符串n=1~4000
National character varying(n)
Ntext
可變長度unicode數據,最大長度為230-1個字符
National text
Binary (n)
固定長度二進制數據,n在1~8000之間,存儲空間為n+4字節
Varbinary (n)
可變長度二進制數據,n=1~8000
Binary varying (n)
Tmage
可變長度二進制數據,大小為0~231-1
注意:
1)????對于數值型數據類型,寬度(scale)是指存儲在小數點后的數字位數,而精度(precision)是指能存儲的包含小數點在內的所有數字位數。
2)????money和small money的存儲寬度為4。
3)????時間戳列值在每一行更新時系統自動更新,時間戳列不能是關鍵字或關鍵字的一部分。
4)????唯一標識數據類型不能使用算術操作符(如+、-等),這種數據類型只能使用相等比較操作。Unicode是所有字符集的一致存儲數據的標準。它要使用兩倍于非Unicode數據存儲的存儲空間。
存取數據
select語句
1. 選擇表中的所有列
“*”對Select語句有特殊意義。它指定表中的所有列,而不用列出列的名字。列的順序和表中的順序相同。
2. 選擇不同的值
如果被選擇列表中的列有重復值,這時“distinct”關鍵字可以用來忽略重復值。
注意: 如果Select list中多于一列,則distinct關鍵字對它們總體有效。如果一列有重復值,而其他列的值是唯一的,則有重復值的一列包含在結果中。
3. 在結果數據集合中對列重命名
結果中列的默認名字是源數據庫中的列名,用戶可以用自己指定的列名來代替默認的列名。
Select AuthorFirstName = au_fname from authors???
--將列名由“au_fname”改成“AuthorFirstName”
4. 選擇計算值
在Select list中可以包含計算值或常量。計算值是在算術表達式的基礎上計算而來的,它可包含在表中的一列或多列。
Select totalSale = price * ytd_sales from titles
條件選擇(Where子句)
使用一個比較或邏輯操作在Where子句中指定過濾條件,來生成表中想得到的行。
1.??比較操作
比較操作能比較數值、字符和日期數據,返回TRUE或FALSE。
比較操作符
<(小于)
>(大于)
=(等于)
<>(不等于)
>=(大于等于)
<=(小于等于)
!=(不等于)
!<(不小于)
!>(不大于)
2.??邏輯操作
邏輯操作測試某些條件是否正確,并根據測試結果返回TRUE或FALSE。
· LIKE 如果操作和指定的字符串相同,則返回TRUE,指定的字符串也可包含通配符。
有通配符的like操作更有用。
????????· “%”規定所有字符串可代替字符“%”的位置。任何在“%”之前或之后的指定字符串視為常量。如:“New%”表示所有以“New”開頭的字符串,“%New”表示以“New”結尾的字符串。
????????· “_”規定任何單個字符可代入“_”的位置。這在只有一個字符不同的相近字符的情況下非常有用。
????????· “[]”規定使用方括號中定義的字符代替一個字符。方括號中可能是獨立的字符(如[ahg]),也可是字符范圍(如[c-i])。
· “[^]”規定方括號中“^”之后的字符為不能用來代入的字符,它可以是獨立字符(如[ahg]),也可是字符范圍(如[c-i])。
注意:可以在一個表達式中組合運用這些通配符。
· BETWEEN 如果操作數在提供的范圍之內,則返回TRUE。
BETWEEN可和NOT操作符一同使用,如果數據在指定范圍之外,則返回TRUE。
注意:BETTEN操作符是指定范圍。例如,BETWEEN A and B表示所有在A和B之間的值,包括A和B。
· IN 如果操作數和任意的指定值相匹配,則IN操作符返回TRUE。指定值可以是一個常量值列表,也可由另外的查詢(稱為子查詢)產生。
????IN操作符也可和NOT操作符聯合使用,如果數據不在指定值中,它返回TRUE。
· AND 它結合兩個表達式,如果兩個表達式都為TRUE,則它返回TRUE,否則返回FALSE。
· OR 它結合兩個表達式,如果兩個表達式中有一個為TRUE,則它返回TRUE,如果兩個都為FALSE,則返回FALSE。
· NOT 它對邏輯操作值求反,它可和大多數邏輯操作聯合使用,對操作返回的值求反。
· SOME|ANY 這兩個操作有相同的格式。它們把操作數和指定值的集合比較。如果操作數與任意指定值的比較返回TRUE,則它返回TRUE。比較操作可以是任意SQL Server定義的比較操作。指定值列表可以由另一個查詢產生。
· ALL ALL操作和SOME及ANY有相似的格式。不同的是,如果所有操作數和指定值的比較返回TRUE,它才返回TRUE。
數據排序
???????ORDER BY子句按指定的順序對數據排序(ordering data)。它要求一個列名字列表或非負整數列表來指定列的位置。分別用ASC代表升序,DESC代表降序,默認為ASC。
限制返回行的數目
???????不使用WHERE子句而限制結果中的行數是可能的。“TOP”子句能按指定數目或百分值來限制行數。
數據分組和計算聚合函數
???????聚合(aggregate)函數計算表中數據的總和。SQL Server提供以下的聚合函數:
???????· AVG 這個函數計算平均值。語法如下:
???????AVG ([ALL | DISTINCT] expression)
???????關鍵字DISTINCT只用來計算不同值的平均值,如果有許多重復值,這些值只計算一次,默認為ALL。
???????Expression可以是涉及一列或多列的算術表達式。
???????· MIN 這個函數查找所提供表達式中的最小值。語法如下:
???????MIN (expression)
???????· MAX 此函數的功能是在提供的表達式中查找最大值。語法如下:
???????MAX (expression)
???????注意: 如果地字符串類型使用MIN和MAX,則輸出依賴于為SQL Server定義的順序。MIN和MAX不能在位上使用。
????· SUM SUM計算所有數據值的和。語法如下:
???????SUM ([ALL | DISTINCT] expression)
???????注意:SUM和AVG只能用于數值數據類型。
????· COUNT 計算表達式值的數目。語法如下:
???????COUNT ([ALL | DISTINCT] expression)
???????COUNT有另一種用法,它可以返回被選擇的行數。
???????如:SELECT NumRows = COUNT (*) FROM titles
???????聚合函數忽略所有空值,但COUNT(*)除外。盡管所有聚合函數的計算基于無空值的情況,然而COUNT(*)計算所有的行(包括有空值的行)。
1.??GROUP BY子句
GROUP BY子句在被定義的數據的基礎上建立比較小的組,并且對每一個組進行聚合函數計算。換句話說,它產生每一組的總體信息。GROUP BY可以把多于一列當成組合列(Grouping Columns)。它總結組合列中不重復值的信息。
使用了GROUP BY子句的選擇列表中只能包含以下項:
· 常量值。
· 組合列。
· 表達式。每個表達式為每組返回一個值(如聚合函數)。如果一列除了在組合列中外,還在選擇列表中,則它有多個值給組合列的每一個不重復值,這種結構類型是不允許的。
2.??GROUP BY和HAVING
HAVING子句用來向使用GROUP BY子句的查詢中增加數據過濾準則。HAVING的用法和SELECT中的WHERE子句一樣。在一個包含GROUP BY子句的查詢中使用WHERE子句是可以的。HAVING和WHERE有相同的語法。HAVING和WHERE的不同這處是:
· 在WHERE子句中,在分組進行以前,去除不滿足條件的行,在HAVING子句中,在分組之后條件被應用。
· HAVING可在條件中包含聚合函數,但WHERE不能。
注意:GROUP BY和HAVING子句不能使用文本或圖像數據類型。
3.??COMPUTE BY子句
COMPUTE BY子句可以得到詳細或總的記錄。它把數據分成較小的組,然后為每組建立詳細記錄結果數據集(象SELECT),它也可為每組產生總的記錄(象GROUP BY)。
在COMPUT BY中,定義BY子句不是必要的。如果沒有定義BY子句,則認為整個表為一個組,并且只有兩個結果數據集產生,一個擁有所有詳細記錄,另一個只有一行,它擁有總記錄。
注意:當在COMPUTE中使用BY時,則要求在所有組合列中包含ORDER BY。
Cube和Rollup操作
????CUBE和ROLLUP操作可比簡單的GROUP BY產生更多的聚合值。在產生交叉標簽報告(cross tab reports)時,這些操作非常有用。如果查詢使用n個組合列,則有2n個計算聚合的組合。
從多個表中訪問數據
????我們已討論了如何訪問單個表中的數據。從多個表中訪問數據也是可能的。從多個表中訪問數據稱為連接表(joining a table)。
1、??CROSS JOIN(笛卡爾積)
CROSS JOIN是簡單地、不加任何約束條件地把表組合。CROSS JOIN后結果的行數是連接前兩個表行數的乘積。如果對兩個分別有好幾千行的表進行連接,則結果是不可想象的。
2、??INNER JOIN
INNER JOIN是組合兩個表最常用的方法。INNER JOIN是基于一個判別式進行的,這個判別式稱為連接條件。連接條件和WHERE子句一起定義。連接條件由來自兩個表中的列組成,并使用一個比較條件來對列的值進行比較。通過比較的值包含在結果數據集中,以下是Inner JOIN的語法:
語法1:(ANSI 92)
Select <select_list>
FROM <table1> INNER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
語法2:
Select <select_list>
FROM <table1>,<table2> WHERE <table1>.<column name> = <table2>.<column name>
在FROM 子句中可為表定義別名,并在任何地方都可用別名代替真名。
注意:如果作為連接條件的列中有空值,則空值不能和任何值匹配,因此結果中不包含有空值的行。
3、??Left Outer JOIN
在Inner JOIN中,只有在兩個表中匹配的行才能在結果數據集中。但在Left Outer JOIN中,所有左邊表中的行都出現在結果數據集中,如果左邊表中的某一行在右邊表中沒有匹配的行,則以空值取代右邊表中的值和它連接。
語法如下:(ANSI 92)
Select <select_list>
FROM <table1> LEFT OUTER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
4、??Right Outer JOIN
Right Out JOIN和Left Outer JOIN相似,不同的是把右邊的表作為外部表(所有右邊表中的行包含在結果數據集中)。
語法如下:
Select <select_list>
FROM <table1> RIGHT OUTER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
5、??Full Outer JOIN
在Full Outer JOIN中,所有兩個表中的行都包含在結果數據集中。
語法如下:
Select <select_list>
FROM <table1> FULL OUTER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
Case語句
????當對不同條件產生不同的結果值時,可使用Case語句。
????Case語句計算所有定義的條件,并按條件是否為真而返回結果。
語法如下:
CASE [<input_expression>]
WHEN <when_expression> THEN <result_expression>
[ELSE <else_expression>]
END
Input_expression是任何有效的SQL Server表達式或布爾表達式。
When_expression是任何有效的SQL Server表達式或布爾表達式。這個表達式和Input_expression比較,如果Input_expression沒有定義,則When_expression應該是一個布爾表達式。
Result_expression是任何有效的SQL Server表達式。如果When_expression和Input_expression的比較返回TRUE(如果定義了Input_expression)或When_expression的值為TRUE,則計算表達式,并返回其結果。否則計算Else_expression中的表達式,并返回其結果。
例如:
SELECT au_fname,au_lname,
State=CASE state
??????????????WHEN ‘CA’ THEN ‘California’
??????????????WHEN ‘KS’ THEN ‘Kansas’
?????????END
FROM authors
UNION
???????UNION語句把兩個或多個查詢的結果組合成一個結果集。
???????語法如下:
???????SELECT <select_list>
???????FROM <table_list>
???????WHERE <join_condition>
???????UNION [ALL]
???????SELECT <table_list>
???????FROM <table_list>
???????WHERE <join_condition>
???????ALL關鍵字指定重復的數據也將包含在最終結果數據集中。如果需要,一個查詢中可以有許多UNION語句。所有Select_list應該有相同數目的列,且是相同或兼容的數據類型。
Go命令???????Go命令用來標志一個查詢批處理(query batch)的結束。查詢批處理是TSQL語句的集合,這些語句集合在一起執行。Go與Osql或SQL Server Query Analyzer一起使用。
管理文本和圖像數據
???????文本和圖像數據類型列可以象其它列一樣包含在SELECT語句的Select_list中。通過SELECT語句檢索的最大文本大小由TEXTSIZE設置來控制。默認的TEXTSIZE的值是4096字節,使用SET TEXTSIZE語句可重新設置。當前的TEXTSIZE設置的值存放在全局變量@@TEXTSIZE中。
???????另一種檢索文本和圖像數據的方法是通過TEXTPTR和READTEXT函數。TEXTPTR函數把列名字作為輸入參數并以二進制格式返回文本指針。
???????這個指針和被稱為偏移量的讀開始指針以及要讀的字節數量一起傳給READTEXT函數,以檢索文本和圖像數據。
修改數據
???????TSQL也提供從數據庫插入、修改、刪除的命令。
插入
???????INSERT命令用來在表中插入數據,語法如下:
???????INSERT [INTO] <table_name> [(column_list)] VALUES (value_list)
???????Value_list是和在Column_list中列相應的值。這些值可以是常量、TSQL變量或SQL Server內部函數。值的順序應和column_list中列的順序相對應。如果沒有定義column_list,則值的順序應和表中列的順序對應。
???????INSERT的Values_list也可通過SELECT語句或一個存儲過程來提供。語法如下:
???????INSERT [INTO] <table_name> [(column_list)]
???????SELECT <select_list> FROM <table_name>
???????INSERT [INTO] <table_name> [(column_list)]
???????EXECUTE <procedure_name>
???????這里的SELECT語句可包含多種連接。如果使用存儲過程,則存儲過程應返回能作為column_list的結果。
???????時間戳(timestamp,又稱時標)值不應被提供。同時,如果列的IDENTITY屬性被定義,則這一列的值也不能提供。這些值都由系統產生。如果列有默認值,則它們的值不被提供,而使用默認值。
修改
???????UPDATE語句用來修改行,語法如下:
???????UPDATE <table_name> SET <column_name> = <value> [,<column_name> = <value>_n]
???????WHERE <search_condition>]
???????Serach_condition是要修改的行應滿足的條件。沒有WHERE子句的UPDATE語句將修改表中的所有行。在UPDATE語句中也可使用連接。
刪除
???????DELETE語句用來從表中刪除行。語法如下:
???????DELETE [FROM] <table_name>
???????[WHERE <search_condition>]???????Serach_condition是刪除行要滿足的條件。一個無條件DELETE語句將刪除表中的所有行。在DELETE語句中也可使用連接。
使用SQL Server開發應用程序
編寫存儲過程與觸發器
???????存儲過程和觸發器是由用戶創建的、駐留在服務器的一組Transact SQL查詢語句。觸發器是系統在特定條件下執行的。存儲過程能夠改善應用程序的性能。當客戶程序需要訪問數據時,一般要經過5個步驟才能訪問到數據:
1)??查詢語句被發送到服務器。
2)??服務器編譯SQL代碼。
3)??優化產生查詢的執行計劃。
4)??數據引擎執行查詢。
5)??結果發回客戶程序。
存儲過程是在創建時編譯的,當存儲過程第一次執行時,SQL Server產生查詢執行計劃并將其存儲進來,以利于將來使用。當通過存儲過程發出一個請求時,上述的第2和第3步就沒有了,這能大大改善系統的性能。即使在第1步上也能提高性能。因為此時發送到服務器的語句只是一條存儲過程的EXECUTE語句,而不是龐大的、復雜的查詢。這種特性能降低網絡的流量。
除了性能方面的改善外,存儲過程還提供了方便地集中維護應用程序的功能。如果將查詢嵌入到應用程序中。而又需要對查詢進行改變,則應用程序需要重新編譯,并重新發布到所有的客戶端。而在存儲過程中,修改對用戶而言是透明的,它只需要在服務器上重新編譯存儲過程。
存儲過程還能提供安全機制,盡管用戶可能無權執行存儲過程中的命令,但它卻可能有權執行存儲過程本身。有時候,系統管理員不會給用戶以數據修改(UPDATE、INSERT和DELETE)的權力。創建的存儲過程卻能進行這些操作。當然用戶需要擁有執行該存儲過程的權力。
建立存儲過程
???????存儲過程可以達到以下目的:
???????· 帶參數。
???????· 返回狀態值。
???????· 調用其它存儲過程。
???????· 在遠程服務器上執行。
???????存儲過程在“sysobjects”系統表中有一個表項,其類型為“P”。存儲過程的文本存儲在“syscomments”系統表中。創建存儲過程需要使用Transact SQL命令CREATE PROCEDURE。
???????例如:
???????USE pubs
???????GO
???????
???????CREATE PROCEDURE ap_GetAuthorsForPublisher
???????AS
???????SELECT a.au_lname,a.au_fname
???????FROM authors a, titleauthor ta, titles t, publishers p
???????WHERE a.au_id = ta.Au_id
???????AND ta.Title_id = t.title_id
???????AND t.pub_id = p.pub_id
???????AND p.pub_name = ’New Moon Books’
???????GO
???????CREATE PROCEDURE語句的語法如下:
???????CREATE PROC[DURE] procedure_name [;number]
??????????????[@parameter_name ][OUTPUT] [,_n] ]
??????????????[WITH {RECOMPILE | ENCRYPTION}]
??????????????[FOR REPLICATION]
???????AS
???????Number是用來對相同名字的過程進行分組的整數。分組是將所有的過程通過drop procedure語句組合到一個分組中。
???????@parameter_name指定參數的名稱。
???????RECOMPILE表示每次執行過程時都要進行編譯。
???????ENCRYPTION表示過程的文本在“syscomments”表中要加密。
???????FOR REPLICATION表示過程不能在提交服務器上執行。
將參數傳遞給存儲過程
???????存儲過程能夠接受參數。
???????注意:過程的參數也可以是用戶定義的數據類型。
給參數一個缺省值
???????用戶還可以為存儲過程中的參數定義缺省值。當在執行時沒有提供所需的參數時,系統就使用缺省值作為參數。如果既沒有定義缺省值,又沒有在執行時提供參數,則SQL Server就會返回一個錯誤。在存儲過程中定義缺省值,并使用一些邏輯檢測是否指定了參數從而采取相應的行動,這是一種很好的習慣。
???????例如:
???????USE pubs
???????GO
???????
???????CREATE PROCEDURE ap_GetAuthorsForPublisher
???????@PublisherName varchar(40) = ‘New Moon Books’
???????AS
???????SELECT a.au_lname,a.au_fname
???????FROM authors a, titleauthor ta, titles t, publishers p
???????WHERE a.au_id = ta.Au_id
???????AND ta.Title_id = t.title_id
???????AND t.pub_id = p.pub_id
???????AND p.pub_name = @PublisherName
???????GO
建立存儲過程體
???????存儲過程邏輯駐留在存儲過程體中。一個存儲過程體中可以包含任意條Transact SQL語句。下面的Transact SQL語句不能在任何存儲過程體中出現:
???????· CREATE DEFAULT
???????· CREATE TRIGGER
???????· CREATE PROCEDURE
???????· CREATE VIEW
???????· CREATE RULE
1、??局部變量
局部變量保持存儲過程中間值。當一個值在存儲過程中需要多次,或者某個查詢的結果需要在隨后的查詢中使用時,需要使用局部變量。在這些情形下,值被存儲在局部變量中,并可用于將來的使用。本地變量的名稱以“@”符號開頭。變量的名稱可以包含字符和數值。局部變量在使用前需要進行類型聲明。對局部變量進行賦值需要使用SELECT語句。SELECT可以從一個表中檢索出值并將其賦給某個變量,也可以給變量賦一個常量值。一個簡單的SELECT語句可以給多個局部變量賦值。
例如:
DECLARE @var1 integer, @var2 varchar(20)
SELECT @var1 = 32,
???????????@var2 = ‘MyAge’
如果從SELECT查詢中沒有返回任何數據,而SELECT又要將數據的值賦予局部變量,則該局部變量的值將不會發生改變。
2、??條件詞句
存儲過程中提供的條件語句包括:
· IF……ELSE語句。
· WHILE語句。
1)??IF……ELSE語句。在該語句中包含三個部分:布爾運算表達式,IF語句塊和ELSE語句塊。語法如下:
IF (boolen_expr)
??{statements}
ELSE
??{statements}
在IF或ELSE語句塊中可以有多條語句,這種情形下,需要語句BEGIN和END來標志語句塊。
2)??WHILE語句。WHILE語句用于處理直到某個條件為TRUE前重復執行的語句。語法如下:
WHILE (boolen_expr)
??BEGIN
??statement(s)
BREAK
Statement(s)
CONTINUE
??????????????END
????????????BEGIN和END語句標志循環體。BREAK語句結束循環的執行(即走到END語句之后)。CONTINUE語句將控制處理過程回到循環的開始處(即BEGIN語句的右邊)。
????????????注意:如果有兩個或多個WHILE循環被嵌套,則內部的BREAK退出的是次外層的循環。內部循環結束之后的所有語句在內部循環執行之后才能繼續執行。
3、??GOTO語句
在存儲過程的執行中,語句是順序執行的。GOTO語句則是用來打破這種語句執行的順序,它立即跳到某條語句上執行,而這條語句往往不緊跟在前一語句之后。GOTO語句與一個標志(Label)一起使用,該標志用來標識一條語句。
例如:
USE pubs
GO
DECLARE @num int
SELECT
IF @num = 0
???????GOTO Err
ELSE
???????BEGIN
???????PRINT ‘authors found’
???????SELECT * FROM authors
???????GOTO Last
???????END
Err: PRINT ‘no authors found’
Last: PRINT ‘Finish execution’
GO
4、??RETURN語句
RETURN語句用于無條件的退出存儲過程。RETURN之后的任何語句都不再執行。RETURN語句可以給調用語句返回一個值,但不能返回NULL值。SQL Server經常為存儲過程返回一個狀態值。如果成功地執行,則返回一個0,如果出現了錯誤,則返回一個為負數的錯誤碼。
存儲過程返回的錯誤碼
值
說????????明
值
說????????明
0
過程執行成功
-8
發生了非致命的內部問題
-1
漏掉了對象
-9
達到了系統極限
-2
發生了數據類型錯誤
-10
發生了致命的內部不一致錯誤
-3
該處理被選擇成了死鎖的犧牲者
-11
發生了致命的內部不一致錯誤
-4
發生了權限錯誤
-12
表或索引被破壞
-5
發生了語法錯誤
-13
數據庫被破壞
-6
發生了混雜的用戶錯誤
-14
發生了硬件錯誤
-7
資源錯誤,如空間不夠等
5、??使用游標(CURSOR)在需要一行一行處理時,游標十分有用。游標可以打開一個結果集合(按照指定的標準選擇的行),并提供在結果集中一行一行處理的功能。基于游標的類型,可以對其進行回滾或者前進。在使用游標時需要5個步驟:
i.??????????????聲明游標
在這一步中,需要指定游標的屬性和根據要求產生的結果集。有兩種方法可以指定一個游標。
形式1??(ANSI 92)
DECLARE cursor_name [INSENSITIVE] [SCROLL] CURSOR
FOR select_statement
[FOR {READ ONLY | UPDATE ][OF column_list]}]
形式2
DECLARE cursor_name CURSOR
[LOCAL | GLOBAL]
[FORWARD_ONLY | SCROLL]
[STATIC | KEYSET | DYNAMIC]
[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]
FOR select_statement
[FOR {READ ONLY | UPDATE ][OF column_list]}]
INSENSITIVE關鍵字指明要為檢索到的結果集建立一個臨時拷貝,以后的數據從這個臨時拷貝中獲取。如果在后來游標處理的過程中,原有基表中數據發生了改變,那么它們對于該游標而言是不可見的。這種不敏感的游標不允許數據更改。
SCROLL關鍵字指明游標可以在任意方向上滾動。所有的fetch選項(first、last、next、relative、absolute)都可以在游標中使用。如果忽略該選項,則游標只能向前滾動(next)。
Select_statement指明SQL語句建立的結果集。Transact SQL語句COMPUTE、COMPUTE BY、FOR BROWSE和INTO在游標聲明的選擇語句中不允許使用。
READ ONLY指明在游標結果集中不允許進行數據修改。
UPDATE關鍵字指明游標的結果集可以修改。
OF column_list指明結果集中可以進行修改的列。缺省情況下(使用UPDATE關鍵字),所有的列都可進行修改。
LOCAL關鍵字指明游標是局部的,它只能在它所聲明的過程中使用。
GLOBAL關鍵字使得游標對于整個連接全局可見。全局的游標在連接激活的任何時候都是可用的。只有當連接結束時,游標才不再可用。
FORWARD_ONLY指明游標只能向前滾動。
STATIC的游標與INSENSITIVE的游標是相同的。
KEYSET指明選取的行的順序。SQL Server將從結果集中創建一個臨時關鍵字集。如果對數據庫的非關鍵字列進行了修改,則它們對游標是可見的。因為是固定的關鍵字集合,所以對關鍵字列進行修改或新插入列是不可見的。
DYNAMIC指明游標將反映所有對結果集的修改。
SCROLL_LOCK是為了保證游標操作的成功,而對修改或刪除加鎖。
OPTIMISTIC指明哪些通過游標進行的修改或者刪除將不會成功。
注意:
· 如果在SELECT語句中使用了DISTINCT、UNION、GROUP BY語句,且在選擇中包含了聚合表達式,則游標自動為INSENSITIVE的游標。
· 如果基表沒有唯一的索引,則游標創建成INSENSITIVE的游標。
· 如果SELECT語句包含了ORDER BY,而被ORDER BY的列并非唯一的行標識,則DYNAMIC游標將轉換成KEYSET游標。如果KEYSET游標不能打開,則將轉換成INSENSITIVE游標。使用SQL ANSI-92語法定義的游標同樣如此,只是沒有INSENSITIVE關鍵字而已。
???????????????????????ii.??????????????打開游標
打開游標就是創建結果集。游標通過DECLARE語句定義,但其實際的執行是通過OPEN語句。語法如下:
OPEN { { [GLOBAL] cursor_name } | cursor_variable_name}
GLOBAL指明一個全局游標。
Cursor_name是被打開的游標的名稱。
Cursor_variable_name是所引用游標的變量名。該變量應該為游標類型。
在游標被打開之后,系統變量@@cursor_rows可以用來檢測結果集的行數。@@cursor_rows為負數時,表示游標正在被異步遷移,其絕對值(如果@@cursor_rows為-5,則絕對值為5)為當前結果集的行數。異步游標使用戶在游標被完全遷移時仍然能夠訪問游標的結果。
??????????????????????iii.??????????????從游標中取值
在從游標中取值的過程中,可以在結果集中的每一行上來回移動和處理。如果游標定義成了可滾動的(在聲明時使用SCROLL關鍵字),則任何時候都可取出結果集中的任意行。對于非滾動的游標,只能對當前行的下一行實施取操作。結果集可以取到局部變量中。Fetch命令的語法如下:
FETCH [NEXT | PRIOR| FIRST | LAST | ABSOLUTE {n | @nvar} | RELATIVE {n | @nvar}]
FROM [GLOBAL] cursor_name} | cursor_variable_name}
[INTO @variable_name ][,……n]]
NEXT指明從當前行的下一行取值。
PRIOR指明從當前行的前一行取值。
FIRST是結果集的第一行。
LAST是結果集的最后一行。
ABSOLUTE n表示結果集中的第n行,該行數同樣可以通過一個局部變量傳播。行號從0開始,所以n為0時不能得到任何行。
RELATIVE n表示要取出的行在當前行的前n行或后n行的位置上。如果該值為正數,則要取出的行在當前行前n行的位置上,如果該值為負數,則返回當前行的后n行。
INTO @cursor_variable_name表示游標列值存儲的地方的變量列表。該列表中的變量數應該與DECLARE語句中選擇語句所使用的變量數相同。變量的數據類型也應該與被選擇列的數據類型相同。直到下一次使用FETCH語句之前,變量中的值都會一直保持。
每一次FETCH的執行都存儲在系統變量@@fetch_status中。如果FETCH成功,則@@fetch_status被設置成0。@@fetch_status為-1表示已經到達了結果集的一部分(例如,在游標被打開之后,基表中的行被刪除)。@@fetch_status可以用來構造游標處理的循環。
例如:
DECLARE @iname char(20), @fname char(20)
OPEN author_cur
FETCH FIRST FROM author_cur INTO @iname, @fname
WHILE @@fetch_status = 0
BEGIN
IF @fname = ‘Albert’
PRINT “Found Albert Ringer”
ELSE
Print “Other Ringer”
FETCH NEXT FROM author_cur INTO @iname, @fname
END
?????????????????????iv.??????????????關閉游標
CLOSE語句用來關閉游標并釋放結果集。游標關閉之后,不能再執行FETCH操作。如果還需要使用FETCH語句,則要重新打開游標。語法如下:
CLOSE [GLOBAL] cursor_name | cursor_variable_name
???????????????????????v.??????????????釋放游標
游標使用不再需要之后,要釋放游標。DEALLOCATE語句釋放數據結構和游標所加的鎖。語法如下:
DEALLOCATE [GLOBAL] cursor_name | cursor_variable_name
???????下面給出游標的一個完整的例子:
???????USE master
???????GO
???????CREATE PROCEDURE sp_BuildIndexes
???????AS
???????DECLARE @TableName sysname, @msg varchar(100), @cmd varchar(100)
???????DECLARE table_cur CURSOR FOR
???????SELECT name FROM sysobjects WHERE type=’u’
???????OPEN table_cur
???????FETCH NEXT FROM table_cur INTO @TableName
???????
???????WHILE @@fetch_status = 0
???????BEGIN
??????????????IF @@fetch_status = -2
?????????????????????CONTINUE
??????????????SELECT @msg = “Building indexes for table”+@TableName+”…”
??????????????PRINT @msg
??????????????SELECT @cmd = “DBCC DBREINDEX (‘”+@TableName+”')”
??????????????EXEC (@cmd)
??????????????PRINT “????“
??????????????FETCH NEXT FROM table_cur INTO @TableName
???????END
???????DEALLOCATE table_cur
???????GO
???????下面的腳本將為PUBS數據庫執行sp_BuildIndexes
???????USE pubs
???????GO
???????EXEC ap_BuildIndexes
???????注意:上面也是創建用戶定義的系統存儲過程的示例。
使用臨時表
???????臨時表是在TempDB中創建的表。臨時表的名稱都以“#”開頭。臨時表的范圍為創建臨時表的連接。因為,臨時表不能在兩個連接之間共享,一旦連接關閉,臨時表就會被丟棄。如果臨時表被創建于存儲過程之中,則臨時表的范圍在存儲過程之中,或者被該存儲過程調用的任何存儲過程之中。如果需要在連接之間共享臨時表,則需要使用全局的臨時表。全局的臨時表以“##”符號開頭,它將一直存在于數據庫中,直到SQL Server重新啟動。一旦這類臨時表創建之后,所有的用戶都可以訪問到。在臨時表上不能明確地指明權限。???????臨時表提供了存儲中間結果的能力。有時候,臨時表還能通過將一個復雜的查詢分解成兩個查詢而獲得性能的改善。這可以通過首先將第一個查詢的結果存在臨時表中,然后在第二個查詢中使用臨時表來實現。當一個大表中的某個子集在一個在座過程中使用多次時,建議使用臨時表。在這種情況下,在臨時表中保持數據的子集,以在隨后的連接中使用,這樣能大大改善性能。還可以在臨時表中創建索引。
存儲過程中返回結果
???????從存儲過程中返回結果有三種方式:
1、??返回結果集
這是客戶端應用程序返回結果的最通用的方法。結果集是通過使用SELECT語句選擇數據產生的。結果集可以從永久表、臨時表或局部變量中產生。將結果返回到另一個存儲過程不是一種有效的方法。存儲過程不能訪問另一個存儲過程建立的結果集。
例如從永久表中返回結果集:
USE pubs
GO
CREATE PROCEDURE ap_CreateResultFromPermtable
AS
SELECT au_iname FROM authors
GO
例如從局部變量中創建結果集:
USE pubs
GO
CREATE PROCEDURE ap_CreateResultFromVariable
AS
DECLARE @au_iname char(20)
SELECT @au_iname = au_iname FROM authors
WHERE au_id = ‘172-32-1176’
SELECT @au_id
GO
2、??設置OUTPUT參數的值
輸出參數經常用來從存儲過程中檢索出結果。如果某個參數在傳輸到存儲過程中時被定義成OUTPUT,則對該參數的任何修改在退出存儲之后仍然有效。
例如:
USE pubs
GO
CREATE PROCEDURE ap_SetOutputVar @count integer OUTPUT
AS
SELECT @count = count(*) FROM authors
GO
從輸出參數中檢索出值:
USE pubs
GO
CREATE PROCEDURE ap_GetOutputVar
AS
DECLARE @num integer
EXECUTE ap_SetOutputVar @num OUTPUT
PRINT “the count is”+convert(char,@num)
GO
· 將游標使用成OUTPUT參數。游標可以使用OUTPUT(輸出)參數,但不能使用成輸入參數。也就是說,游標可以作為結果返回,但卻不能傳輸到過程中去。當游標被用作參數時,需要限定其為OUTPUT和VARYING。VARYING關鍵字指出該結果集要用來支持輸出參數。這樣就提供了將結果集返回到調用過程的能力。
例如:
USE pubs
GO
CREATE PROCEDURE GetTitleCount @count_cursor CURSOR VARYING OUTPUT
AS
SET @count_cursor = CURSOR
FOR
SELECT au_id,count(*)
FROM titleauthors
GROUP BY au_id
OPEN @count_cursor
GO
3、??通過RETURN參數返回狀態
這是一種從存儲過程返回錯誤碼的方法。存儲過程總是返回一個狀態值,用戶也可以使用RETURN語句返回自己的狀態。
例如:
USE pubs
GO
CREATE PROCEDURE ap_SetReturnStatus
AS
DECLARE @count integer
SELECT @count = count(*) FROM authors
IF @count = 0
RETURN(1)
ELSE
RETURN (0)
GO
例如檢索出返回的狀態:
USE pubs
GO
CREATE PROCEDURE ap_GetReturnStatus
AS
DECLARE @status integer
EXECUTE @status = ap_SetReturnStatus
IF @status = 1
PRINT “No rows found”
ELSE
PRINT “successful”
GO
在存儲過程中進行錯誤處理
???????如同其它程序一樣,在存儲過程中進行錯誤處理是非常重要的。系統變更@@error在執行每一個Transact SQL語句之后都會得到一個值。對于成功的執行,@@error的值為0,如果出現錯誤,則@@error中將包含錯誤信息。@@error系統變量對存儲過程的錯誤處理是非常重要的。
???????注意:為了防止錯誤,@@error所能設置的值在sysmessages表的“error”中反映了出來。
在存儲過程中的錯誤有兩種類型:
1、????數據庫相關的錯誤
這些錯誤是由數據庫的不一致性引起的,系統使用非0的@@error值表示特定的數據庫問題。在Transact SQL執行之后,可以通過@@error獲得所出現的錯誤。如果發現@@error不為0,則必須采取必要的行動,大多數情況下,存儲將不再繼續進行處理而返回。下面的示例展示了典型的獲取數據庫錯誤的方法。該過程將錯誤代碼放置到輸出變量中,這樣,調用程序就能夠訪問到。
USE pubs
GO
CREATE PROCEDURE ap_TrapDatabaseError @return_code integer OUTPUT
AS
UPDATE authors SET au_iname = “Jackson”
WHERE au_iname = “Smith”
IF @@error <> 0
BEGIN
???????SELECT @return_code = @@error
???????RETURN
END
ELSE
???????@return_code = 0
GO
2、????業務邏輯錯誤
這些錯誤是由于違反了業務規則而引起的。要獲取這些錯誤,首先需要定義業務規則,基于這些規則,需要在存儲過程中增加必要的錯誤檢測代碼。人們經常使用RAISERROR語句通報這些錯誤。RAISERROR提供了返回用戶定義錯誤及將@@error變量設置成用戶定義錯誤號的能力。錯誤消息可以被動態地建立,或者基于錯誤號從“sysmessages”表中檢索到。一旦出現了錯誤,錯誤就會以一種服務器錯誤消息的方式返回到客戶機。下面是RAISERROR命令的語法:
RAISERROR (msg_id | msg_str, severity, state
[, argument ][,…n]])
[WITH options]
Msg_id指明用戶定義消息的id,該消息存儲在“sysmessages”系統表中。
Msg_str用于動態創建消息的消息字符串。這與C語言中的“printf”非常相似。
Severity定義用戶賦值的錯誤消息嚴重程度。
State是從1到127的任意整數值,它表示錯誤的調用狀態信息。負數的state值將缺省為1。
OPTIONS指明錯誤的定制選項。OPTIONS的有效值如下:
1)??LOG。
將錯誤記錄到服務器錯誤日志和NT事件日志中。該選項需要消息帶有從19到25的嚴重程度。而只有系統管理員才能發出這種消息。
2)??NOWAIT。
將消息立即發送到客戶端服務器。
3)??SETERROR。
不管其嚴重級別如何,將@@error的值設置為msg_id或5000。
遠程過程調用
???????SQL Server提供了調用駐留在不同服務器上的存儲過程的能力。調用這樣的存儲過程稱謂遠程存儲過程調用。為了使得調用能從一個SQL Server轉移到另一個服務器,兩個服務器應該相互定義成對方的有效遠程服務器。
???????設置遠程服務器的配置:
???????· 擴展某個服務器的組。
???????· 右擊該服務器并點擊“Properties”。
???????· 設置選項“Allow other SQL Servers to connect remotely to this SQL server via RPC”。
???????· 設置“Query time out”選項的值,該值指定從一個查詢處理返回所能等待的秒數。缺省值為0,表示允許無限的等待時間。
???????· 設置完成配置選項之后,點擊“OK”。
???????· 重新啟動服務器之后,修改將會生效。
???????· 在另一臺遠程服務器上重復相同的步驟。
???????調用遠程存儲過程需要指明服務器的名稱,后帶數據庫的名稱和擁有者的名稱。下面是在不同的服務器(Server2)上調用一個存儲過程的示例。
Exec server2.pubs.dbo.myproc
豆豆的后話:
???????這里只是粗淺的介紹了SQL Server常用的知識,對象也是基于SQL Server數據庫編寫應用程序的編程人員,而非數據庫管理者。但對于應用程序編程者,了解數據庫的管理也是非常有用的。建議在以后的時間自行去了解數據庫的管理,這對于優化程序也是相當有用的。
————————全文完—————————
它是SQL Server的查詢語言。提供以下命令:
· 創建和數據庫對象。
· 訪問和修改數據。
· 數據聚合(aggregation,又稱聚集)。
· 實施安全措施。
數據庫對象
???????數據庫對象是數據庫中的物理對象。這些對象擁有唯一的名字,并保存數據和數據關系信息。SQL Server定義了如下幾種對象:
1、 表(table)
表是用來存儲數據的兩維數組,它有行和列。列也稱為表屬性或字段,表中的每一列擁有唯一的名字,每一列包含具體的數據類型,這個數據類型由列中的數據類型定義。
2、 視圖(view)
視圖是虛擬的表,它只包含表的一部分。與表不同的是,保存在視圖中的數據并不是物理存儲的數據,它是由表派生的,派生表被稱為視圖的基本表。視圖的定義存儲在數據庫中。
3、 約束條件(constraint)
約束條件定義數據的完整性和有效性。約束條件為列中的值建立規則。換而言之,如果在某一列上定義了結束條件,則插入這一列的每一個值需要通過約束條件檢查。約束條件是在觸發器和規則上保證數據完整性和有效性的較佳選擇。SQL Server Query Optimizer利用約束條件產生出低成本的查詢計劃。約束條件有如下類型:
· NOT NULL 這個約束條件要求列中不能有NULL值。
· CHECK 為列指定能擁有的值的集合后,檢查約束條件。列中任何在定義之外的數據都為無效數據。有效值集合稱為列的域。
· PRIMARY KEY 主關鍵字是列或列組合,它用來唯一標識一行。
· FOREIGN KEY 用來定義兩個表之間的父子關系。如果一個關鍵字既是一個表的主關鍵字的一部分,同時又是另一個表的主關鍵字,則稱它為外來關鍵字。外來關鍵字用來定義數據的引用完整性。
· UNIQUE 唯一約束條件是指無任何兩行在列中有相同的NON-NULL值。唯一性由主關鍵字保證,但他們不允許NULL值,并且每一個表只能有一個關鍵字。
4、 默認值(default)
默認值是為列定義的值,如果在插入一行時沒有提供某一列的值,則此列使用默認值,默認值可以是以下的一種:
· 常量
· 數學表達式
· 內部函數(Built-in function)
5、 規則(rule)
規則執行和CHECK約束條件同樣的功能。但規則和約束條件不同的是:規則作為獨立的對象存在,它可以用于多個表,而約束條件作為表的一部分存儲。然而,規則是作為向后兼容特點而提供的,建議用戶使用約束條件。
6、 觸發器和存儲過程
觸發器和存儲過程是一個TSQL命令集,它們作為一個對象存儲在數據庫中。
對象命名約定
SQL Server用三段式(three-part)名字標識對象:
<數據庫名>.<所有者名>.<對象名>
前兩部分可以省略,系統有一個默認值。數據庫名的默認值是當前數據庫,所有者名的默認值是數據庫所有者(dbo)。
數據類型
???????任何包含數據的對象都有一個數據類型和它關聯。數據類型是指定對象能包含何種數據的屬性。
???????SQL Server數據類型
數據類型
說??明
同??義
Bit
1位,值為0或1
Int
Integer
4字節,值為-2^31~2^31-1
Smallint
2字節,值為-2^15~2^15-1
Tinyint
1字節,值為0~255
Decimal (p,s)
數字數據,固定精度為P,寬度為S
Numeric
Money
8字節,存放貨幣類型,值為-2^63~2^63-1
Small money
4字節,存放貨幣類型,值為-214748.3648~+214748.3647近似數值數據類型
Float (n)
N在1~24之間,4字節,7位精度
N=1~7為real
N在25~53之間,8字節,15位精度
=8~15為float
Datetime
8字節,描述某天的日期和時刻,值的精確度為1/300秒
Smalldatetime
4字節,描述某天的日期和時刻,精度為分鐘
Cursor
對游標的引用
Timestamp
8字節,存放在數據庫內唯一的數據
Uniqueidentifier
16字節,存放全局唯一標識(GUID)
Char (n)
非unicode字符串的固定長度,n=1~8000
Character (n)
Varchar (n)
可變長度,非unicode字符串n=1~8000
Char varying(n)
Text
服務器代碼頁中可變長度非unicode數據。最大長度為231-1個字符
Nchar
固定長度unicode字符串n=1~4000
National character (n),
National char(n)
Nvarchar
固定長度unicode字符串n=1~4000
National character varying(n)
Ntext
可變長度unicode數據,最大長度為230-1個字符
National text
Binary (n)
固定長度二進制數據,n在1~8000之間,存儲空間為n+4字節
Varbinary (n)
可變長度二進制數據,n=1~8000
Binary varying (n)
Tmage
可變長度二進制數據,大小為0~231-1
注意:
1)????對于數值型數據類型,寬度(scale)是指存儲在小數點后的數字位數,而精度(precision)是指能存儲的包含小數點在內的所有數字位數。
2)????money和small money的存儲寬度為4。
3)????時間戳列值在每一行更新時系統自動更新,時間戳列不能是關鍵字或關鍵字的一部分。
4)????唯一標識數據類型不能使用算術操作符(如+、-等),這種數據類型只能使用相等比較操作。Unicode是所有字符集的一致存儲數據的標準。它要使用兩倍于非Unicode數據存儲的存儲空間。
存取數據
select語句
1. 選擇表中的所有列
“*”對Select語句有特殊意義。它指定表中的所有列,而不用列出列的名字。列的順序和表中的順序相同。
2. 選擇不同的值
如果被選擇列表中的列有重復值,這時“distinct”關鍵字可以用來忽略重復值。
注意: 如果Select list中多于一列,則distinct關鍵字對它們總體有效。如果一列有重復值,而其他列的值是唯一的,則有重復值的一列包含在結果中。
3. 在結果數據集合中對列重命名
結果中列的默認名字是源數據庫中的列名,用戶可以用自己指定的列名來代替默認的列名。
Select AuthorFirstName = au_fname from authors???
--將列名由“au_fname”改成“AuthorFirstName”
4. 選擇計算值
在Select list中可以包含計算值或常量。計算值是在算術表達式的基礎上計算而來的,它可包含在表中的一列或多列。
Select totalSale = price * ytd_sales from titles
條件選擇(Where子句)
使用一個比較或邏輯操作在Where子句中指定過濾條件,來生成表中想得到的行。
1.??比較操作
比較操作能比較數值、字符和日期數據,返回TRUE或FALSE。
比較操作符
<(小于)
>(大于)
=(等于)
<>(不等于)
>=(大于等于)
<=(小于等于)
!=(不等于)
!<(不小于)
!>(不大于)
2.??邏輯操作
邏輯操作測試某些條件是否正確,并根據測試結果返回TRUE或FALSE。
· LIKE 如果操作和指定的字符串相同,則返回TRUE,指定的字符串也可包含通配符。
有通配符的like操作更有用。
????????· “%”規定所有字符串可代替字符“%”的位置。任何在“%”之前或之后的指定字符串視為常量。如:“New%”表示所有以“New”開頭的字符串,“%New”表示以“New”結尾的字符串。
????????· “_”規定任何單個字符可代入“_”的位置。這在只有一個字符不同的相近字符的情況下非常有用。
????????· “[]”規定使用方括號中定義的字符代替一個字符。方括號中可能是獨立的字符(如[ahg]),也可是字符范圍(如[c-i])。
· “[^]”規定方括號中“^”之后的字符為不能用來代入的字符,它可以是獨立字符(如[ahg]),也可是字符范圍(如[c-i])。
注意:可以在一個表達式中組合運用這些通配符。
· BETWEEN 如果操作數在提供的范圍之內,則返回TRUE。
BETWEEN可和NOT操作符一同使用,如果數據在指定范圍之外,則返回TRUE。
注意:BETTEN操作符是指定范圍。例如,BETWEEN A and B表示所有在A和B之間的值,包括A和B。
· IN 如果操作數和任意的指定值相匹配,則IN操作符返回TRUE。指定值可以是一個常量值列表,也可由另外的查詢(稱為子查詢)產生。
????IN操作符也可和NOT操作符聯合使用,如果數據不在指定值中,它返回TRUE。
· AND 它結合兩個表達式,如果兩個表達式都為TRUE,則它返回TRUE,否則返回FALSE。
· OR 它結合兩個表達式,如果兩個表達式中有一個為TRUE,則它返回TRUE,如果兩個都為FALSE,則返回FALSE。
· NOT 它對邏輯操作值求反,它可和大多數邏輯操作聯合使用,對操作返回的值求反。
· SOME|ANY 這兩個操作有相同的格式。它們把操作數和指定值的集合比較。如果操作數與任意指定值的比較返回TRUE,則它返回TRUE。比較操作可以是任意SQL Server定義的比較操作。指定值列表可以由另一個查詢產生。
· ALL ALL操作和SOME及ANY有相似的格式。不同的是,如果所有操作數和指定值的比較返回TRUE,它才返回TRUE。
數據排序
???????ORDER BY子句按指定的順序對數據排序(ordering data)。它要求一個列名字列表或非負整數列表來指定列的位置。分別用ASC代表升序,DESC代表降序,默認為ASC。
限制返回行的數目
???????不使用WHERE子句而限制結果中的行數是可能的。“TOP”子句能按指定數目或百分值來限制行數。
數據分組和計算聚合函數
???????聚合(aggregate)函數計算表中數據的總和。SQL Server提供以下的聚合函數:
???????· AVG 這個函數計算平均值。語法如下:
???????AVG ([ALL | DISTINCT] expression)
???????關鍵字DISTINCT只用來計算不同值的平均值,如果有許多重復值,這些值只計算一次,默認為ALL。
???????Expression可以是涉及一列或多列的算術表達式。
???????· MIN 這個函數查找所提供表達式中的最小值。語法如下:
???????MIN (expression)
???????· MAX 此函數的功能是在提供的表達式中查找最大值。語法如下:
???????MAX (expression)
???????注意: 如果地字符串類型使用MIN和MAX,則輸出依賴于為SQL Server定義的順序。MIN和MAX不能在位上使用。
????· SUM SUM計算所有數據值的和。語法如下:
???????SUM ([ALL | DISTINCT] expression)
???????注意:SUM和AVG只能用于數值數據類型。
????· COUNT 計算表達式值的數目。語法如下:
???????COUNT ([ALL | DISTINCT] expression)
???????COUNT有另一種用法,它可以返回被選擇的行數。
???????如:SELECT NumRows = COUNT (*) FROM titles
???????聚合函數忽略所有空值,但COUNT(*)除外。盡管所有聚合函數的計算基于無空值的情況,然而COUNT(*)計算所有的行(包括有空值的行)。
1.??GROUP BY子句
GROUP BY子句在被定義的數據的基礎上建立比較小的組,并且對每一個組進行聚合函數計算。換句話說,它產生每一組的總體信息。GROUP BY可以把多于一列當成組合列(Grouping Columns)。它總結組合列中不重復值的信息。
使用了GROUP BY子句的選擇列表中只能包含以下項:
· 常量值。
· 組合列。
· 表達式。每個表達式為每組返回一個值(如聚合函數)。如果一列除了在組合列中外,還在選擇列表中,則它有多個值給組合列的每一個不重復值,這種結構類型是不允許的。
2.??GROUP BY和HAVING
HAVING子句用來向使用GROUP BY子句的查詢中增加數據過濾準則。HAVING的用法和SELECT中的WHERE子句一樣。在一個包含GROUP BY子句的查詢中使用WHERE子句是可以的。HAVING和WHERE有相同的語法。HAVING和WHERE的不同這處是:
· 在WHERE子句中,在分組進行以前,去除不滿足條件的行,在HAVING子句中,在分組之后條件被應用。
· HAVING可在條件中包含聚合函數,但WHERE不能。
注意:GROUP BY和HAVING子句不能使用文本或圖像數據類型。
3.??COMPUTE BY子句
COMPUTE BY子句可以得到詳細或總的記錄。它把數據分成較小的組,然后為每組建立詳細記錄結果數據集(象SELECT),它也可為每組產生總的記錄(象GROUP BY)。
在COMPUT BY中,定義BY子句不是必要的。如果沒有定義BY子句,則認為整個表為一個組,并且只有兩個結果數據集產生,一個擁有所有詳細記錄,另一個只有一行,它擁有總記錄。
注意:當在COMPUTE中使用BY時,則要求在所有組合列中包含ORDER BY。
Cube和Rollup操作
????CUBE和ROLLUP操作可比簡單的GROUP BY產生更多的聚合值。在產生交叉標簽報告(cross tab reports)時,這些操作非常有用。如果查詢使用n個組合列,則有2n個計算聚合的組合。
從多個表中訪問數據
????我們已討論了如何訪問單個表中的數據。從多個表中訪問數據也是可能的。從多個表中訪問數據稱為連接表(joining a table)。
1、??CROSS JOIN(笛卡爾積)
CROSS JOIN是簡單地、不加任何約束條件地把表組合。CROSS JOIN后結果的行數是連接前兩個表行數的乘積。如果對兩個分別有好幾千行的表進行連接,則結果是不可想象的。
2、??INNER JOIN
INNER JOIN是組合兩個表最常用的方法。INNER JOIN是基于一個判別式進行的,這個判別式稱為連接條件。連接條件和WHERE子句一起定義。連接條件由來自兩個表中的列組成,并使用一個比較條件來對列的值進行比較。通過比較的值包含在結果數據集中,以下是Inner JOIN的語法:
語法1:(ANSI 92)
Select <select_list>
FROM <table1> INNER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
語法2:
Select <select_list>
FROM <table1>,<table2> WHERE <table1>.<column name> = <table2>.<column name>
在FROM 子句中可為表定義別名,并在任何地方都可用別名代替真名。
注意:如果作為連接條件的列中有空值,則空值不能和任何值匹配,因此結果中不包含有空值的行。
3、??Left Outer JOIN
在Inner JOIN中,只有在兩個表中匹配的行才能在結果數據集中。但在Left Outer JOIN中,所有左邊表中的行都出現在結果數據集中,如果左邊表中的某一行在右邊表中沒有匹配的行,則以空值取代右邊表中的值和它連接。
語法如下:(ANSI 92)
Select <select_list>
FROM <table1> LEFT OUTER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
4、??Right Outer JOIN
Right Out JOIN和Left Outer JOIN相似,不同的是把右邊的表作為外部表(所有右邊表中的行包含在結果數據集中)。
語法如下:
Select <select_list>
FROM <table1> RIGHT OUTER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
5、??Full Outer JOIN
在Full Outer JOIN中,所有兩個表中的行都包含在結果數據集中。
語法如下:
Select <select_list>
FROM <table1> FULL OUTER JOIN <table2>
ON <table1>.<column name> = <table2>.<column name>
Case語句
????當對不同條件產生不同的結果值時,可使用Case語句。
????Case語句計算所有定義的條件,并按條件是否為真而返回結果。
語法如下:
CASE [<input_expression>]
WHEN <when_expression> THEN <result_expression>
[ELSE <else_expression>]
END
Input_expression是任何有效的SQL Server表達式或布爾表達式。
When_expression是任何有效的SQL Server表達式或布爾表達式。這個表達式和Input_expression比較,如果Input_expression沒有定義,則When_expression應該是一個布爾表達式。
Result_expression是任何有效的SQL Server表達式。如果When_expression和Input_expression的比較返回TRUE(如果定義了Input_expression)或When_expression的值為TRUE,則計算表達式,并返回其結果。否則計算Else_expression中的表達式,并返回其結果。
例如:
SELECT au_fname,au_lname,
State=CASE state
??????????????WHEN ‘CA’ THEN ‘California’
??????????????WHEN ‘KS’ THEN ‘Kansas’
?????????END
FROM authors
UNION
???????UNION語句把兩個或多個查詢的結果組合成一個結果集。
???????語法如下:
???????SELECT <select_list>
???????FROM <table_list>
???????WHERE <join_condition>
???????UNION [ALL]
???????SELECT <table_list>
???????FROM <table_list>
???????WHERE <join_condition>
???????ALL關鍵字指定重復的數據也將包含在最終結果數據集中。如果需要,一個查詢中可以有許多UNION語句。所有Select_list應該有相同數目的列,且是相同或兼容的數據類型。
Go命令???????Go命令用來標志一個查詢批處理(query batch)的結束。查詢批處理是TSQL語句的集合,這些語句集合在一起執行。Go與Osql或SQL Server Query Analyzer一起使用。
管理文本和圖像數據
???????文本和圖像數據類型列可以象其它列一樣包含在SELECT語句的Select_list中。通過SELECT語句檢索的最大文本大小由TEXTSIZE設置來控制。默認的TEXTSIZE的值是4096字節,使用SET TEXTSIZE語句可重新設置。當前的TEXTSIZE設置的值存放在全局變量@@TEXTSIZE中。
???????另一種檢索文本和圖像數據的方法是通過TEXTPTR和READTEXT函數。TEXTPTR函數把列名字作為輸入參數并以二進制格式返回文本指針。
???????這個指針和被稱為偏移量的讀開始指針以及要讀的字節數量一起傳給READTEXT函數,以檢索文本和圖像數據。
修改數據
???????TSQL也提供從數據庫插入、修改、刪除的命令。
插入
???????INSERT命令用來在表中插入數據,語法如下:
???????INSERT [INTO] <table_name> [(column_list)] VALUES (value_list)
???????Value_list是和在Column_list中列相應的值。這些值可以是常量、TSQL變量或SQL Server內部函數。值的順序應和column_list中列的順序相對應。如果沒有定義column_list,則值的順序應和表中列的順序對應。
???????INSERT的Values_list也可通過SELECT語句或一個存儲過程來提供。語法如下:
???????INSERT [INTO] <table_name> [(column_list)]
???????SELECT <select_list> FROM <table_name>
???????INSERT [INTO] <table_name> [(column_list)]
???????EXECUTE <procedure_name>
???????這里的SELECT語句可包含多種連接。如果使用存儲過程,則存儲過程應返回能作為column_list的結果。
???????時間戳(timestamp,又稱時標)值不應被提供。同時,如果列的IDENTITY屬性被定義,則這一列的值也不能提供。這些值都由系統產生。如果列有默認值,則它們的值不被提供,而使用默認值。
修改
???????UPDATE語句用來修改行,語法如下:
???????UPDATE <table_name> SET <column_name> = <value> [,<column_name> = <value>_n]
???????WHERE <search_condition>]
???????Serach_condition是要修改的行應滿足的條件。沒有WHERE子句的UPDATE語句將修改表中的所有行。在UPDATE語句中也可使用連接。
刪除
???????DELETE語句用來從表中刪除行。語法如下:
???????DELETE [FROM] <table_name>
???????[WHERE <search_condition>]???????Serach_condition是刪除行要滿足的條件。一個無條件DELETE語句將刪除表中的所有行。在DELETE語句中也可使用連接。
使用SQL Server開發應用程序
編寫存儲過程與觸發器
???????存儲過程和觸發器是由用戶創建的、駐留在服務器的一組Transact SQL查詢語句。觸發器是系統在特定條件下執行的。存儲過程能夠改善應用程序的性能。當客戶程序需要訪問數據時,一般要經過5個步驟才能訪問到數據:
1)??查詢語句被發送到服務器。
2)??服務器編譯SQL代碼。
3)??優化產生查詢的執行計劃。
4)??數據引擎執行查詢。
5)??結果發回客戶程序。
存儲過程是在創建時編譯的,當存儲過程第一次執行時,SQL Server產生查詢執行計劃并將其存儲進來,以利于將來使用。當通過存儲過程發出一個請求時,上述的第2和第3步就沒有了,這能大大改善系統的性能。即使在第1步上也能提高性能。因為此時發送到服務器的語句只是一條存儲過程的EXECUTE語句,而不是龐大的、復雜的查詢。這種特性能降低網絡的流量。
除了性能方面的改善外,存儲過程還提供了方便地集中維護應用程序的功能。如果將查詢嵌入到應用程序中。而又需要對查詢進行改變,則應用程序需要重新編譯,并重新發布到所有的客戶端。而在存儲過程中,修改對用戶而言是透明的,它只需要在服務器上重新編譯存儲過程。
存儲過程還能提供安全機制,盡管用戶可能無權執行存儲過程中的命令,但它卻可能有權執行存儲過程本身。有時候,系統管理員不會給用戶以數據修改(UPDATE、INSERT和DELETE)的權力。創建的存儲過程卻能進行這些操作。當然用戶需要擁有執行該存儲過程的權力。
建立存儲過程
???????存儲過程可以達到以下目的:
???????· 帶參數。
???????· 返回狀態值。
???????· 調用其它存儲過程。
???????· 在遠程服務器上執行。
???????存儲過程在“sysobjects”系統表中有一個表項,其類型為“P”。存儲過程的文本存儲在“syscomments”系統表中。創建存儲過程需要使用Transact SQL命令CREATE PROCEDURE。
???????例如:
???????USE pubs
???????GO
???????
???????CREATE PROCEDURE ap_GetAuthorsForPublisher
???????AS
???????SELECT a.au_lname,a.au_fname
???????FROM authors a, titleauthor ta, titles t, publishers p
???????WHERE a.au_id = ta.Au_id
???????AND ta.Title_id = t.title_id
???????AND t.pub_id = p.pub_id
???????AND p.pub_name = ’New Moon Books’
???????GO
???????CREATE PROCEDURE語句的語法如下:
???????CREATE PROC[DURE] procedure_name [;number]
??????????????[@parameter_name ][OUTPUT] [,_n] ]
??????????????[WITH {RECOMPILE | ENCRYPTION}]
??????????????[FOR REPLICATION]
???????AS
???????Number是用來對相同名字的過程進行分組的整數。分組是將所有的過程通過drop procedure語句組合到一個分組中。
???????@parameter_name指定參數的名稱。
???????RECOMPILE表示每次執行過程時都要進行編譯。
???????ENCRYPTION表示過程的文本在“syscomments”表中要加密。
???????FOR REPLICATION表示過程不能在提交服務器上執行。
將參數傳遞給存儲過程
???????存儲過程能夠接受參數。
???????注意:過程的參數也可以是用戶定義的數據類型。
給參數一個缺省值
???????用戶還可以為存儲過程中的參數定義缺省值。當在執行時沒有提供所需的參數時,系統就使用缺省值作為參數。如果既沒有定義缺省值,又沒有在執行時提供參數,則SQL Server就會返回一個錯誤。在存儲過程中定義缺省值,并使用一些邏輯檢測是否指定了參數從而采取相應的行動,這是一種很好的習慣。
???????例如:
???????USE pubs
???????GO
???????
???????CREATE PROCEDURE ap_GetAuthorsForPublisher
???????@PublisherName varchar(40) = ‘New Moon Books’
???????AS
???????SELECT a.au_lname,a.au_fname
???????FROM authors a, titleauthor ta, titles t, publishers p
???????WHERE a.au_id = ta.Au_id
???????AND ta.Title_id = t.title_id
???????AND t.pub_id = p.pub_id
???????AND p.pub_name = @PublisherName
???????GO
建立存儲過程體
???????存儲過程邏輯駐留在存儲過程體中。一個存儲過程體中可以包含任意條Transact SQL語句。下面的Transact SQL語句不能在任何存儲過程體中出現:
???????· CREATE DEFAULT
???????· CREATE TRIGGER
???????· CREATE PROCEDURE
???????· CREATE VIEW
???????· CREATE RULE
1、??局部變量
局部變量保持存儲過程中間值。當一個值在存儲過程中需要多次,或者某個查詢的結果需要在隨后的查詢中使用時,需要使用局部變量。在這些情形下,值被存儲在局部變量中,并可用于將來的使用。本地變量的名稱以“@”符號開頭。變量的名稱可以包含字符和數值。局部變量在使用前需要進行類型聲明。對局部變量進行賦值需要使用SELECT語句。SELECT可以從一個表中檢索出值并將其賦給某個變量,也可以給變量賦一個常量值。一個簡單的SELECT語句可以給多個局部變量賦值。
例如:
DECLARE @var1 integer, @var2 varchar(20)
SELECT @var1 = 32,
???????????@var2 = ‘MyAge’
如果從SELECT查詢中沒有返回任何數據,而SELECT又要將數據的值賦予局部變量,則該局部變量的值將不會發生改變。
2、??條件詞句
存儲過程中提供的條件語句包括:
· IF……ELSE語句。
· WHILE語句。
1)??IF……ELSE語句。在該語句中包含三個部分:布爾運算表達式,IF語句塊和ELSE語句塊。語法如下:
IF (boolen_expr)
??{statements}
ELSE
??{statements}
在IF或ELSE語句塊中可以有多條語句,這種情形下,需要語句BEGIN和END來標志語句塊。
2)??WHILE語句。WHILE語句用于處理直到某個條件為TRUE前重復執行的語句。語法如下:
WHILE (boolen_expr)
??BEGIN
??statement(s)
BREAK
Statement(s)
CONTINUE
??????????????END
????????????BEGIN和END語句標志循環體。BREAK語句結束循環的執行(即走到END語句之后)。CONTINUE語句將控制處理過程回到循環的開始處(即BEGIN語句的右邊)。
????????????注意:如果有兩個或多個WHILE循環被嵌套,則內部的BREAK退出的是次外層的循環。內部循環結束之后的所有語句在內部循環執行之后才能繼續執行。
3、??GOTO語句
在存儲過程的執行中,語句是順序執行的。GOTO語句則是用來打破這種語句執行的順序,它立即跳到某條語句上執行,而這條語句往往不緊跟在前一語句之后。GOTO語句與一個標志(Label)一起使用,該標志用來標識一條語句。
例如:
USE pubs
GO
DECLARE @num int
SELECT
IF @num = 0
???????GOTO Err
ELSE
???????BEGIN
???????PRINT ‘authors found’
???????SELECT * FROM authors
???????GOTO Last
???????END
Err: PRINT ‘no authors found’
Last: PRINT ‘Finish execution’
GO
4、??RETURN語句
RETURN語句用于無條件的退出存儲過程。RETURN之后的任何語句都不再執行。RETURN語句可以給調用語句返回一個值,但不能返回NULL值。SQL Server經常為存儲過程返回一個狀態值。如果成功地執行,則返回一個0,如果出現了錯誤,則返回一個為負數的錯誤碼。
存儲過程返回的錯誤碼
值
說????????明
值
說????????明
0
過程執行成功
-8
發生了非致命的內部問題
-1
漏掉了對象
-9
達到了系統極限
-2
發生了數據類型錯誤
-10
發生了致命的內部不一致錯誤
-3
該處理被選擇成了死鎖的犧牲者
-11
發生了致命的內部不一致錯誤
-4
發生了權限錯誤
-12
表或索引被破壞
-5
發生了語法錯誤
-13
數據庫被破壞
-6
發生了混雜的用戶錯誤
-14
發生了硬件錯誤
-7
資源錯誤,如空間不夠等
5、??使用游標(CURSOR)在需要一行一行處理時,游標十分有用。游標可以打開一個結果集合(按照指定的標準選擇的行),并提供在結果集中一行一行處理的功能。基于游標的類型,可以對其進行回滾或者前進。在使用游標時需要5個步驟:
i.??????????????聲明游標
在這一步中,需要指定游標的屬性和根據要求產生的結果集。有兩種方法可以指定一個游標。
形式1??(ANSI 92)
DECLARE cursor_name [INSENSITIVE] [SCROLL] CURSOR
FOR select_statement
[FOR {READ ONLY | UPDATE ][OF column_list]}]
形式2
DECLARE cursor_name CURSOR
[LOCAL | GLOBAL]
[FORWARD_ONLY | SCROLL]
[STATIC | KEYSET | DYNAMIC]
[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]
FOR select_statement
[FOR {READ ONLY | UPDATE ][OF column_list]}]
INSENSITIVE關鍵字指明要為檢索到的結果集建立一個臨時拷貝,以后的數據從這個臨時拷貝中獲取。如果在后來游標處理的過程中,原有基表中數據發生了改變,那么它們對于該游標而言是不可見的。這種不敏感的游標不允許數據更改。
SCROLL關鍵字指明游標可以在任意方向上滾動。所有的fetch選項(first、last、next、relative、absolute)都可以在游標中使用。如果忽略該選項,則游標只能向前滾動(next)。
Select_statement指明SQL語句建立的結果集。Transact SQL語句COMPUTE、COMPUTE BY、FOR BROWSE和INTO在游標聲明的選擇語句中不允許使用。
READ ONLY指明在游標結果集中不允許進行數據修改。
UPDATE關鍵字指明游標的結果集可以修改。
OF column_list指明結果集中可以進行修改的列。缺省情況下(使用UPDATE關鍵字),所有的列都可進行修改。
LOCAL關鍵字指明游標是局部的,它只能在它所聲明的過程中使用。
GLOBAL關鍵字使得游標對于整個連接全局可見。全局的游標在連接激活的任何時候都是可用的。只有當連接結束時,游標才不再可用。
FORWARD_ONLY指明游標只能向前滾動。
STATIC的游標與INSENSITIVE的游標是相同的。
KEYSET指明選取的行的順序。SQL Server將從結果集中創建一個臨時關鍵字集。如果對數據庫的非關鍵字列進行了修改,則它們對游標是可見的。因為是固定的關鍵字集合,所以對關鍵字列進行修改或新插入列是不可見的。
DYNAMIC指明游標將反映所有對結果集的修改。
SCROLL_LOCK是為了保證游標操作的成功,而對修改或刪除加鎖。
OPTIMISTIC指明哪些通過游標進行的修改或者刪除將不會成功。
注意:
· 如果在SELECT語句中使用了DISTINCT、UNION、GROUP BY語句,且在選擇中包含了聚合表達式,則游標自動為INSENSITIVE的游標。
· 如果基表沒有唯一的索引,則游標創建成INSENSITIVE的游標。
· 如果SELECT語句包含了ORDER BY,而被ORDER BY的列并非唯一的行標識,則DYNAMIC游標將轉換成KEYSET游標。如果KEYSET游標不能打開,則將轉換成INSENSITIVE游標。使用SQL ANSI-92語法定義的游標同樣如此,只是沒有INSENSITIVE關鍵字而已。
???????????????????????ii.??????????????打開游標
打開游標就是創建結果集。游標通過DECLARE語句定義,但其實際的執行是通過OPEN語句。語法如下:
OPEN { { [GLOBAL] cursor_name } | cursor_variable_name}
GLOBAL指明一個全局游標。
Cursor_name是被打開的游標的名稱。
Cursor_variable_name是所引用游標的變量名。該變量應該為游標類型。
在游標被打開之后,系統變量@@cursor_rows可以用來檢測結果集的行數。@@cursor_rows為負數時,表示游標正在被異步遷移,其絕對值(如果@@cursor_rows為-5,則絕對值為5)為當前結果集的行數。異步游標使用戶在游標被完全遷移時仍然能夠訪問游標的結果。
??????????????????????iii.??????????????從游標中取值
在從游標中取值的過程中,可以在結果集中的每一行上來回移動和處理。如果游標定義成了可滾動的(在聲明時使用SCROLL關鍵字),則任何時候都可取出結果集中的任意行。對于非滾動的游標,只能對當前行的下一行實施取操作。結果集可以取到局部變量中。Fetch命令的語法如下:
FETCH [NEXT | PRIOR| FIRST | LAST | ABSOLUTE {n | @nvar} | RELATIVE {n | @nvar}]
FROM [GLOBAL] cursor_name} | cursor_variable_name}
[INTO @variable_name ][,……n]]
NEXT指明從當前行的下一行取值。
PRIOR指明從當前行的前一行取值。
FIRST是結果集的第一行。
LAST是結果集的最后一行。
ABSOLUTE n表示結果集中的第n行,該行數同樣可以通過一個局部變量傳播。行號從0開始,所以n為0時不能得到任何行。
RELATIVE n表示要取出的行在當前行的前n行或后n行的位置上。如果該值為正數,則要取出的行在當前行前n行的位置上,如果該值為負數,則返回當前行的后n行。
INTO @cursor_variable_name表示游標列值存儲的地方的變量列表。該列表中的變量數應該與DECLARE語句中選擇語句所使用的變量數相同。變量的數據類型也應該與被選擇列的數據類型相同。直到下一次使用FETCH語句之前,變量中的值都會一直保持。
每一次FETCH的執行都存儲在系統變量@@fetch_status中。如果FETCH成功,則@@fetch_status被設置成0。@@fetch_status為-1表示已經到達了結果集的一部分(例如,在游標被打開之后,基表中的行被刪除)。@@fetch_status可以用來構造游標處理的循環。
例如:
DECLARE @iname char(20), @fname char(20)
OPEN author_cur
FETCH FIRST FROM author_cur INTO @iname, @fname
WHILE @@fetch_status = 0
BEGIN
IF @fname = ‘Albert’
PRINT “Found Albert Ringer”
ELSE
Print “Other Ringer”
FETCH NEXT FROM author_cur INTO @iname, @fname
END
?????????????????????iv.??????????????關閉游標
CLOSE語句用來關閉游標并釋放結果集。游標關閉之后,不能再執行FETCH操作。如果還需要使用FETCH語句,則要重新打開游標。語法如下:
CLOSE [GLOBAL] cursor_name | cursor_variable_name
???????????????????????v.??????????????釋放游標
游標使用不再需要之后,要釋放游標。DEALLOCATE語句釋放數據結構和游標所加的鎖。語法如下:
DEALLOCATE [GLOBAL] cursor_name | cursor_variable_name
???????下面給出游標的一個完整的例子:
???????USE master
???????GO
???????CREATE PROCEDURE sp_BuildIndexes
???????AS
???????DECLARE @TableName sysname, @msg varchar(100), @cmd varchar(100)
???????DECLARE table_cur CURSOR FOR
???????SELECT name FROM sysobjects WHERE type=’u’
???????OPEN table_cur
???????FETCH NEXT FROM table_cur INTO @TableName
???????
???????WHILE @@fetch_status = 0
???????BEGIN
??????????????IF @@fetch_status = -2
?????????????????????CONTINUE
??????????????SELECT @msg = “Building indexes for table”+@TableName+”…”
??????????????PRINT @msg
??????????????SELECT @cmd = “DBCC DBREINDEX (‘”+@TableName+”')”
??????????????EXEC (@cmd)
??????????????PRINT “????“
??????????????FETCH NEXT FROM table_cur INTO @TableName
???????END
???????DEALLOCATE table_cur
???????GO
???????下面的腳本將為PUBS數據庫執行sp_BuildIndexes
???????USE pubs
???????GO
???????EXEC ap_BuildIndexes
???????注意:上面也是創建用戶定義的系統存儲過程的示例。
使用臨時表
???????臨時表是在TempDB中創建的表。臨時表的名稱都以“#”開頭。臨時表的范圍為創建臨時表的連接。因為,臨時表不能在兩個連接之間共享,一旦連接關閉,臨時表就會被丟棄。如果臨時表被創建于存儲過程之中,則臨時表的范圍在存儲過程之中,或者被該存儲過程調用的任何存儲過程之中。如果需要在連接之間共享臨時表,則需要使用全局的臨時表。全局的臨時表以“##”符號開頭,它將一直存在于數據庫中,直到SQL Server重新啟動。一旦這類臨時表創建之后,所有的用戶都可以訪問到。在臨時表上不能明確地指明權限。???????臨時表提供了存儲中間結果的能力。有時候,臨時表還能通過將一個復雜的查詢分解成兩個查詢而獲得性能的改善。這可以通過首先將第一個查詢的結果存在臨時表中,然后在第二個查詢中使用臨時表來實現。當一個大表中的某個子集在一個在座過程中使用多次時,建議使用臨時表。在這種情況下,在臨時表中保持數據的子集,以在隨后的連接中使用,這樣能大大改善性能。還可以在臨時表中創建索引。
存儲過程中返回結果
???????從存儲過程中返回結果有三種方式:
1、??返回結果集
這是客戶端應用程序返回結果的最通用的方法。結果集是通過使用SELECT語句選擇數據產生的。結果集可以從永久表、臨時表或局部變量中產生。將結果返回到另一個存儲過程不是一種有效的方法。存儲過程不能訪問另一個存儲過程建立的結果集。
例如從永久表中返回結果集:
USE pubs
GO
CREATE PROCEDURE ap_CreateResultFromPermtable
AS
SELECT au_iname FROM authors
GO
例如從局部變量中創建結果集:
USE pubs
GO
CREATE PROCEDURE ap_CreateResultFromVariable
AS
DECLARE @au_iname char(20)
SELECT @au_iname = au_iname FROM authors
WHERE au_id = ‘172-32-1176’
SELECT @au_id
GO
2、??設置OUTPUT參數的值
輸出參數經常用來從存儲過程中檢索出結果。如果某個參數在傳輸到存儲過程中時被定義成OUTPUT,則對該參數的任何修改在退出存儲之后仍然有效。
例如:
USE pubs
GO
CREATE PROCEDURE ap_SetOutputVar @count integer OUTPUT
AS
SELECT @count = count(*) FROM authors
GO
從輸出參數中檢索出值:
USE pubs
GO
CREATE PROCEDURE ap_GetOutputVar
AS
DECLARE @num integer
EXECUTE ap_SetOutputVar @num OUTPUT
PRINT “the count is”+convert(char,@num)
GO
· 將游標使用成OUTPUT參數。游標可以使用OUTPUT(輸出)參數,但不能使用成輸入參數。也就是說,游標可以作為結果返回,但卻不能傳輸到過程中去。當游標被用作參數時,需要限定其為OUTPUT和VARYING。VARYING關鍵字指出該結果集要用來支持輸出參數。這樣就提供了將結果集返回到調用過程的能力。
例如:
USE pubs
GO
CREATE PROCEDURE GetTitleCount @count_cursor CURSOR VARYING OUTPUT
AS
SET @count_cursor = CURSOR
FOR
SELECT au_id,count(*)
FROM titleauthors
GROUP BY au_id
OPEN @count_cursor
GO
3、??通過RETURN參數返回狀態
這是一種從存儲過程返回錯誤碼的方法。存儲過程總是返回一個狀態值,用戶也可以使用RETURN語句返回自己的狀態。
例如:
USE pubs
GO
CREATE PROCEDURE ap_SetReturnStatus
AS
DECLARE @count integer
SELECT @count = count(*) FROM authors
IF @count = 0
RETURN(1)
ELSE
RETURN (0)
GO
例如檢索出返回的狀態:
USE pubs
GO
CREATE PROCEDURE ap_GetReturnStatus
AS
DECLARE @status integer
EXECUTE @status = ap_SetReturnStatus
IF @status = 1
PRINT “No rows found”
ELSE
PRINT “successful”
GO
在存儲過程中進行錯誤處理
???????如同其它程序一樣,在存儲過程中進行錯誤處理是非常重要的。系統變更@@error在執行每一個Transact SQL語句之后都會得到一個值。對于成功的執行,@@error的值為0,如果出現錯誤,則@@error中將包含錯誤信息。@@error系統變量對存儲過程的錯誤處理是非常重要的。
???????注意:為了防止錯誤,@@error所能設置的值在sysmessages表的“error”中反映了出來。
在存儲過程中的錯誤有兩種類型:
1、????數據庫相關的錯誤
這些錯誤是由數據庫的不一致性引起的,系統使用非0的@@error值表示特定的數據庫問題。在Transact SQL執行之后,可以通過@@error獲得所出現的錯誤。如果發現@@error不為0,則必須采取必要的行動,大多數情況下,存儲將不再繼續進行處理而返回。下面的示例展示了典型的獲取數據庫錯誤的方法。該過程將錯誤代碼放置到輸出變量中,這樣,調用程序就能夠訪問到。
USE pubs
GO
CREATE PROCEDURE ap_TrapDatabaseError @return_code integer OUTPUT
AS
UPDATE authors SET au_iname = “Jackson”
WHERE au_iname = “Smith”
IF @@error <> 0
BEGIN
???????SELECT @return_code = @@error
???????RETURN
END
ELSE
???????@return_code = 0
GO
2、????業務邏輯錯誤
這些錯誤是由于違反了業務規則而引起的。要獲取這些錯誤,首先需要定義業務規則,基于這些規則,需要在存儲過程中增加必要的錯誤檢測代碼。人們經常使用RAISERROR語句通報這些錯誤。RAISERROR提供了返回用戶定義錯誤及將@@error變量設置成用戶定義錯誤號的能力。錯誤消息可以被動態地建立,或者基于錯誤號從“sysmessages”表中檢索到。一旦出現了錯誤,錯誤就會以一種服務器錯誤消息的方式返回到客戶機。下面是RAISERROR命令的語法:
RAISERROR (msg_id | msg_str, severity, state
[, argument ][,…n]])
[WITH options]
Msg_id指明用戶定義消息的id,該消息存儲在“sysmessages”系統表中。
Msg_str用于動態創建消息的消息字符串。這與C語言中的“printf”非常相似。
Severity定義用戶賦值的錯誤消息嚴重程度。
State是從1到127的任意整數值,它表示錯誤的調用狀態信息。負數的state值將缺省為1。
OPTIONS指明錯誤的定制選項。OPTIONS的有效值如下:
1)??LOG。
將錯誤記錄到服務器錯誤日志和NT事件日志中。該選項需要消息帶有從19到25的嚴重程度。而只有系統管理員才能發出這種消息。
2)??NOWAIT。
將消息立即發送到客戶端服務器。
3)??SETERROR。
不管其嚴重級別如何,將@@error的值設置為msg_id或5000。
遠程過程調用
???????SQL Server提供了調用駐留在不同服務器上的存儲過程的能力。調用這樣的存儲過程稱謂遠程存儲過程調用。為了使得調用能從一個SQL Server轉移到另一個服務器,兩個服務器應該相互定義成對方的有效遠程服務器。
???????設置遠程服務器的配置:
???????· 擴展某個服務器的組。
???????· 右擊該服務器并點擊“Properties”。
???????· 設置選項“Allow other SQL Servers to connect remotely to this SQL server via RPC”。
???????· 設置“Query time out”選項的值,該值指定從一個查詢處理返回所能等待的秒數。缺省值為0,表示允許無限的等待時間。
???????· 設置完成配置選項之后,點擊“OK”。
???????· 重新啟動服務器之后,修改將會生效。
???????· 在另一臺遠程服務器上重復相同的步驟。
???????調用遠程存儲過程需要指明服務器的名稱,后帶數據庫的名稱和擁有者的名稱。下面是在不同的服務器(Server2)上調用一個存儲過程的示例。
Exec server2.pubs.dbo.myproc
豆豆的后話:
???????這里只是粗淺的介紹了SQL Server常用的知識,對象也是基于SQL Server數據庫編寫應用程序的編程人員,而非數據庫管理者。但對于應用程序編程者,了解數據庫的管理也是非常有用的。建議在以后的時間自行去了解數據庫的管理,這對于優化程序也是相當有用的。
————————全文完—————————
轉載于:https://www.cnblogs.com/cnLiou/archive/2005/08/13/213866.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的SQL SERVER7应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小程序发布上线流程_家居小程序傻瓜式制作
- 下一篇: mysqldump全量恢复_删库不跑路-