W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎勵
DECLARE — 定義一個游標(biāo)
DECLAREname
[ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FORquery
DECLARE
允許用戶創(chuàng)建游標(biāo), 游標(biāo)可以被用來在大型查詢暫停時檢索少量的行。游標(biāo)被創(chuàng)建后, 可以用FETCH從中取得行。
這個頁面描述在 SQL 命令層面上游標(biāo)的用法。如果想要在 PL/pgSQL函數(shù)中使用游標(biāo),其規(guī)則是不同的 — 詳見第 42.7 節(jié)。
name
要創(chuàng)建的游標(biāo)的名稱。
BINARY
讓游標(biāo)返回二進(jìn)制數(shù)據(jù)而不是返回文本格式數(shù)據(jù)。
INSENSITIVE
指示從游標(biāo)中檢索數(shù)據(jù)的過程不受游標(biāo)創(chuàng)建之后在其底層表上發(fā)生的更新的 影響。在PostgreSQL中,這是默認(rèn)的 行為。因此這個關(guān)鍵詞沒有實(shí)際效果,僅僅被用于兼容 SQL 標(biāo)準(zhǔn)。
SCROLL
NO SCROLL
SCROLL
指定游標(biāo)可以用非順序(例如,反向) 的方式從中檢索行。根據(jù)查詢的執(zhí)行計(jì)劃的復(fù)雜度,指定 SCROLL
可能導(dǎo)致查詢執(zhí)行時間上的性能損失。 NO SCROLL
指定游標(biāo)不能以非順序的方式從中檢索 行。默認(rèn)是允許在某些情況下滾動,但這和指定 SCROLL
不完全相同。詳情請見本文中的注意事項(xiàng)。
WITH HOLD
WITHOUT HOLD
WITH HOLD
指定該游標(biāo)在創(chuàng)建它的事務(wù)提交 之后還能被繼續(xù)使用。WITHOUT HOLD
指定該游標(biāo) 不能在創(chuàng)建它的事務(wù)之外使用。如果兩者都沒有指定,則默認(rèn)為 WITHOUT HOLD
。
query
關(guān)鍵詞BINARY
、 INSENSITIVE
和SCROLL
可以以任意順序出現(xiàn)。
普通游標(biāo)以文本格式返回數(shù)據(jù),這和SELECT
產(chǎn)生的數(shù)據(jù)一樣。 BINARY
選項(xiàng)指定游標(biāo)應(yīng)該以二進(jìn)制格式返回數(shù)據(jù)。這減少了服務(wù) 器和客戶端的轉(zhuǎn)換負(fù)擔(dān),但程序員需要付出更多工作來處理與平臺相關(guān)的二進(jìn)制 數(shù)據(jù)格式。例如,如果一個查詢從一個整數(shù)列中返回一個值一,用一個默認(rèn)游標(biāo) 將得到一個字符串1
,而使用一個二進(jìn)制游標(biāo)將得到該值的四字節(jié)
內(nèi)部表示(big-endian 大端字節(jié)順序)。
使用二進(jìn)制游標(biāo)時應(yīng)該小心。很多應(yīng)用(包括 psql)還沒有準(zhǔn)備好處理二進(jìn)制游標(biāo), 它們?nèi)匀黄诖龜?shù)據(jù)以文本格式到來。
當(dāng)客戶端應(yīng)用使用“擴(kuò)展查詢”協(xié)議發(fā)出一個 FETCH
命令,綁定協(xié)議消息會指定使用文本還是 二進(jìn)制格式檢索數(shù)據(jù)。這種選擇會覆蓋定義游標(biāo)時指定的方式。因此 在使用擴(kuò)展查詢協(xié)議時,這樣一個二進(jìn)制游標(biāo)的概念實(shí)際是被廢棄的 — 任何游標(biāo)都可以被視作文本或者二進(jìn)制。
除非指定了WITH HOLD
,這個命令創(chuàng)建的游標(biāo) 只能在當(dāng)前事務(wù)中使用。因此,沒有WITH HOLD
的DECLARE
在事務(wù)塊外是沒有用的:游標(biāo)只會生存 到該語句結(jié)束。因此如果這種命令在事務(wù)塊之外被使用, PostgreSQL會報告一個錯誤。 定義事務(wù)塊需要使用
BEGIN
和 COMMIT(或者ROLLBACK)。
如果指定了WITH HOLD
并且創(chuàng)建游標(biāo)的事務(wù) 成功提交,在同一個會話中的后續(xù)事務(wù)中還能夠繼續(xù)訪問該游標(biāo)( 但是如果創(chuàng)建事務(wù)被中止,游標(biāo)會被移除)。一個用 WITH HOLD
創(chuàng)建的游標(biāo)可以用一個顯式的 CLOSE
命令關(guān)閉,或者會話結(jié)束時它 也會被關(guān)閉。在當(dāng)前的實(shí)現(xiàn)中,由一個被保持游標(biāo)表示的行會被復(fù) 制到一個臨時文件或者內(nèi)存區(qū)域中,這樣它們才會在后續(xù)事務(wù)中保
持可用。
當(dāng)查詢包括FOR UPDATE
或FOR SHARE
時, 不能指定WITH HOLD
。
在定義一個將被反向取元組的游標(biāo)時,應(yīng)該指定SCROLL
選項(xiàng)。這是 SQL 標(biāo)準(zhǔn)所要求的。不過,為了和早期版本兼容, 如果游標(biāo)的查詢計(jì)劃足夠簡單到支持它不需要額外的開銷, PostgreSQL會允許在沒有 SCROLL
的情況下反向取元組。不過,建議應(yīng)用開發(fā)者 不要依賴于從沒有用SCROLL
創(chuàng)建的游標(biāo)中反向取
元組。如果指定了NO SCROLL
,那么任何情況下都不 允許反向取元組。
當(dāng)查詢包括FOR UPDATE
或FOR SHARE
時, 也不允許反向取元組。因此在這種情況下不能指定 SCROLL
。
如果可滾動和WITH HOLD
游標(biāo)調(diào)用了任何不穩(wěn)定的 函數(shù)(見第 37.7 節(jié)),它們可能給出預(yù)期之外 的結(jié)果。當(dāng)重新取得一個之前取得過的行時,那些函數(shù)會被重新執(zhí)行,這 可能導(dǎo)致得到與第一次不同的結(jié)果。對這類情況的一種變通方法是,聲明 游標(biāo)為WITH HOLD
并且在從其中讀取任何行之前提交
事務(wù)。這將強(qiáng)制該游標(biāo)的整個輸出被物化在臨時存儲中,這樣針對每一行 只會執(zhí)行一次不穩(wěn)定函數(shù)。
如果游標(biāo)的查詢包括FOR UPDATE
或者FOR
SHARE
,那么被返回的行會在它們第一次被取得時被鎖定,這和帶有 這些選項(xiàng)的常規(guī)SELECT命令一樣。此外,被返回的 行將是最新的版本,因此這些選項(xiàng)提供了被 SQL 標(biāo)準(zhǔn)稱為 “敏感游標(biāo)”的等效體(把
INSENSITIVE
與 FOR UPDATE
或者FOR SHARE
一起指定是錯誤)。
如果游標(biāo)要和UPDATE ... WHERE CURRENT OF
或者 DELETE ... WHERE CURRENT OF
一起使用,通常推薦 使用FOR UPDATE
。使用FOR UPDATE
可以 阻止其他會話在行被取得和被更新之間修改行。如果沒有 FOR UPDATE
,當(dāng)行在游標(biāo)創(chuàng)建后被更改后,一個后續(xù)的
WHERE CURRENT OF
命令將不會產(chǎn)生效果。
另一個使用FOR UPDATE
的原因是,如果沒有它,當(dāng)游標(biāo)查詢不符合 SQL 標(biāo)準(zhǔn)的“簡單可更新”規(guī)則時,后續(xù)的 WHERE CURRENT OF
可能會失敗(特別地,該游標(biāo)必須只引用一個 表并且沒有使用分組或者ORDER BY
)。不是簡單可更新的游標(biāo)可能
成功也可能不成功,這取決于計(jì)劃選擇的細(xì)節(jié)。因此在最壞的情況下,應(yīng)用可能會 在測試時成功但是在生產(chǎn)中失敗。如果指定了FOR UPDATE
, 則保證游標(biāo)是可更新的。
不把FOR UPDATE
和WHERE CURRENT OF
一起用的 主要原因是,需要游標(biāo)時可滾動的或者對于后續(xù)更新不敏感(也就是說,繼續(xù)顯示 舊的數(shù)據(jù))。如果這是你的需求,應(yīng)密切關(guān)注安上述警示。
SQL 標(biāo)準(zhǔn)只對嵌入式SQL中的游標(biāo)做出了規(guī)定。 PostgreSQL服務(wù)器沒有為游標(biāo)實(shí)現(xiàn) OPEN
語句。當(dāng)游標(biāo)被聲明時就被認(rèn)為已經(jīng) 被打開。不過,ECPG( PostgreSQL的嵌入式
SQL 預(yù)處理器) 支持標(biāo)準(zhǔn) SQL 游標(biāo)習(xí)慣,包括那些DECLARE
和OPEN
語句。
你可以通過查詢pg_cursors
系統(tǒng)視圖可以看到所有可用的游標(biāo)。
SQL 標(biāo)準(zhǔn)認(rèn)為游標(biāo)是否默認(rèn)對底層數(shù)據(jù)的并發(fā)更新敏感是與實(shí)現(xiàn)相關(guān)的。在 PostgreSQL中,默認(rèn)游標(biāo)對此是不敏 感的,并且可以通過指定FOR UPDATE
讓它變得對此敏感。其他 產(chǎn)品的行為可能有所不同。
SQL 標(biāo)準(zhǔn)只允許在嵌入式SQL和模塊中使用游標(biāo)。 PostgreSQL允許以交互的方式使用游標(biāo)。
二進(jìn)制游標(biāo)是一種PostgreSQL 擴(kuò)展。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: