關聯式資料庫中的作業會針對完整的資料列集運作。 由 SELECT 陳述式所傳回的資料列集包括所有滿足陳述式 WHERE 子句之條件的資料列。 由陳述式傳回的完整資料列稱為結果集。 應用程式無法總是有效地將整個結果集作為一個整體來處理。 這些應用程式需要能夠一次運用一個資料列或小型資料列區塊。 游標是結果集的擴充功能,可提供該機制。
游標可藉由執行下列各項作業來延伸結果集的處理能力:
- 允許在結果集的特定資料列進行定位。
- 從結果集的目前位置,擷取一個資料列或資料列區塊。
- 支援對結果集中目前位置的資料列進行資料修改。
- 支援以不同可見度層級來檢視其他使用者對結果集所呈現的資料庫資料所做的變更。
注意
如需 SQL Server 資料指標類型的完整描述,請參閱資料指標的類型。
JDBC 規格支援只能向前的游標和可捲動的游標;這些游標可對其他工作所做的變更敏感或不敏感,也可以是唯讀或可更新的。 這項功能是由 Microsoft JDBC Driver for SQL Server SQLServerResultSet 類別所提供。
備註
JDBC 驅動程式支援下列結果集和資料指標類型,以及指定的行為選項。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選擇方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_FORWARD_ONLY(CONCUR_READ_ONLY) | N/A | 順向、唯讀 | 直接 | 完整 |
應用程式必須以單向(順向)方式走訪結果集一次。 此傳遞作業是預設行為,其行為與 TYPE_SS_DIRECT_FORWARD_ONLY 游標相同。 驅動程式會在陳述式執行時間,將完整的結果集從伺服器讀入記憶體中。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選擇方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_FORWARD_ONLY(CONCUR_READ_ONLY) | N/A | 順向、唯讀 | 直接 | 自適應 |
應用程式必須對結果集進行單次(向前)走訪。 其行為與 TYPE_SS_DIRECT_FORWARD_ONLY 游標相同。 驅動程式會依照應用程式的要求從伺服器讀取資料列,並將用戶端記憶體使用量降到最低。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選擇方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_FORWARD_ONLY(CONCUR_READ_ONLY) | 向前快轉 | 順向、唯讀 | 資料指標 | N/A |
應用程式必須使用伺服器游標,以單次(向前)的方式處理結果集。 它的行為與 TYPE_SS_SERVER_CURSOR_FORWARD_ONLY 游標相同。
資料列會依照擷取大小所指定的區塊,從伺服器分批擷取。
| 結果集 (游標) 類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_FORWARD_ONLY(CONCUR_UPDATABLE) | 動態(僅限向前) | 順向、可更新的 | N/A | N/A |
應用程式必須以單一(向前)的方式逐筆走訪結果集,才能更新一或多個資料列。
資料列會依擷取大小所指定的區塊,分批從伺服器擷取。
根據預設,當應用程式呼叫 SQLServerResultSet 物件的 setFetchSize 方法時,提取大小是固定的。
注意
JDBC 驅動程式提供自適性緩衝功能,可讓您在應用程式需要時,從 SQL Server 中擷取陳述式執行結果,而非一次擷取所有結果。 例如,如果應用程式應該擷取的大型資料過大而無法完整納入應用程式記憶體中,適應性緩衝就會允許用戶端應用程式將這類值擷取成資料流。 此驅動程式的預設行為是 "adaptive"。 不過,若要取得順向可更新結果集的適應性緩衝,應用程式必須提供字串值 "adaptive" 來明確呼叫 SQLServerStatement 物件的 setResponseBuffering 方法。 如需範例程式碼,請參閱更新大型資料範例。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SCROLL_INSENSITIVE | 靜態 | 可捲動、不可更新 系統不會顯示外部資料列更新、插入和刪除。 |
N/A | N/A |
應用程式需要資料庫快照集。 此結果集不可更新。 僅支援 CONCUR_READ_ONLY。 與此游標類型一起使用時,所有其他並行性類型都會引發例外。
資料列會以擷取大小所指定的區塊為單位,從伺服器擷取。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選擇方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SCROLL_SENSITIVE(僅限讀取) | 鍵集 | 可捲動、唯讀。 外部資料列的更新會顯示出來,而刪除則會顯示為資料遺失。 系統不會顯示外部資料列插入。 |
N/A | N/A |
應用程式必須僅針對現有的資料列查看變更的資料。
資料列會以擷取大小所指定的區塊為單位,從伺服器擷取。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SCROLL_SENSITIVE (CONCUR_UPDATABLE、CONCUR_SS_SCROLL_LOCKS、CONCUR_SS_OPTIMISTIC_CC、CONCUR_SS_OPTIMISTIC_CCVAL) | 鍵集 | 可捲動、可更新。 外部和內部的資料列更新皆可見,而刪除會顯示為缺少的資料;插入則不可見。 |
N/A | N/A |
應用程式可能會使用 ResultSet 物件來變更現有資料列中的資料。 應用程式也必須能夠查看其他人在 ResultSet 物件外部對資料列所做的變更。
從伺服器中擷取資料列 (以提取大小所指定的區塊為單位)。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SS_DIRECT_FORWARD_ONLY | N/A | 順向、唯讀 | N/A | 完整或適應性 |
整數值 = 2003。 提供已完全緩衝的用戶端唯讀游標。 不會建立伺服器游標。
僅支援 CONCUR_READ_ONLY 並行類型。 與這種游標類型搭配使用時,所有其他並行存取類型都會引發例外。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SS_SERVER_CURSOR_FORWARD_ONLY | 向前快轉 | 順向 | N/A | N/A |
整數值 = 2004。 速度快,並使用伺服器游標存取所有資料。 搭配 CONCUR_UPDATABLE 並行類型使用時,它是可更新的。
從伺服器中擷取資料列 (以提取大小所指定的區塊為單位)。
若要取得此案例的適應性緩衝,應用程式必須提供字串值 "adaptive" 來明確呼叫 SQLServerStatement 物件的 setResponseBuffering 方法。 如需範例程式碼,請參閱更新大型資料範例。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SS_SCROLL_STATIC | 靜態 | 系統不會反映其他使用者的更新。 | N/A | N/A |
整數值 = 1004。 應用程式需要資料庫快照集。 此選項是 JDBC TYPE_SCROLL_INSENSITIVE 的 SQL Server 特定同義字,具有相同的並行設定行為。
從伺服器中擷取資料列 (以提取大小所指定的區塊為單位)。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SS_SCROLL_KEYSET(CONCUR_READ_ONLY) | 鍵集 | 可捲動、唯讀。 外部資料列的更新會顯示出來,而刪除則會顯示為資料遺失。 外部插入的資料列不會顯示。 |
N/A | N/A |
整數值 = 1005。 應用程式必須僅針對現有的資料列查看變更的資料。 此選項是 JDBC TYPE_SCROLL_SENSITIVE 的 SQL Server 特定同義字,具有相同的並行設定行為。
資料列會依照 fetch size 指定的區塊,從伺服器擷取。
| 結果集(游標)類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SS_SCROLL_KEYSET (CONCUR_UPDATABLE、CONCUR_SS_SCROLL_LOCKS、CONCUR_SS_OPTIMISTIC_CC、CONCUR_SS_OPTIMISTIC_CCVAL) | 鍵集 | 可捲動、可更新。 外部和內部的資料列更新皆可見,而刪除會呈現為資料缺漏;插入則不可見。 |
N/A | N/A |
整數值 = 1005。 應用程式必須變更資料或針對現有的資料列查看變更的資料。 此選項是 JDBC TYPE_SCROLL_SENSITIVE 的 SQL Server 特定同義字,具有相同的並行設定行為。
資料列會依照擷取大小所指定的區塊,從伺服器擷取。
| 結果集 (游標) 類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SS_SCROLL_DYNAMIC(CONCUR_READ_ONLY) | 動態 | 可捲動、唯讀。 外部對資料列所做的更新與插入會顯示出來,而刪除則會在目前的擷取緩衝區中顯示為暫時缺失的資料。 |
N/A | N/A |
整數值 = 1006。 應用程式必須能看見既有資料列中已變更的資料,並且在游標的生命週期內看見插入和刪除的資料列。
資料列會依照擷取大小所指定的區塊,從伺服器擷取。
| 結果集 (游標) 類型 | SQL Server 游標類型 | 特性 | 選取方法 | 回應緩衝 |
|---|---|---|---|---|
| TYPE_SS_SCROLL_DYNAMIC (CONCUR_UPDATABLE、CONCUR_SS_SCROLL_LOCKS、CONCUR_SS_OPTIMISTIC_CC、CONCUR_SS_OPTIMISTIC_CCVAL) | 動態 | 可捲動、可更新。 外部與內部對資料列的更新與插入皆可見,而刪除則會在目前的擷取緩衝區中顯示為暫時缺失的資料。 |
N/A | N/A |
整數值 = 1006。 應用程式可能會使用 ResultSet 物件來變更現有資料列的資料,或者插入或刪除資料列。 應用程式也必須能夠查看其他人在 ResultSet 物件外部所做的變更、插入和刪除。
資料列會依照擷取大小所指定的區塊,從伺服器擷取。
游標定位
TYPE_FORWARD_ONLY、TYPE_SS_DIRECT_FORWARD_ONLY 以及 TYPE_SS_SERVER_CURSOR_FORWARD_ONLY 游標僅支援 next 定位方式。
TYPE_SS_SCROLL_DYNAMIC 游標不支援 absolute 與 getRow 方法。 absolute 方法可透過結合呼叫對於動態游標的 first 和 relative 方法來近似實現。
getRow 方法僅受 TYPE_FORWARD_ONLY、TYPE_SS_DIRECT_FORWARD_ONLY、TYPE_SS_SERVER_CURSOR_FORWARD_ONLY、TYPE_SS_SCROLL_KEYSET 以及 TYPE_SS_SCROLL_STATIC 游標支援。 具有全部順向資料指標類型的 getRow 方法會傳回目前透過資料指標讀取的資料列數目。
注意
當應用程式進行不支援的資料指標定位呼叫時,或進行不支援的 getRow 方法呼叫時,會擲回一個例外狀況訊息:「不支援使用此資料指標類型來執行要求的作業」。
只有 TYPE_SS_SCROLL_KEYSET 和等效的 TYPE_SCROLL_SENSITIVE 游標會顯示已刪除的資料列。 如果游標位於已刪除的資料列上,則資料行值將無法使用,而且 rowDeleted 方法會傳回 "true"。 呼叫 get<Type> 方法會擲回例外狀況,並顯示訊息「無法從已刪除的資料列取得值」。 無法更新已刪除的資料列。 如果您嘗試在已刪除的資料列上呼叫 update<Type> 方法,則會擲回例外狀況,並顯示訊息「無法更新已刪除的資料列」。 TYPE_SS_SCROLL_DYNAMIC 游標的行為也相同,直到游標移出目前的擷取緩衝區為止。
向前游標和動態游標會以類似的方式顯示已刪除的資料列,但僅限於游標仍可透過擷取緩衝區存取時。 對於向前游標,這種行為相當直接。 對於動態游標,當提取大小大於 1 時,情況會更複雜。 應用程式可以在由擷取緩衝區所定義的視窗範圍內前後移動游標,但當離開進行更新時所在的原始擷取緩衝區後,已刪除的資料列就會消失。 如果應用程式不想使用動態資料指標查看暫時刪除的資料列,則應使用 fetch relative (0)。
如果使用游標更新 TYPE_SS_SCROLL_KEYSET 或 TYPE_SCROLL_SENSITIVE 游標資料列的鍵值,則無論更新後的資料列是否符合游標的選取條件,該資料列都會保留其在結果集中的原始位置。 如果資料列是在游標之外更新,已刪除的資料列會出現在該資料列的原始位置;但只有在另一個具有新索引鍵值的資料列原本存在於游標中、且後來已被刪除的情況下,該資料列才會出現在游標中。
對於動態游標,已更新的資料列會在擷取緩衝區內維持其位置,直到離開由擷取緩衝區所定義的視窗為止。 更新的資料列稍後可能會重複出現在資料集中的不同位置,也可能完全消失。 必須避免結果集中出現暫時性不一致的應用程式,應將擷取大小設為 1(預設值為:在 CONCUR_SS_SCROLL_LOCKS 並行模式下是 8 個資料列,在其他並行模式下是 128 個資料列)。
游標轉換
SQL Server 有時可能會選擇實作與所要求不同的資料指標類型,這稱為隱含資料指標轉換 (或資料指標降級)。
在 SQL Server 2000 (8.x) 中,當您透過 ResultSet.TYPE_SCROLL_SENSITIVE 和 ResultSet.CONCUR_UPDATABLE 結果集更新資料時,會擲回例外狀況,並顯示訊息「資料指標為 READ ONLY」。 因為 SQL Server 2000 (8.x) 已針對該結果集進行隱含性資料指標轉換,而且未傳回所要求的可更新資料指標,所以會發生此例外狀況。
若要解決這個問題,您可以執行下列其中一種解決方案:
- 確保基礎資料表擁有主索引鍵。
- 建立陳述式時,使用 SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC 而非 ResultSet.TYPE_SCROLL_SENSITIVE。
游標更新
對於游標類型和並行性支援更新的游標,支援就地更新。 如果資料指標不在結果集中的可更新資料列上 (get<Type> 方法呼叫不會成功),呼叫 update<Type> 方法會擲回例外狀況,並顯示訊息「結果集目前沒有資料列」。JDBC 規格指出,針對資料指標為 CONCUR_READ_ONLY 的資料行呼叫更新方法時,會引發例外狀況。 在資料列無法更新的情況下;例如,因為競相更新或刪除之類的開放式並行衝突,在呼叫 insertRow、updateRow 或 deleteRow 前,可能不會引發例外狀況。
呼叫 update<Type> 之後,在呼叫 updateRow 或 cancelRowUpdates 之前,便無法使用 get<Type> 存取受影響的資料行。 此行為可避免下列問題:使用不同於伺服器所傳回之類型更新資料行時,後續 getter 呼叫可能會叫用用戶端類型轉換而提供不正確的結果。 呼叫 get<Type> 時會擲回例外狀況,並顯示訊息:「在呼叫 updateRow() 或 cancelRowUpdates() 之前,無法存取已更新的資料行。」
注意
如果在尚未更新任何資料行時呼叫 updateRow 方法,JDBC 驅動程式將會擲回例外狀況訊息:「尚未更新任何資料行時呼叫 updateRow()」。
呼叫 moveToInsertRow 之後,如果在結果集上呼叫 get<Type>、update<Type>、insertRow 和資料指標定位方法(包括 moveToCurrentRow)以外的任何方法,則會擲回例外。 moveToInsertRow 方法會使結果集進入插入模式,而游標定位方法則會結束插入模式。 相對游標定位呼叫會將游標移動到相對於呼叫 moveToInsertRow 之前所在位置的位置。 在游標定位呼叫之後,游標最終的目標位置會成為新的游標位置。
如果在插入模式不成功時進行資料指標定位呼叫,呼叫失敗之後的資料指標位置會是呼叫 moveToInsetRow 之前的原始資料指標位置。 如果 insertRow 失敗,游標會維持在插入列上,且仍處於插入模式。
插入資料列中的資料行一開始會處於未初始化的狀態。 呼叫 update<Type> 方法會將資料行狀態設定為已初始化。 針對未初始化的資料行呼叫 get<Type> 方法會擲回例外狀況。 insertRow 方法的呼叫會將插入資料列中的所有資料行返回到未初始化的狀態。
如果在呼叫 insertRow 方法時未初始化任何資料行,則會插入資料行的預設值。 如果沒有預設值,但資料行可為空值,則會插入 NULL。 如果沒有預設值,而且資料行不可為空值,則伺服器會傳回錯誤,並引發例外狀況。
注意
getRow 方法的呼叫在插入模式時會傳回 0。
JDBC 驅動程式不支援定位更新或刪除。 根據 JDBC 規格,setCursorName 方法沒有效果,而 getCursorName 方法將會擲回例外狀況 (如果呼叫的話)。
唯讀和靜態游標永遠無法更新。
SQL Server 將伺服器游標限制為單一結果集。 如果某個批次或預存程序包含多個陳述式,則必須使用順向唯讀的用戶端游標。