計算機等級三級數據庫SQLServer7.0入門(七)

字號:

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 ][OFcolumn_list]}]
    INSENSITIVE關鍵字指明要為檢索到的結果集建立一個臨時拷貝,以后的數據從這個臨時拷貝中獲取。如果在后來游標處理的過程中,原有基表中數據發(fā)生了改變,那么它們對于該游標而言是不可見的。這種不敏感的游標不允許數據更改。
    SCROLL 關鍵字指明游標可以在任意方向上滾動。所有的 fetch 選項( first 、 last 、 next 、 relative 、 absolute)都可以在游標中使用。如果忽略該選項,則游標只能向前滾動( next )。
    Select_statement 指明 SQL 語句建立的結果集。
    TransactSQL 語句 COMPUTE 、 COMPUTE BY 、 FOR BROWSE 和 INTO 在游標聲明的選擇語句中不允許使用。 READ ONLY指明在游標結果集中不允許進行數據修改。
    UPDATE 關鍵字指明游標的結果集可以修改。 OF column_list指明結果集中可以進行修改的列。缺省情況下(使用 UPDATE 關鍵字),所有的列都可進行修改。
    LOCAL關鍵字指明游標是局部的,它只能在它所聲明的過程中使用。 GLOBAL關鍵字使得游標對于整個連接全局可見。全局的游標在連接激活的任何時候都是可用的。只有當連接結束時,游標才不再可用。
    FORWARD_ONLY指明游標只能向前滾動。
    STATIC 的游標與 INSENSITIVE 的游標是相同的。 KEYSET 指明選取的行的順序。
    SQL Server將從結果集中創(chuàng)建一個臨時關鍵字集。如果對數據庫的非關鍵字列進行了修改,則它們對游標是可見的。因為是固定的關鍵字集合,所以對關鍵字列進行修改或新插入列是不可見的。DYNAMIC 指明游標將反映所有對結果集的修改。
    SCROLL_LOCK 是為了保證游標操作的成功,Examda提示:而對修改或刪除加鎖。
    OPTIMISTIC指明哪些通過游標進行的修改或者刪除將不會成功。
    注意: · 如果在 SELECT 語句中使用了 DISTINCT 、 UNION 、 GROUP BY語句,且在選擇中包含了聚合表鍤劍蠐偽曜遠?INSENSITIVE 的游標。
    · 如果基表沒有的索引,則游標創(chuàng)建成 INSENSITIVE 的游標。
    · 如果 SELECT 語句包含了 ORDER BY ,而被 ORDER BY 的列并非的行標識,則 DYNAMIC 游標將轉換成 KEYSET游標。如果 KEYSET 游標不能打開,則將轉換成 INSENSITIVE 游標。使用 SQL ANSI-92 語法定義的游標同樣如此,只是沒有INSENSITIVE 關鍵字而已。
    ii. 打開游標打開游標就是創(chuàng)建結果集。Examda提示:游標通過DECLARE 語句定義,但其實際的執(zhí)行是通過 OPEN 語句。
    語法如下: OPEN { { [GLOBAL] cursor_name } |cursor_variable_name} GLOBAL 指明一個全局游標。
    Cursor_name 是被打開的游標的名稱。
    Cursor_variable_name 是所引用游標的變量名。該變量應該為游標類型。在游標被打開之后,系統(tǒng)變量 @@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的執(zhí)行都存儲在系統(tǒng)變量 @@fetch_status 中。
    如果 FETCH 成功,則 @@fetch_status 被設置成 0 。@@fetch_status 為 -1 表示已經到達了結果集的一部分(例如,在游標被打開之后,基表中的行被刪除)。
    @@fetch_status可以用來構造游標處理的循環(huán)。
    例如: DECLARE @iname char(20), @fname char(20) OPEN author_cur FETCHFIRST 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 語句用來關閉游標并釋放結果集。游標關閉之后,不能再執(zhí)行 FETCH 操作。如果還需要使用 FETCH語句,則要重新打開游標。
    語法如下: CLOSE [GLOBAL] cursor_name |cursor_variable_name
    v. 釋放游標游標使用不再需要之后,要釋放游標。 DEALLOCATE 語句釋放數據結構和游標所加的鎖。
    語法如下: DEALLOCATE [GLOBAL]cursor_name | cursor_variable_name
    下面給出游標的一個完整的例子:
    USEmaster
    GO
    CREATE PROCEDURE sp_BuildIndexes
    AS
    DECLARE @TableName sysname, @msg varchar(100), @cmd varchar(100)
    DECLAREtable_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 indexesfor table ” +@TableName+ ” … ”
    PRINT @msg
    SELECT@cmd = “ DBCC DBREINDEX ( ‘” +@TableName+ ”’ ) ”
    EXEC(@cmd)
    PRINT “ “
    FETCH NEXT FROM table_curINTO @TableName
    END
    DEALLOCATE table_cur
    GO
    下面的腳本將為PUBS 數據庫執(zhí)行 sp_BuildIndexes
    USE pubs
    GO
    EXECap_BuildIndexes
    注意:上面也是創(chuàng)建用戶定義的系統(tǒng)存儲過程的示例。
    使用臨時表
    臨時表是在 TempDB中創(chuàng)建的表。臨時表的名稱都以“ #”開頭。臨時表的范圍為創(chuàng)建臨時表的連接。因為,臨時表不能在兩個連接之間共享,一旦連接關閉,臨時表就會被丟棄。如果臨時表被創(chuàng)建于存儲過程之中,則臨時表的范圍在存儲過程之中,或者被該存儲過程調用的任何存儲過程之中。如果需要在連接之間共享臨時表,則需要使用全局的臨時表。全局的臨時表以“## ”符號開頭,它將一直存在于數據庫中,直到 SQL Server重新啟動。一旦這類臨時表創(chuàng)建之后,考試大提示:所有的用戶都可以訪問到。在臨時表上不能明確地指明權限。
    臨時表提供了存儲中間結果的能力。有時候,臨時表還能通過將一個復雜的查詢分解成兩個查詢而獲得性能的改善。這可以通過首先將第一個查詢的結果存在臨時表中,然后在第二個查詢中使用臨時表來實現。當一個大表中的某個子集在一個在座過程中使用多次時,建議使用臨時表。在這種情況下,在臨時表中保持數據的子集,以在隨后的連接中使用,這樣能大大改善性能。還可以在臨時表中創(chuàng)建索引。