1.說明:
1)cursor和refcursor的區別:
靜態游標,不能修改里面的語句
動態游標,可以多次open和close,指定不同的SQL
隱式游標,DML和for操作,都在內部轉換為了一個隱式游標在執行
2)fetch的區別:
使用fetch cur 和 fetch next from cur 一樣,因為NEXT 是 FETCH 的默認選項.
2.創建測試表:
create table test(id int, info text, crt_time timestamp); insert into test select generate_series(1,10), 'test', now();
3.測試:
DO $$ DECLARE id integer; one_row record; ret_cur CURSOR FOR SELECT * FROM test; --靜態游標,不能修改里面的語句 ret_cur2 refcursor;--動態游標,可以多次open和close,指定不同的SQL BEGIN id:=1; raise notice 'test id: %', id; --動態游標 OPEN ret_cur2 FOR SELECT * FROM test; FETCH ret_cur2 INTO one_row; while ret_cur2%FOUND loop raise notice 'row info, id is: %, info is: %, crt_time is: %', one_row.id, one_row.info, one_row.crt_time; FETCH ret_cur2 INTO one_row; END loop; CLOSE ret_cur2; raise notice 'user fetch next: '; --靜態游標: OPEN ret_cur; FETCH NEXT FROM ret_cur INTO one_row; while ret_cur%FOUND loop raise notice 'row info, id is: %, info is: %, crt_time is: %', one_row.id, one_row.info, one_row.crt_time; FETCH NEXT FROM ret_cur INTO one_row; END loop; CLOSE ret_cur; --隱式游標,實際上select * from test是存在一個內部的游標中的: raise notice '隱式游標:'; FOR one_row IN (SELECT * FROM test) loop raise notice 'row info, id is: %, info is: %, crt_time is: %', one_row.id, one_row.info, one_row.crt_time; END loop; --最后執行: EXCEPTION WHEN NO_DATA_FOUND THEN raise notice 'no data FOUND'; END $$
4.執行結果:
00000: test id: 1 00000: row info, id is: 1, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 2, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 3, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 4, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 5, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 6, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 7, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 8, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 9, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 10, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: user fetch next: 00000: row info, id is: 1, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 2, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 3, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 4, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 5, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 6, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 7, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 8, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 9, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 10, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: 隱式游標: 00000: row info, id is: 1, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 2, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 3, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 4, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 5, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 6, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 7, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 8, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 9, info is: test, crt_time is: 2020-09-09 15:01:35.837492 00000: row info, id is: 10, info is: test, crt_time is: 2020-09-09 15:01:35.837492
5.游標屬性:
%FOUND: bool - TRUE if >1 row returned %NOTFOUND:bool - TRUE if 0 rows returned %ISOPEN: bool - TRUE if cursor still open %ROWCOUNT:int - number of rows affected by last SQL statement 注:NO_DATA_FOUND和%NOTFOUND的用法是有區別的,小結如下: 1)SELECT . . . INTO 語句觸發 NO_DATA_FOUND; 2)當一個顯式光標的 where 子句未找到時觸發 %NOTFOUND; 3)當UPDATE或DELETE 語句的where 子句未找到時觸發 SQL%NOTFOUND; 4)在光標的提取(Fetch)循環中要用 %NOTFOUND 或%FOUND 來確定循環的退出條件,不要用NO_DATA_FOUND