支援的版本: 目前 (17) / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

DECLARE

DECLARE — 定義游標

概要

DECLARE name [ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ]
    CURSOR [ { WITH | WITHOUT } HOLD ] FOR query

描述

DECLARE 允許使用者建立游標,游標可用於一次從較大的查詢中檢索少量列。 建立游標後,使用 FETCH 從游標中提取列。

注意

本頁描述了在 SQL 指令層級使用游標。 如果您嘗試在 PL/pgSQL 函式中使用游標,則規則有所不同 — 請參閱 第 41.7 節

參數

name

要建立的游標名稱。 這必須與工作階段中任何其他活動游標名稱不同。

BINARY

使游標以二進位而非文字格式傳回資料。

ASENSITIVE
INSENSITIVE

游標靈敏度決定了在宣告游標之後,在同一交易中對游標底層資料所做的變更是否在游標中可見。 INSENSITIVE 表示它們不可見,ASENSITIVE 表示行為取決於實作。 第三種行為 SENSITIVE 表示此類變更在游標中可見,但在 PostgreSQL 中不可用。 在 PostgreSQL 中,所有游標都不敏感; 因此,這些關鍵字沒有任何作用,僅為了與 SQL 標準相容而被接受。

INSENSITIVEFOR UPDATEFOR SHARE 一起指定是錯誤的。

SCROLL
NO SCROLL

SCROLL 指定游標可用於以非循序方式 (例如,向後) 檢索列。 根據查詢執行計畫的複雜性,指定 SCROLL 可能會對查詢的執行時間產生效能影響。 NO SCROLL 指定游標不能用於以非循序方式檢索列。 預設情況下,允許在某些情況下捲動; 這與指定 SCROLL 不同。 有關詳細資訊,請參閱下面的備註

WITH HOLD
WITHOUT HOLD

WITH HOLD 指定在成功提交建立它的交易後,可以繼續使用游標。 WITHOUT HOLD 指定游標不能在建立它的交易之外使用。 如果未指定 WITHOUT HOLD 也未指定 WITH HOLD,則預設為 WITHOUT HOLD

query

一個 SELECTVALUES 指令,它將提供要由游標傳回的列。

關鍵字 ASENSITIVEBINARYINSENSITIVESCROLL 可以以任何順序出現。

備註

一般游標以文字格式傳回資料,與 SELECT 產生的資料相同。 BINARY 選項指定游標應以二進位格式傳回資料。 這減少了伺服器和用戶端的轉換工作量,但代價是程式設計師需要付出更多努力來處理與平台相關的二進位資料格式。 例如,如果查詢從整數欄傳回值 1,您將使用預設游標取得字串 1,而使用二進位游標,您將取得一個 4 位元組的欄位,其中包含該值的內部表示形式 (以大端位元組順序)。

應小心使用二進位游標。 許多應用程式,包括 psql,尚未準備好處理二進位游標,並且期望資料以文字格式傳回。

注意

當用戶端應用程式使用擴充查詢協定發出 FETCH 指令時,「繫結」協定訊息會指定是以文字還是二進位格式檢索資料。 此選擇會覆蓋定義游標的方式。 因此,在使用擴充查詢協定時,二進位游標的概念已經過時 — 任何游標都可以被視為文字或二進位。

除非指定 WITH HOLD,否則此指令建立的游標只能在目前交易中使用。 因此,沒有 WITH HOLDDECLARE 在交易區塊之外毫無用處:游標只會存活到語句完成。 因此,如果在交易區塊之外使用此類指令,PostgreSQL 會報告錯誤。 使用 BEGINCOMMIT (或 ROLLBACK) 來定義交易區塊。

如果指定了 WITH HOLD 並且建立游標的交易成功提交,則後續交易可以在同一工作階段中繼續存取該游標。(但如果建立交易中止,則游標將被移除。)使用 WITH HOLD 建立的游標會在對其發出明確的 CLOSE 指令或工作階段結束時關閉。 在目前的實作中,由保留游標表示的列被複製到臨時檔案或記憶體區域中,以便它們對於後續交易仍然可用。

當查詢包含 FOR UPDATEFOR SHARE 時,不可指定 WITH HOLD

在定義將用於向後提取資料的游標時,應指定 SCROLL 選項。這是 SQL 標準的要求。然而,為了與早期版本相容,如果游標的查詢計畫夠簡單,不需要額外負擔來支援向後提取,PostgreSQL 允許在沒有 SCROLL 的情況下進行向後提取。然而,建議應用程式開發人員不要依賴於從未用 SCROLL 建立的游標進行向後提取。如果指定 NO SCROLL,則在任何情況下都不允許向後提取。

當查詢包含 FOR UPDATEFOR SHARE 時,也不允許向後提取;因此在這種情況下,不可指定 SCROLL

注意

如果可捲動游標調用任何不穩定的函式(請參閱 第 36.7 節),可能會產生意想不到的結果。當重新提取先前提取的列時,函式可能會重新執行,從而可能導致與第一次不同的結果。最好為涉及不穩定函式的查詢指定 NO SCROLL。如果這不可行,一種變通方法是宣告游標為 SCROLL WITH HOLD,並在從中讀取任何列之前提交交易。這將強制將游標的整個輸出具體化到臨時儲存空間中,以便每個列僅執行一次不穩定的函式。

如果游標的查詢包含 FOR UPDATEFOR SHARE,則返回的列在第一次提取時會被鎖定,與具有這些選項的常規 SELECT 命令相同。此外,返回的列將是最新的版本。

注意

通常建議在使用 UPDATE ... WHERE CURRENT OFDELETE ... WHERE CURRENT OF 時使用 FOR UPDATE。使用 FOR UPDATE 可防止其他會話在提取列和更新列之間更改列。如果沒有 FOR UPDATE,如果列自建立游標以來已更改,則後續的 WHERE CURRENT OF 命令將不起作用。

使用 FOR UPDATE 的另一個原因是,如果游標查詢不符合 SQL 標準中關於成為簡單可更新的規則(尤其是,游標必須僅引用一個表,並且不使用分組或 ORDER BY),則後續的 WHERE CURRENT OF 可能會失敗。不是簡單可更新的游標可能會起作用,也可能不起作用,具體取決於計畫選擇的細節;因此,在最壞的情況下,應用程式可能在測試中起作用,然後在生產中失敗。如果指定了 FOR UPDATE,則保證游標是可更新的。

不使用 FOR UPDATEWHERE CURRENT OF 的主要原因是,如果您需要游標是可捲動的,或者與並行更新隔離(即,繼續顯示舊資料)。如果這是一個要求,請密切注意上面顯示的注意事項。

SQL 標準僅為嵌入式游標提供規定SQLPostgreSQL 伺服器不實現游標的 OPEN 語句;游標在宣告時被認為是開啟的。然而,ECPGPostgreSQL 的嵌入式 SQL 預處理器,支援標準 SQL 游標慣例,包括涉及 DECLAREOPEN 語句的慣例。

開放游標底層的伺服器資料結構稱為 portal(入口)。入口名稱在客戶端協議中公開:如果客戶端知道入口名稱,則可以直接從開放入口提取列。使用 DECLARE 建立游標時,入口名稱與游標名稱相同。

您可以透過查詢 pg_cursors 系統檢視來查看所有可用的游標。

範例

宣告游標

DECLARE liahona CURSOR FOR SELECT * FROM films;

有關游標用法的更多範例,請參閱 FETCH

相容性

SQL 標準僅允許嵌入式游標SQL和模組中的游標。PostgreSQL 允許以互動方式使用游標。

根據 SQL 標準,透過 UPDATE ... WHERE CURRENT OFDELETE ... WHERE CURRENT OF 語句對不敏感游標所做的更改在同一個游標中是可見的。PostgreSQL 將這些語句視為所有其他資料變更語句,它們在不敏感游標中不可見。

二進位游標是 PostgreSQL 的擴充功能。

另請參閱

CLOSEFETCHMOVE

提交更正

如果您在文件中看到任何不正確、與您使用特定功能的經驗不符或需要進一步說明的內容,請使用此表格來報告文件問題。