PostgreSQL 游标处理

前端之家收集整理的这篇文章主要介绍了PostgreSQL 游标处理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Postgresql 游标处理

简单循环处理I


此写法是先取一条数据,然后判断循环条件



--清空日志表.
Test=#truncatetablelog_table;
TRUNCATETABLE

Test=#select*fromtest_main;
id|value
----+-------
1|ONE
2|TWO
4|FOUR
(3行记录)




CREATEORREPLACEFUNCTIONTestCursor()RETURNSvoidAS
$$
DECLARE
--定义游标.
c_test_mainCURSORFOR
SELECTid,valueFROMtest_main;
--定义存储数据的变量.
v_idINT;
v_valueVARCHAR(10);
BEGIN
--打开游标.
OPENc_test_main;
--填充数据.
FETCHc_test_mainINTOv_id,v_value;

--假如检索到了数据,才处理.
whilefoundloop
INSERTINTOlog_tableVALUES(v_value);
	--填充下一条数据.
FETCHc_test_mainINTOv_id,v_value;
endloop;

--关闭游标
CLOSEc_test_main;
END;
$$
LANGUAGEplpgsql;




Test=#selectTestCursor();
testcursor
------------

(1行记录)


Test=#select*fromlog_table;
log_text
----------
ONE
TWO
FOUR
(3行记录)



如果sql语句中,列的数量很多,那么定义很多的变量,对应没一列。
开发、维护成本都会比较高。
这种情况下,可以采用表名%rowtype的方式,只定义一个变量来进行处理.

--清空日志表.
Test=#truncatetablelog_table;
TRUNCATETABLE


CREATEORREPLACEFUNCTIONTestCursor()RETURNSvoidAS
$$
DECLARE
--定义游标.
c_test_mainCURSORFOR
SELECTid,valueFROMtest_mainORDERBYidDESC;
--定义存储数据的变量.
v_main_datatest_main%ROWTYPE;

BEGIN
--打开游标.
OPENc_test_main;
--填充数据.
FETCHc_test_mainINTOv_main_data;

--假如检索到了数据,才处理.
whilefoundloop
INSERTINTOlog_tableVALUES(v_main_data.value);
	--填充下一条数据.
FETCHc_test_mainINTOv_main_data;
endloop;

--关闭游标
CLOSEc_test_main;
END;
$$
LANGUAGEplpgsql;


Test=#selectTestCursor();
testcursor
------------

(1行记录)


Test=#select*fromlog_table;
log_text
----------
FOUR
TWO
ONE
(3行记录)



简单循环处理II

此写法是先开始循环,然后取数据,然后判断条件




--清空日志表.
Test=#truncatetablelog_table;
TRUNCATETABLE

Test=#select*fromtest_main;
id|value
----+-------
1|ONE
2|TWO
4|FOUR
(3行记录)




CREATEORREPLACEFUNCTIONTestCursor2()RETURNSvoidAS
$$
DECLARE
--定义游标.
c_test_mainCURSORFOR
SELECTid,valueFROMtest_main;
--定义存储数据的变量.
v_idINT;
v_valueVARCHAR(10);
BEGIN
--打开游标.
OPENc_test_main;

LOOP
--填充数据.
FETCHc_test_mainINTOv_id,v_value;
--假如没有检索到数据,结束循环处理
ExitwhenNOTfound;
	--游标每一行的实际操作.
INSERTINTOlog_tableVALUES(v_value);
ENDLOOP;

--关闭游标
CLOSEc_test_main;
END;
$$
LANGUAGEplpgsql;




Test=#selectTestCursor2();
testcursor2
-------------

(1行记录)


Test=#select*fromlog_table;
log_text
----------
ONE
TWO
FOUR
(3行记录)



支持来回滚动的游标



--清空日志表.
Test=#truncatetablelog_table;
TRUNCATETABLE


--为达到测试效果,多加几行测试数据.
INSERTINTOtest_main(id,value)VALUES(11,'ONEONE');
INSERTINTOtest_main(id,value)VALUES(12,'ONETWO');
INSERTINTOtest_main(id,value)VALUES(13,'ONETHREE');

Test=#SELECTid,valueFROMtest_mainORDERBYid;
id|value
----+----------
1|ONE1
2|TWO1
4|FOUR1
11|ONEONE
12|ONETWO
13|ONETHREE
(6行记录)


CREATEORREPLACEFUNCTIONTestCursorScroll()RETURNSvoidAS
$$
DECLARE
--定义游标.
c_test_mainSCROLLCURSORFOR
SELECTid,valueFROMtest_mainORDERBYid;

--定义存储数据的变量.
v_main_datatest_main%ROWTYPE;

BEGIN
--打开游标.
OPENc_test_main;

--填充数据.
FETCHFIRSTFROMc_test_mainINTOv_main_data;
INSERTINTOlog_tableVALUES('游标第一行:'||v_main_data.value);

--填充数据.
FETCHLASTFROMc_test_mainINTOv_main_data;
INSERTINTOlog_tableVALUES('游标最末行:'||v_main_data.value);

--填充数据.
FETCHABSOLUTE3FROMc_test_mainINTOv_main_data;
INSERTINTOlog_tableVALUES('游标绝对第3行:'||v_main_data.value);

--填充数据.
FETCHRELATIVE2FROMc_test_mainINTOv_main_data;
INSERTINTOlog_tableVALUES('游标相对第2行:'||v_main_data.value);

--填充数据.
FETCHPRIORFROMc_test_mainINTOv_main_data;
INSERTINTOlog_tableVALUES('游标上一行:'||v_main_data.value);

--填充数据.
FETCHNEXTFROMc_test_mainINTOv_main_data;
INSERTINTOlog_tableVALUES('游标下一行:'||v_main_data.value);

--关闭游标
CLOSEc_test_main;
END;
$$
LANGUAGEplpgsql;


Test=#selectTestCursorScroll();
testcursorscroll
------------------

(1行记录)


Test=#select*fromlog_table;
log_text
----------------------
游标第一行:ONE1
游标最末行:ONETHREE
游标绝对第3行:FOUR1
游标相对第2行:ONETWO
游标上一行:ONEONE
游标下一行:ONETWO
(6行记录)



带参数的游标

这里同时需要使用前面外键约束的test_sub表



--清空日志表.
Test=#truncatetablelog_table;
TRUNCATETABLE





CREATEORREPLACEFUNCTIONTestCursorMainSub()RETURNSvoidAS
$$
DECLARE
--定义游标(主表).
c_test_mainCURSORFOR
SELECTid,valueFROMtest_main;
--保存主表游标数据的变量
v_main_datatest_main%ROWTYPE;

--定义游标(子表).
c_test_subCURSOR(p_main_idINT)IS
SELECTid,main_id,value
FROMtest_sub
WHEREmain_id=p_main_id;
--保存子表游标数据的变量
v_sub_datatest_sub%ROWTYPE;
BEGIN

--打开游标(主表).
OPENc_test_main;

--开始循环处理(主表).
LOOP
--填充数据(主表).
FETCHc_test_mainINTOv_main_data;
--假如没有检索到(主表)数据,结束循环处理
ExitwhenNOTfound;

--主表每一行的实际操作.
INSERTINTOlog_tableVALUES('Main:'||v_main_data.value);

--打开游标(子表).
OPENc_test_sub(v_main_data.id);

--开始循环处理(子表).
LOOP
--填充数据(子表).
FETCHc_test_subINTOv_sub_data;
--假如没有检索到(主表)数据,结束循环处理
ExitwhenNOTfound;

--子表每一行的实际操作.
INSERTINTOlog_tableVALUES('-->Sub:'||v_sub_data.value);
ENDLOOP;
--关闭游标(子表).
CLOSEc_test_sub;
ENDLOOP;

--关闭游标(主表).
CLOSEc_test_main;
END;
$$
LANGUAGEplpgsql;



Test=#selectTestCursorMainSub();
testcursormainsub
-------------------

(1行记录)


Test=#select*fromlog_table;
log_text
-----------------
Main:ONE
-->Sub:ONEONE
Main:TWO
-->Sub:TWOTWO
Main:FOUR
-->Sub:FOURFOUR
(6行记录)




用于更新的游标




CREATEORREPLACEFUNCTIONTestUpdateCursor()RETURNSvoidAS
$$
DECLARE
--定义游标.
c_test_mainCURSORFOR
SELECTid,valueFROMtest_mainFORUPDATE;
--定义存储数据的变量.
v_main_datatest_main%ROWTYPE;

BEGIN
--打开游标.
OPENc_test_main;

LOOP
--填充数据.
FETCHc_test_mainINTOv_main_data;
--假如没有检索到数据,结束循环处理
ExitwhenNOTfound;
	
	--游标每一行的实际操作.

	--更新数据.
UPDATE
test_main
SET
value=value||'1'
WHERE
CURRENTOFc_test_main;

ENDLOOP;


--关闭游标
CLOSEc_test_main;
END;
$$
LANGUAGEplpgsql;



Test=#selectTestUpdateCursor();
testupdatecursor
------------------

(1行记录)


Test=#select*fromtest_main;
id|value
----+-------
1|ONE1
2|TWO1
4|FOUR1
(3行记录)

FOR的使用



--清空日志表.
Test=#truncatetablelog_table;
TRUNCATETABLE



CREATEORREPLACEFUNCTIONTestCursorFor()RETURNSvoidAS
$$
DECLARE
--定义存储数据的变量.
v_main_dataRECORD;
BEGIN

FORv_main_dataINSELECTid,valueFROMtest_mainLOOP
	--每一行的实际操作.
INSERTINTOlog_tableVALUES(v_main_data.value);
ENDLOOP;

END;
$$
LANGUAGEplpgsql;




Test=#SELECTTestCursorFor();
testcursorfor
---------------

(1行记录)


Test=#select*fromlog_table;
log_text
----------
ONE1
TWO1
FOUR1
(3行记录)
原文链接:https://www.f2er.com/postgresql/196079.html

猜你在找的Postgre SQL相关文章