42.7. ÐÑÑÑоÑÑ #
ÐмеÑÑо Ñого ÑÑÐ¾Ð±Ñ ÑÑÐ°Ð·Ñ Ð²ÑполнÑÑÑ Ð²ÐµÑÑ Ð·Ð°Ð¿ÑоÑ, еÑÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð½Ð°ÑÑÑоиÑÑ ÐºÑÑÑоÑ, инкапÑÑлиÑÑÑÑий запÑоÑ, и заÑем полÑÑаÑÑ ÑезÑлÑÑÐ°Ñ Ð·Ð°Ð¿ÑоÑа по неÑколÑÐºÑ ÑÑÑок за Ñаз. Ðдна из пÑиÑин Ñак делаÑÑ Ð·Ð°ÐºÐ»ÑÑаеÑÑÑ Ð² Ñом, ÑÑÐ¾Ð±Ñ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ Ð¿ÐµÑÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼ÑÑи, когда ÑезÑлÑÑÐ°Ñ ÑодеÑÐ¶Ð¸Ñ Ð±Ð¾Ð»ÑÑое колиÑеÑÑво ÑÑÑок. (ÐолÑзоваÑелÑм PL/pgSQL не нÑжно об ÑÑом беÑпокоиÑÑÑÑ, Ñак как ÑÐ¸ÐºÐ»Ñ FOR авÑомаÑиÑеÑки иÑполÑзÑÑÑ ÐºÑÑÑоÑÑ, ÑÑÐ¾Ð±Ñ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ Ð¿Ñоблем Ñ Ð¿Ð°Ð¼ÑÑÑÑ.) Ðолее инÑеÑеÑнÑм ваÑианÑом иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑвлÑеÑÑÑ Ð²Ð¾Ð·Ð²ÑÐ°Ñ Ð¸Ð· ÑÑнкÑии ÑÑÑлки на кÑÑÑоÑ, ÑÑо позволÑÐµÑ Ð²ÑзÑваÑÑÐµÐ¼Ñ Ð¿Ð¾Ð»ÑÑаÑÑ ÑÑÑоки запÑоÑа. ÐÑо ÑÑÑекÑивнÑй ÑпоÑоб полÑÑаÑÑ Ð±Ð¾Ð»ÑÑие набоÑÑ ÑÑÑок из ÑÑнкÑий.
42.7.1. ÐбÑÑвление кÑÑÑоÑнÑÑ Ð¿ÐµÑеменнÑÑ #
ÐоÑÑÑп к кÑÑÑоÑам в PL/pgSQL оÑÑÑеÑÑвлÑеÑÑÑ ÑеÑез кÑÑÑоÑнÑе пеÑеменнÑе, коÑоÑÑе вÑегда имеÑÑ ÑпеÑиалÑнÑй Ñип даннÑÑ
refcursor. Ðдин из ÑпоÑобов ÑоздаÑÑ ÐºÑÑÑоÑнÑÑ Ð¿ÐµÑеменнÑÑ, пÑоÑÑо обÑÑвиÑÑ ÐµÑ ÐºÐ°Ðº пеÑеменнÑÑ Ñипа refcursor. ÐÑÑгой ÑпоÑоб заклÑÑаеÑÑÑ Ð² иÑполÑзовании ÑинÑакÑиÑа обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÑÑÑоÑа, коÑоÑÑй в обÑем виде вÑглÑÐ´Ð¸Ñ Ñак:
имÑ[ [ NO ] SCROLL ] CURSOR [ (аÑгÑменÑÑ) ] FORзапÑоÑ;
(ÐÐ»Ñ ÑовмеÑÑимоÑÑи Ñ Oracle, FOR можно заменÑÑÑ Ð½Ð° IS.) С Ñказанием SCROLL кÑÑÑÐ¾Ñ Ð¼Ð¾Ð¶Ð½Ð¾ бÑÐ´ÐµÑ Ð¿ÑокÑÑÑиваÑÑ Ð½Ð°Ð·Ð°Ð´. ÐÑи NO SCROLL пÑокÑÑÑка назад не ÑазÑеÑаеÑÑÑ. ÐÑли ниÑего не Ñказано, Ñо возможноÑÑÑ Ð¿ÑокÑÑÑки назад завиÑÐ¸Ñ Ð¾Ñ Ð·Ð°Ð¿ÑоÑа. ÐÑли ÑÐºÐ°Ð·Ð°Ð½Ñ Ð°ÑгÑменÑÑ, Ñо они Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑедÑÑавлÑÑÑ Ñобой паÑÑ , ÑазделÑннÑе ÑеÑез запÑÑÑÑ. ÐÑи паÑÑ Ð¾Ð¿ÑеделÑÑÑ Ð¸Ð¼ÐµÐ½Ð°, коÑоÑÑе бÑдÑÑ Ð·Ð°Ð¼ÐµÐ½ÐµÐ½Ñ Ð·Ð½Ð°ÑениÑми паÑамеÑÑов в данном запÑоÑе. ФакÑиÑеÑкие знаÑÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÐ½Ñ ÑÑиÑ
имÑн поÑвÑÑÑÑ Ð¿Ð¾Ð·Ð¶Ðµ, пÑи оÑкÑÑÑии кÑÑÑоÑа.Ð¸Ð¼Ñ Ñип_даннÑÑ
ÐÑимеÑÑ:
DECLARE
curs1 refcursor;
curs2 CURSOR FOR SELECT * FROM tenk1;
curs3 CURSOR (key integer) FOR SELECT * FROM tenk1 WHERE unique1 = key; ÐÑе ÑÑи пеÑеменнÑе имеÑÑ Ñип даннÑÑ
refcursor. ÐеÑÐ²Ð°Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ÑполÑзована Ñ Ð»ÑбÑм запÑоÑом, вÑоÑÐ°Ñ ÑвÑзана (bound) Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ ÑÑоÑмиÑованнÑм запÑоÑом, а поÑледнÑÑ ÑвÑзана Ñ Ð¿Ð°ÑамеÑÑизованнÑм запÑоÑом. (key бÑÐ´ÐµÑ Ð·Ð°Ð¼ÐµÐ½Ñн ÑелоÑиÑленнÑм знаÑением паÑамеÑÑа пÑи оÑкÑÑÑии кÑÑÑоÑа.) ÐÑо пеÑеменнÑÑ curs1 говоÑÑÑ, ÑÑо она ÑвлÑеÑÑÑ Ð½ÐµÑвÑзанной (unbound), Ñак как к ней не пÑивÑзан никакой запÑоÑ.
ÐаÑамеÑÑ SCROLL нелÑÐ·Ñ Ð¸ÑполÑзоваÑÑ, еÑли в запÑоÑе кÑÑÑоÑа иÑполÑзÑеÑÑÑ FOR UPDATE/SHARE. ÐÑоме Ñого, Ñ Ð·Ð°Ð¿ÑоÑом, вклÑÑаÑÑим изменÑивÑе ÑÑнкÑии, лÑÑÑе вÑего иÑполÑзоваÑÑ NO SCROLL. РеализаÑÐ¸Ñ SCROLL пÑедполагаеÑ, ÑÑо повÑоÑное ÑÑение вÑвода запÑоÑа даÑÑ ÑоглаÑованнÑе ÑезÑлÑÑаÑÑ, Ñего нелÑÐ·Ñ Ð³Ð°ÑанÑиÑоваÑÑ Ð¿Ñи иÑполÑзовании изменÑивой ÑÑнкÑии.
42.7.2. ÐÑкÑÑÑие кÑÑÑоÑа #
ÐÑежде Ñем полÑÑаÑÑ ÑÑÑоки из кÑÑÑоÑа, его нÑжно оÑкÑÑÑÑ. (ÐÑо ÑквиваленÑно дейÑÑÐ²Ð¸Ñ SQL-ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ DECLARE CURSOR.) Ð PL/pgSQL еÑÑÑ ÑÑи ÑоÑÐ¼Ñ Ð¾Ð¿ÐµÑаÑоÑа OPEN, две из коÑоÑÑÑ
иÑполÑзÑÑÑÑÑ Ð´Ð»Ñ Ð½ÐµÑвÑзаннÑÑ
кÑÑÑоÑнÑÑ
пеÑеменнÑÑ
, а ÑÑеÑÑÑ Ð´Ð»Ñ ÑвÑзаннÑÑ
.
ÐÑимеÑание
СвÑзаннÑе кÑÑÑоÑнÑе пеÑеменнÑе можно иÑполÑзоваÑÑ Ñ Ñиклом FOR без Ñвного оÑкÑÑÑÐ¸Ñ ÐºÑÑÑоÑа, как опиÑано в ÐодÑазделе 42.7.4. Цикл FOR оÑкÑÐ¾ÐµÑ ÐºÑÑÑоÑ, а заÑем закÑÐ¾ÐµÑ ÐµÐ³Ð¾ по завеÑÑении Ñикла.
ÐÑкÑÑÑие кÑÑÑоÑа подÑазÑÐ¼ÐµÐ²Ð°ÐµÑ Ñоздание внÑÑÑенней Ð´Ð»Ñ ÑеÑвеÑа ÑÑÑÑкÑÑÑÑ Ð´Ð°Ð½Ð½ÑÑ Ð¿Ð¾Ð´ названием поÑÑал, коÑоÑÑй ÑдеÑÐ¶Ð¸Ð²Ð°ÐµÑ ÑоÑÑоÑние вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑа кÑÑÑоÑа. У поÑÑала еÑÑÑ Ð¸Ð¼Ñ, коÑоÑое должно бÑÑÑ ÑникалÑнÑм в ÑÐ°Ð¼ÐºÐ°Ñ ÑеанÑа на пÑоÑÑжении ÑÑÑеÑÑÐ²Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÑÑала. Ðо ÑмолÑÐ°Ð½Ð¸Ñ PL/pgSQL пÑиÑÐ²Ð°Ð¸Ð²Ð°ÐµÑ ÑникалÑное Ð¸Ð¼Ñ ÑÐ¾Ð·Ð´Ð°Ð²Ð°ÐµÐ¼Ð¾Ð¼Ñ Ð¸Ð¼ поÑÑалÑ. Ðднако еÑли пÑиÑвоиÑÑ Ð¿ÐµÑеменной кÑÑÑоÑа непÑÑÑое ÑÑÑоковое знаÑение, в каÑеÑÑве имени поÑÑала бÑÐ´ÐµÑ Ð¸ÑполÑзовано именно оно. ÐÑполÑзование ÑÑой ÑÑнкÑионалÑноÑÑи опиÑано в ÐодÑазделе 42.7.3.5.
42.7.2.1. OPEN FOR query #
OPENнеÑвÑзаннаÑ_пеÑеменнаÑ_кÑÑÑоÑа[[NO] SCROLL] FORquery;
ÐÑÑÑоÑÐ½Ð°Ñ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¾ÑкÑÑваеÑÑÑ Ð¸ полÑÑÐ°ÐµÑ ÐºÐ¾Ð½ÐºÑеÑнÑй запÑÐ¾Ñ Ð´Ð»Ñ Ð²ÑполнениÑ. ÐÑÑÑÐ¾Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ñже бÑÑÑ Ð¾ÑкÑÑÑÑм, а кÑÑÑоÑÐ½Ð°Ñ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¾Ð±Ñзана бÑÑÑ Ð½ÐµÑвÑзанной (Ñо еÑÑÑ Ð¿ÑоÑÑо пеÑеменной Ñипа refcursor). ÐапÑÐ¾Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ бÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹ SELECT или лÑбой дÑÑгой, коÑоÑÐ°Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ ÑÑÑоки (к пÑимеÑÑ EXPLAIN). ÐапÑÐ¾Ñ Ð¾Ð±ÑабаÑÑваеÑÑÑ Ñак же, как и дÑÑгие ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL в PL/pgSQL: имена пеÑеменнÑÑ
PL/pgSQL заменÑÑÑÑÑ Ð½Ð° знаÑениÑ, план запÑоÑа кеÑиÑÑеÑÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð²ÑоÑного иÑполÑзованиÑ. ÐодÑÑановка знаÑений пеÑеменнÑÑ
PL/pgSQL пÑоводиÑÑÑ Ð¿Ñи оÑкÑÑÑии кÑÑÑоÑа командой OPEN, поÑледÑÑÑие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñений пеÑеменнÑÑ
не влиÑÑÑ Ð½Ð° ÑабоÑÑ ÐºÑÑÑоÑа. SCROLL и NO SCROLL имеÑÑ ÑÐ¾Ñ Ð¶Ðµ ÑмÑÑл, ÑÑо и Ð´Ð»Ñ ÑвÑзанного кÑÑÑоÑа.
ÐÑимеÑ:
OPEN curs1 FOR SELECT * FROM foo WHERE key = mykey;
42.7.2.2. OPEN FOR EXECUTE #
OPENнеÑвÑзаннаÑ_пеÑеменнаÑ_кÑÑÑоÑа[[NO] SCROLL] FOR EXECUTEÑÑÑока_запÑоÑа[USINGвÑÑажение[, ...]];
ÐеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ ÐºÑÑÑоÑа оÑкÑÑваеÑÑÑ Ð¸ полÑÑÐ°ÐµÑ ÐºÐ¾Ð½ÐºÑеÑнÑй запÑÐ¾Ñ Ð´Ð»Ñ Ð²ÑполнениÑ. ÐÑÑÑÐ¾Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ñже оÑкÑÑÑ Ð¸ он должен бÑÑÑ Ð¾Ð±ÑÑвлен как неÑвÑÐ·Ð°Ð½Ð½Ð°Ñ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ ÐºÑÑÑоÑа (Ñо еÑÑÑ, как пÑоÑÑо пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ refcursor). ÐапÑÐ¾Ñ Ð·Ð°Ð´Ð°ÑÑÑÑ ÑÑÑоковÑм вÑÑажением, Ñак же, как в команде EXECUTE. Ðак обÑÑно, ÑÑо даÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð³Ð¸Ð±ÐºÐ¾ менÑÑÑ Ð¿Ð»Ð°Ð½ запÑоÑа Ð¾Ñ Ñаза к ÑÐ°Ð·Ñ (Ñм. ÐодÑаздел 42.11.2). ÐÑо Ñакже ознаÑаеÑ, ÑÑо замена пеÑеменнÑÑ
пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð½Ðµ в Ñамой ÑÑÑоке командÑ. Ðак и Ñ EXECUTE, знаÑÐµÐ½Ð¸Ñ Ð¿Ð°ÑамеÑÑов вÑÑавлÑÑÑÑÑ Ð² динамиÑеÑкÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ, иÑполÑзÑÑ format() и USING. ÐаÑамеÑÑÑ SCROLL и NO SCROLL здеÑÑ Ð´ÐµÐ¹ÑÑвÑÑÑ Ñак же, как и Ñо ÑвÑзаннÑм кÑÑÑоÑом.
ÐÑимеÑ:
OPEN curs1 FOR EXECUTE format('SELECT * FROM %I WHERE col1 = $1',tabname) USING keyvalue; Ð ÑÑом пÑимеÑе в ÑекÑÑ Ð·Ð°Ð¿ÑоÑа вÑÑавлÑеÑÑÑ Ð¸Ð¼Ñ ÑаблиÑÑ Ñ Ð¿Ñименением format(). ÐнаÑение, ÑÑавниваемое Ñ col1, вÑÑавлÑеÑÑÑ Ð¿Ð¾ÑÑедÑÑвом паÑамеÑÑа USING, Ñак ÑÑо заклÑÑаÑÑ ÐµÐ³Ð¾ в апоÑÑÑоÑÑ Ð½Ðµ нÑжно.
42.7.2.3. ÐÑкÑÑÑие ÑвÑзанного кÑÑÑоÑа #
OPENÑвÑзаннаÑ_пеÑеменнаÑ_кÑÑÑоÑа[( [имÑ_аÑгÑменÑа:=]знаÑение_аÑгÑменÑа[, ...] )];
ÐÑа ÑоÑма OPEN иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¾ÑкÑÑÑÐ¸Ñ ÐºÑÑÑоÑной пеÑеменной, коÑоÑÐ°Ñ Ð±Ñла ÑвÑзана Ñ Ð·Ð°Ð¿ÑоÑом пÑи обÑÑвлении. ÐÑÑÑÐ¾Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ñже бÑÑÑ Ð¾ÑкÑÑÑÑм. СпиÑок ÑакÑиÑеÑкиÑ
знаÑений аÑгÑменÑов должен пÑиÑÑÑÑÑвоваÑÑ ÑолÑко в Ñом ÑлÑÑае, еÑли кÑÑÑÐ¾Ñ Ð¾Ð±ÑÑвлÑлÑÑ Ñ Ð¿Ð°ÑамеÑÑами. ÐÑи знаÑÐµÐ½Ð¸Ñ Ð±ÑдÑÑ Ð¿Ð¾Ð´ÑÑÐ°Ð²Ð»ÐµÐ½Ñ Ð² запÑоÑ.
Ðлан запÑоÑа Ð´Ð»Ñ ÑвÑзанного кÑÑÑоÑа вÑегда ÑÑиÑаеÑÑÑ ÐºÐµÑиÑÑемÑм. Ð ÑÑом ÑлÑÑае Ð½ÐµÑ ÑквиваленÑа EXECUTE. ÐбÑаÑиÑе внимание, ÑÑо SCROLL и NO SCROLL не могÑÑ Ð±ÑÑÑ ÑÐºÐ°Ð·Ð°Ð½Ñ Ð² ÑÑой ÑоÑме OPEN, возможноÑÑÑ Ð¿ÑокÑÑÑки назад бÑла опÑеделена пÑи обÑÑвлении кÑÑÑоÑа.
ÐÑи пеÑедаÑе знаÑений аÑгÑменÑов можно иÑполÑзоваÑÑ Ð¿Ð¾Ð·Ð¸ÑионнÑÑ Ð¸Ð»Ð¸ именнÑÑ Ð½Ð¾ÑаÑиÑ. РпозиÑионной ноÑаÑии вÑе аÑгÑменÑÑ ÑказÑваÑÑÑÑ Ð¿Ð¾ поÑÑдкÑ. Рименной ноÑаÑии Ð¸Ð¼Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ аÑгÑменÑа оÑделÑеÑÑÑ Ð¾Ñ Ð²ÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð°ÑгÑменÑа Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ :=. ÐÑо подобно вÑÐ·Ð¾Ð²Ñ ÑÑнкÑий, опиÑÐ°Ð½Ð½Ð¾Ð¼Ñ Ð² Разделе 4.3. Также ÑазÑеÑаеÑÑÑ ÑмеÑиваÑÑ Ð¿Ð¾Ð·Ð¸ÑионнÑÑ Ð¸ именнÑÑ Ð½Ð¾ÑаÑии.
ÐÑимеÑÑ (здеÑÑ Ð¸ÑполÑзÑÑÑÑÑ Ñанее обÑÑвленнÑе кÑÑÑоÑÑ):
OPEN curs2; OPEN curs3(42); OPEN curs3(key := 42);
Так как Ð´Ð»Ñ ÑвÑзанного кÑÑÑоÑа вÑполнÑеÑÑÑ Ð¿Ð¾Ð´ÑÑановка знаÑений пеÑеменнÑÑ
, Ñо, на Ñамом деле, ÑÑÑеÑÑвÑÐµÑ Ð´Ð²Ð° ÑпоÑоба пеÑедаÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð² кÑÑÑоÑ. Ðибо иÑполÑзоваÑÑ ÑвнÑе аÑгÑменÑÑ Ð² OPEN, либо неÑвно, ÑÑÑлаÑÑÑ Ð½Ð° пеÑеменнÑе PL/pgSQL в запÑоÑе. Ð ÑвÑзанном кÑÑÑоÑе можно ÑÑÑлаÑÑÑÑ ÑолÑко на Ñе пеÑеменнÑе, коÑоÑÑе бÑли обÑÑÐ²Ð»ÐµÐ½Ñ Ð´Ð¾ Ñамого кÑÑÑоÑа. РлÑбом ÑлÑÑае знаÑение пеÑеменной Ð´Ð»Ñ Ð¿Ð¾Ð´ÑÑановки в запÑÐ¾Ñ Ð±ÑÐ´ÐµÑ Ð¾Ð¿ÑеделÑÑÑÑÑ Ð½Ð° Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ OPEN. ÐÐ¾Ñ ÐµÑÑ Ð¾Ð´Ð¸Ð½ ÑпоÑоб полÑÑиÑÑ ÑÐ¾Ñ Ð¶Ðµ ÑезÑлÑÑÐ°Ñ Ñ curs3, как в пÑимеÑе вÑÑе:
DECLARE
key integer;
curs4 CURSOR FOR SELECT * FROM tenk1 WHERE unique1 = key;
BEGIN
key := 42;
OPEN curs4;42.7.3. ÐÑполÑзование кÑÑÑоÑов #
ÐоÑле Ñого как кÑÑÑÐ¾Ñ Ð±ÑÐ´ÐµÑ Ð¾ÑкÑÑÑ, Ñ Ð½Ð¸Ð¼ можно ÑабоÑаÑÑ Ð¿Ñи помоÑи опиÑаннÑÑ Ð·Ð´ÐµÑÑ Ð¾Ð¿ÐµÑаÑоÑов.
РабоÑаÑÑ Ñ ÐºÑÑÑоÑом необÑзаÑелÑно в Ñой же ÑÑнкÑии, где он бÑл оÑкÑÑÑ. Ðз ÑÑнкÑии можно веÑнÑÑÑ Ð·Ð½Ð°Ñение Ñ Ñипом refcursor, ÑÑо Ð¿Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ Ð²ÑзÑваÑÑÐµÐ¼Ñ Ð¿ÑодолжиÑÑ ÑабоÑÑ Ñ ÐºÑÑÑоÑом. (ÐнÑÑÑи refcursor пÑедÑÑавлÑÐµÑ Ñобой обÑÑное ÑÑÑоковое Ð¸Ð¼Ñ Ð¿Ð¾ÑÑала, ÑодеÑжаÑего акÑивнÑй запÑÐ¾Ñ ÐºÑÑÑоÑа. ÐÑо Ð¸Ð¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ пеÑедаваÑÑ, пÑиÑваиваÑÑ Ð´ÑÑгим пеÑеменнÑм Ñ Ñипом refcursor и Ñак далее, пÑи ÑÑом поÑÑал не наÑÑÑаеÑÑÑ.)
ÐÑе поÑÑÐ°Ð»Ñ Ð½ÐµÑвно закÑÑваÑÑÑÑ Ð² конÑе ÑÑанзакÑии, поÑÑÐ¾Ð¼Ñ Ð·Ð½Ð°Ñение refcursor можно иÑполÑзоваÑÑ Ð´Ð»Ñ ÑÑÑлки на оÑкÑÑÑÑй кÑÑÑÐ¾Ñ ÑолÑко до конÑа ÑÑанзакÑии.
42.7.3.1. FETCH #
FETCH [напÑавление{ FROM | IN }]кÑÑÑоÑINTOÑелÑ;
FETCH Ð¸Ð·Ð²Ð»ÐµÐºÐ°ÐµÑ ÑледÑÑÑÑÑ ÑÑÑÐ¾ÐºÑ (в Ñказанном напÑавлении) из кÑÑÑоÑа в ÑелÑ. РкаÑеÑÑве Ñели Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿ÐµÑеменнаÑ-коÑÑеж, пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñипа record или ÑазделÑннÑй запÑÑÑми ÑпиÑок пÑоÑÑÑÑ
пеÑеменнÑÑ
, как и в SELECT INTO. ÐÑли подÑ
одÑÑей ÑÑÑоки неÑ, Ñели пÑиÑваиваеÑÑÑ NULL. Ðак и в SELECT INTO, пÑовеÑиÑÑ, бÑла ли полÑÑена запиÑÑ, можно пÑи помоÑи ÑпеÑиалÑной пеÑеменной FOUND. ÐÑли ÑÑÑока не найдена, кÑÑÑÐ¾Ñ ÑÑÑанавливаеÑÑÑ Ð¿Ð¾Ñле поÑледней ÑÑÑоки или пеÑед пеÑвой ÑÑÑокой в завиÑимоÑÑи Ð¾Ñ Ð½Ð°Ð¿ÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ.
ÐдеÑÑ Ð½Ð°Ð¿Ñавление Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð»ÑбÑм допÑÑÑимÑм в SQL-команде FETCH ваÑианÑом, кÑоме ÑеÑ
, ÑÑо извлекаÑÑ Ð±Ð¾Ð»ÐµÐµ одной ÑÑÑоки. Рименно: NEXT, PRIOR, FIRST, LAST, ABSOLUTE ÑиÑло, RELATIVE ÑиÑло, FORWARD или BACKWARD. Ðез ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð½Ð°Ð¿ÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´ÑазÑмеваеÑÑÑ Ð²Ð°ÑÐ¸Ð°Ð½Ñ NEXT. Ðезде, где иÑполÑзÑеÑÑÑ ÑиÑло, оно Ð¼Ð¾Ð¶ÐµÑ Ð¾Ð¿ÑеделÑÑÑÑÑ Ð»ÑбÑм ÑелоÑиÑленнÑм вÑÑажением (в оÑлиÑие Ð¾Ñ SQL-ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ FETCH, допÑÑкаÑÑей ÑолÑко ÑелоÑиÑленнÑе конÑÑанÑÑ). ÐнаÑÐµÐ½Ð¸Ñ Ð½Ð°Ð¿ÑавлениÑ, коÑоÑÑе ÑÑебÑÑÑ Ð¿ÐµÑемеÑÐµÐ½Ð¸Ñ Ð½Ð°Ð·Ð°Ð´, пÑиведÑÑ Ðº оÑибке, еÑли кÑÑÑÐ¾Ñ Ð½Ðµ бÑл обÑÑвлен или оÑкÑÑÑ Ñ Ñказанием SCROLL.
кÑÑÑÐ¾Ñ ÑÑо пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñ Ñипом refcursor, коÑоÑÐ°Ñ ÑÑÑлаеÑÑÑ Ð½Ð° оÑкÑÑÑÑй поÑÑал кÑÑÑоÑа.
ÐÑимеÑÑ:
FETCH curs1 INTO rowvar; FETCH curs2 INTO foo, bar, baz; FETCH LAST FROM curs3 INTO x, y; FETCH RELATIVE -2 FROM curs4 INTO x;
42.7.3.2. MOVE #
MOVE [напÑавление{ FROM | IN }]кÑÑÑоÑ;
MOVE пеÑемеÑÐ°ÐµÑ ÐºÑÑÑÐ¾Ñ Ð±ÐµÐ· извлеÑÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
. MOVE ÑабоÑÐ°ÐµÑ ÑоÑно Ñак же как и FETCH, но пÑи ÑÑом ÑолÑко пеÑемеÑÐ°ÐµÑ ÐºÑÑÑÐ¾Ñ Ð¸ не Ð¸Ð·Ð²Ð»ÐµÐºÐ°ÐµÑ ÑÑÑокÑ, к коÑоÑой он пеÑемеÑÑилÑÑ. ÐÐ»Ñ Ð½Ð°Ð¿ÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ иÑполÑзоваÑÑ Ð»Ñбой ваÑианÑ, ÑазÑеÑÑннÑй в SQL-команде FETCH, вклÑÑÐ°Ñ Ð¸Ð·Ð²Ð»ÐµÐºÐ°ÑÑие более одной ÑÑÑоки. ÐÑÑÑÐ¾Ñ Ð±ÑÐ´ÐµÑ Ð¿ÐµÑемеÑÑн на поÑледнÑÑ ÑакÑÑ ÑÑÑокÑ. (Ðднако ваÑианÑ, в коÑоÑом напÑавление ÑвлÑеÑÑÑ Ð²ÑÑажением ÑиÑла без клÑÑевого Ñлова, ÑÑÑаÑел в PL/pgSQL. ÐÑÐ¾Ñ ÑинÑакÑÐ¸Ñ Ð½ÐµÐ¾Ð´Ð½Ð¾Ð·Ð½Ð°Ñен в ÑлÑÑаÑÑ
, когда напÑавление опÑÑено, поÑÑÐ¾Ð¼Ñ Ð¼Ð¾Ð¶ÐµÑ Ð·Ð°Ð²ÐµÑÑаÑÑÑÑ Ð¾Ñибкой, еÑли ÑиÑло не ÑвлÑеÑÑÑ ÐºÐ¾Ð½ÑÑанÑой.) Ðак и в SELECT INTO, пÑовеÑиÑÑ, бÑла ли обнаÑÑжена ÑÑÑока Ð´Ð»Ñ Ð¿ÐµÑемеÑениÑ, можно пÑи помоÑи ÑпеÑиалÑной пеÑеменной FOUND. ÐÑли ÑÑÑока не найдена, кÑÑÑÐ¾Ñ ÑÑÑанавливаеÑÑÑ Ð¿Ð¾Ñле поÑледней ÑÑÑоки или пеÑед пеÑвой ÑÑÑокой в завиÑимоÑÑи Ð¾Ñ Ð½Ð°Ð¿ÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ.
ÐÑимеÑÑ:
MOVE curs1; MOVE LAST FROM curs3; MOVE RELATIVE -2 FROM curs4; MOVE FORWARD 2 FROM curs4;
42.7.3.3. UPDATE/DELETE WHERE CURRENT OF #
UPDATEÑаблиÑаSET ... WHERE CURRENT OFкÑÑÑоÑ; DELETE FROMÑаблиÑаWHERE CURRENT OFкÑÑÑоÑ;
Ðогда кÑÑÑÐ¾Ñ Ð¿Ð¾Ð·Ð¸ÑиониÑован на ÑÑÑÐ¾ÐºÑ ÑаблиÑÑ, ÑÑÑ ÑÑÑÐ¾ÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ измениÑÑ Ð¸Ð»Ð¸ ÑдалиÑÑ Ð¿Ñи помоÑи кÑÑÑоÑа. ÐÑÑÑ Ð¾Ð³ÑаниÑÐµÐ½Ð¸Ñ Ð½Ð° Ñо, каким Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð·Ð°Ð¿ÑÐ¾Ñ ÐºÑÑÑоÑа (в ÑаÑÑноÑÑи, не должно бÑÑÑ Ð³ÑÑппиÑовок), и кÑайне желаÑелÑно иÑполÑзоваÑÑ Ñказание FOR UPDATE. Ðа дополниÑелÑнÑми ÑведениÑми обÑаÑиÑеÑÑ Ðº ÑÑÑаниÑе ÑпÑавки DECLARE.
ÐÑимеÑ:
UPDATE foo SET dataval = myval WHERE CURRENT OF curs1;
42.7.3.4. CLOSE #
CLOSE кÑÑÑоÑ;CLOSE закÑÑÐ²Ð°ÐµÑ ÑвÑзаннÑй Ñ ÐºÑÑÑоÑом поÑÑал. ÐÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¾ÑвободиÑÑ ÑеÑÑÑÑÑ ÑанÑÑе, Ñем законÑиÑÑÑ ÑÑанзакÑиÑ, или ÑÑÐ¾Ð±Ñ Ð¾ÑвободиÑÑ ÐºÑÑÑоÑнÑÑ Ð¿ÐµÑеменнÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð²ÑоÑного оÑкÑÑÑиÑ.
ÐÑимеÑ:
CLOSE curs1;
42.7.3.5. ÐозвÑÐ°Ñ ÐºÑÑÑоÑа из ÑÑнкÑии #
ÐÑÑÑоÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ возвÑаÑаÑÑ Ð¸Ð· ÑÑнкÑии на PL/pgSQL. ÐÑо полезно, когда нÑжно веÑнÑÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво ÑÑÑок и ÑÑолбÑов, оÑобенно еÑли вÑбоÑки оÑÐµÐ½Ñ Ð±Ð¾Ð»ÑÑие. ÐÐ»Ñ ÑÑого, в ÑÑнкÑии оÑкÑÑваеÑÑÑ ÐºÑÑÑÐ¾Ñ Ð¸ его Ð¸Ð¼Ñ Ð²Ð¾Ð·Ð²ÑаÑаеÑÑÑ Ð²ÑзÑваÑÑÐµÐ¼Ñ (или пÑоÑÑо оÑкÑÑваеÑÑÑ ÐºÑÑÑоÑ, иÑполÑзÑÑ Ñказанное Ð¸Ð¼Ñ Ð¿Ð¾ÑÑала, каким-либо обÑазом извеÑÑное вÑзÑваÑÑемÑ). ÐÑзÑваÑÑий заÑем Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð·Ð²Ð»ÐµÐºÐ°ÑÑ ÑÑÑоки из кÑÑÑоÑа. ÐÑÑÑÐ¾Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð·Ð°ÐºÑÑÑ Ð²ÑзÑваÑÑим или он бÑÐ´ÐµÑ Ð°Ð²ÑомаÑиÑеÑки закÑÑÑ Ð¿Ñи завеÑÑении ÑÑанзакÑии.
ÐÐ¼Ñ Ð¿Ð¾ÑÑала, иÑполÑзÑемое Ð´Ð»Ñ ÐºÑÑÑоÑа, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ñказано ÑазÑабоÑÑиком или бÑÐ´ÐµÑ Ð³ÐµÐ½ÐµÑиÑоваÑÑÑÑ Ð°Ð²ÑомаÑиÑеÑки. ЧÑÐ¾Ð±Ñ ÑказаÑÑ Ð¸Ð¼Ñ Ð¿Ð¾ÑÑала, нÑжно пÑоÑÑо пÑиÑвоиÑÑ ÑÑÑÐ¾ÐºÑ Ð² пеÑеменнÑÑ refcursor пеÑед его оÑкÑÑÑием. ÐнаÑение ÑÑÑоки пеÑеменной refcursor бÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹ OPEN как Ð¸Ð¼Ñ Ð¿Ð¾ÑÑала. Ðднако еÑли пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ refcursor Ð¸Ð¼ÐµÐµÑ Ð·Ð½Ð°Ñение NULL (как и ÑÑÑановлено по ÑмолÑаниÑ), OPEN авÑомаÑиÑеÑки генеÑиÑÑÐµÑ Ð¸Ð¼Ñ, коÑоÑое не конÑликÑÑÐµÑ Ñ Ð»ÑбÑм ÑÑÑеÑÑвÑÑÑим поÑÑалом, и пÑиÑÐ²Ð°Ð¸Ð²Ð°ÐµÑ ÐµÐ³Ð¾ пеÑеменной refcursor.
ÐÑимеÑание
РвеÑÑиÑÑ PostgreSQL ниже 16 ÑвÑзаннÑе кÑÑÑоÑнÑе пеÑеменнÑе иниÑиализиÑовалиÑÑ Ð² знаÑениÑ, ÑодеÑжаÑие ÑобÑÑвеннÑе имена, а не в NULL, поÑÑÐ¾Ð¼Ñ Ð¸Ð¼Ñ Ð¿Ð¾ÑÑала Ñовпадало Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ кÑÑÑоÑной пеÑеменной, заданнÑм по ÑмолÑаниÑ. Ðоведение изменилоÑÑ Ð²Ð¾ избежание конÑликÑов Ð¼ÐµÐ¶Ð´Ñ ÐºÑÑÑоÑами Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñми именами в ÑазнÑÑ ÑÑнкÑиÑÑ .
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¾Ð´Ð¸Ð½ из ÑпоÑобов пеÑедаÑи имени кÑÑÑоÑа вÑзÑваÑÑемÑ:
CREATE TABLE test (col text);
INSERT INTO test VALUES ('123');
CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS '
BEGIN
OPEN $1 FOR SELECT col FROM test;
RETURN $1;
END;
' LANGUAGE plpgsql;
BEGIN;
SELECT reffunc('funccursor');
FETCH ALL IN funccursor;
COMMIT;Ð ÑледÑÑÑем пÑимеÑе иÑполÑзÑеÑÑÑ Ð°Ð²ÑомаÑиÑеÑÐºÐ°Ñ Ð³ÐµÐ½ÐµÑаÑÐ¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ кÑÑÑоÑа:
CREATE FUNCTION reffunc2() RETURNS refcursor AS '
DECLARE
ref refcursor;
BEGIN
OPEN ref FOR SELECT col FROM test;
RETURN ref;
END;
' LANGUAGE plpgsql;
-- Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÑÑÑоÑов, необÑ
одимо наÑаÑÑ ÑÑанзакÑиÑ
BEGIN;
SELECT reffunc2();
reffunc2
--------------------
<unnamed cursor 1>
(1 row)
FETCH ALL IN "<unnamed cursor 1>";
COMMIT;Ð ÑледÑÑÑем пÑимеÑе показан один из ÑпоÑобов веÑнÑÑÑ Ð½ÐµÑколÑко кÑÑÑоÑов из одной ÑÑнкÑии:
CREATE FUNCTION myfunc(refcursor, refcursor) RETURNS SETOF refcursor AS $$
BEGIN
OPEN $1 FOR SELECT * FROM table_1;
RETURN NEXT $1;
OPEN $2 FOR SELECT * FROM table_2;
RETURN NEXT $2;
END;
$$ LANGUAGE plpgsql;
-- Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÑÑÑоÑов необÑ
одимо наÑаÑÑ ÑÑанзакÑиÑ
BEGIN;
SELECT * FROM myfunc('a', 'b');
FETCH ALL FROM a;
FETCH ALL FROM b;
COMMIT;42.7.4. ÐбÑабоÑка кÑÑÑоÑа в Ñикле #
Ðдин из ваÑианÑов Ñикла FOR позволÑÐµÑ Ð¿ÐµÑебиÑаÑÑ ÑÑÑоки, возвÑаÑÑннÑе кÑÑÑоÑом. ÐÐ¾Ñ ÐµÐ³Ð¾ ÑинÑакÑиÑ:
[ <<меÑка>> ] FORпеÑеменнаÑ-запиÑÑINÑвÑзаннаÑ_пеÑеменнаÑ_кÑÑÑоÑа[ ( [имÑ_аÑгÑменÑа:= ]знаÑение_аÑгÑменÑа[, ...] ) ] LOOPопеÑаÑоÑÑEND LOOP [меÑка];
ÐÑÑÑоÑÐ½Ð°Ñ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° бÑÑÑ ÑвÑзана Ñ Ð·Ð°Ð¿ÑоÑом пÑи обÑÑвлении. ÐÑÑÑÐ¾Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾ÑкÑÑÑÑм. Ðоманда FOR авÑомаÑиÑеÑки оÑкÑÑÐ²Ð°ÐµÑ ÐºÑÑÑÐ¾Ñ Ð¸ авÑомаÑиÑеÑки закÑÑÐ²Ð°ÐµÑ Ð¿Ñи завеÑÑении Ñикла. СпиÑок ÑакÑиÑеÑкиÑ
знаÑений аÑгÑменÑов должен пÑиÑÑÑÑÑвоваÑÑ ÑолÑко в Ñом ÑлÑÑае, еÑли кÑÑÑÐ¾Ñ Ð¾Ð±ÑÑвлÑлÑÑ Ñ Ð¿Ð°ÑамеÑÑами. ÐÑи знаÑÐµÐ½Ð¸Ñ Ð±ÑдÑÑ Ð¿Ð¾Ð´ÑÑÐ°Ð²Ð»ÐµÐ½Ñ Ð² запÑоÑ, как и пÑи вÑполнении OPEN (Ñм. ÐодÑаздел 42.7.2.3).
ÐÐ°Ð½Ð½Ð°Ñ Ð¿ÐµÑеменнаÑ-запиÑÑ Ð°Ð²ÑомаÑиÑеÑки опÑеделÑеÑÑÑ ÐºÐ°Ðº пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñипа record и ÑÑÑеÑÑвÑÐµÑ ÑолÑко внÑÑÑи Ñикла (дÑÑгие обÑÑвленнÑе пеÑеменнÑе Ñ Ñаким именем игноÑиÑÑеÑÑÑ Ð² Ñикле). ÐÐ°Ð¶Ð´Ð°Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÐ¼Ð°Ñ ÐºÑÑÑоÑом ÑÑÑока поÑледоваÑелÑно пÑиÑваиваеÑÑÑ ÑÑой пеÑеменной и вÑполнÑеÑÑÑ Ñело Ñикла.