PostgreSQL 存儲過程中 in、out、in out參數


傳參類型說明:

in:  是參數的默認模式,這種模式就是在程序運行的時候已經具有值,在程序體中值不會改變。

out:  模式定義的參數只能在過程體內部賦值,表示該參數可以將某個值傳遞回調用他的過程。簡單說:out參數在調用的時候,不需要傳入參數(嘗試傳入會報錯),不需要rutrun該參數,function結束會自動返回該out參數。

in out: 表示參數可以向該過程中傳遞值,也可以將某個值傳出去。簡單說:傳參要指定對應參數,結束的時候,還需要專門當out參數去獲取。

 

這里是以類PG數據庫做的實驗,本質基本相同:

 

1.創建類型、數組類型:

DROP TABLE test_type CASCADE ;
DROP TYPE test_type CASCADE ;
CREATE type  test_type as (
      id INT,
      info varchar(32)
);
    
DROP TYPE test_type_Array;
CREATE TYPE test_type_Array AS TABLE OF test_type;

  

2.創建測試表,填充測試數據:

DROP TABLE test;
CREATE TABLE test(id VARCHAR(32), info varchar(32), crt_time TIMESTAMP);
INSERT INTO test values('1', 'test1', now());
INSERT INTO test values('1', 'test11', now());
INSERT INTO test values('2', 'test2', now());

  

3.創建四個function,分別測試簡單類型和對象類型(這里創建數組來測試):

/*
 * 測試簡單類型的in out參數使用,參數需要指定,結果需要當做out參數獲取*
 * exp:v_info := test_fnc(v_record_id, v_info);
 */
CREATE OR REPLACE FUNCTION test_fnc(id VARCHAR(32), info IN OUT varchar(32)) RETURNS varchar(32) AS
$$
BEGIN 
	info := info|| '_connect_' || id;
	raise notice 'info is: %', info;
END 
$$
LANGUAGE plsql;

/*
 * 測試簡單類型的out參數使用,參數不需要指定,結果需要獲取*
 * exp:v_info := test_fnc2(v_record_id);
 */
CREATE OR REPLACE FUNCTION test_fnc2(id VARCHAR(32), info  OUT varchar(32)) RETURNS varchar(32) AS
$$
BEGIN 
	info := info|| '_connect_' || id;
	raise notice 'info is: %', info;
END 
$$
LANGUAGE plsql;

/*
 * 測試數組類型的in out參數使用,參數需要指定,結果需要當做out參數獲取*
 * exp:test_A := test_array_fnc(v_record_id, test_A);
 */
CREATE OR REPLACE FUNCTION test_array_fnc(v_id VARCHAR(32), test_A IN OUT test_type_Array) RETURNS test_type_Array AS
$$
DECLARE 
	v_num int;
	one_type_value test_type;
	CURSOR test_values IS SELECT * FROM test WHERE id = v_id;
BEGIN 
	v_num := 1;
	FOR one_value IN test_values LOOP
		one_type_value.id := one_value.id;
		one_type_value.info := one_value.info;
		
		test_A.extend;
		test_A(v_num) := one_type_value;
		
		raise notice 'v_num is: %', v_num;
		raise notice 'test_A.count is: %', test_A.count;
		
		v_num := v_num + 1;
	END LOOP;
END 
$$
LANGUAGE plsql;

/*
 * 測試數組類型的out參數使用,參數不需要指定,結果需要獲取*
 * exp:test_A := test_array_fnc2(v_record_id);
 */
CREATE OR REPLACE FUNCTION test_array_fnc2(v_id VARCHAR(32), test_A  OUT test_type_Array) RETURNS test_type_Array AS
$$
DECLARE 
	v_num int;
	one_type_value test_type;
	CURSOR test_values IS SELECT * FROM test WHERE id = v_id;
BEGIN 
	v_num := 1;
	test_A := test_type_Array();
	FOR one_value IN test_values LOOP
		one_type_value.id := one_value.id;
		one_type_value.info := one_value.info;
		
		test_A.extend;
		test_A(v_num) := one_type_value;
		
		raise notice 'v_num is: %', v_num;
		raise notice 'test_A.count is: %', test_A.count;
		
		v_num := v_num + 1;
	END LOOP;
END 
$$
LANGUAGE plsql;

  

4.在匿名塊中測試:

DO 
$BODY$
DECLARE 
	test_A test_type_Array;
	v_record_id varchar(32);
	v_info varchar(32);
BEGIN 
	v_record_id := '1';
	
	raise notice 'test object, like array. must use "in out":';
	test_A := test_type_Array();
	test_A := test_array_fnc(v_record_id, test_A);
	raise notice 'out: test_A.count is: %', test_A.count;
	
	raise notice '';
	raise notice 'execute again, the object value will in the function:';
	test_A := test_array_fnc(v_record_id, test_A);
	raise notice 'out: test_A.count is: %', test_A.count;
	
	--NOTICE:這樣的用法,不會因為是in out參數而直接給參數賦值,相當於只是將參數傳遞進去了
	raise notice '';
	raise notice 'do not get the result:';
	test_array_fnc(v_record_id, test_A);
	raise notice 'out: test_A.count is: %', test_A.count;
	
	raise notice '';
	raise notice 'test object, like array. use "out":';
	test_A := test_array_fnc2(v_record_id);
	raise notice 'out: test_A.count is: %', test_A.count;
	
	v_info := 'init';
	raise notice '';
	raise notice 'test vachar, use "in out":';
	v_info := test_fnc(v_record_id, v_info);
	raise notice 'out: test_fnc: v_info is: %', v_info;
	
	raise notice '';
	raise notice 'test varchar, just use "out":';
	v_info := test_fnc2(v_record_id);
	raise notice 'out: test_fnc2: v_info is: %', v_info;
END 
$BODY$

  

5.測試結果:

test object, like array. must use "in out":
v_num is: 1
test_A.count is: 1
v_num is: 2
test_A.count is: 2
out: test_A.count is: 2

execute again, the object value will in the function:
v_num is: 1
test_A.count is: 3
v_num is: 2
test_A.count is: 4
out: test_A.count is: 4
--上面可以看出,傳入和傳出都獲取了相應的值。 do not get the result: v_num is: 1 test_A.count is: 5 v_num is: 2 test_A.count is: 6 out: test_A.count is: 4 test object, like array. use "out": v_num is: 1 test_A.count is: 1 v_num is: 2 test_A.count is: 2 out: test_A.count is: 2
--在里面做了初始化,傳出值直接獲取 test vachar, use "in out": info is: init_connect_1 out: test_fnc: v_info is: init_connect_1 test varchar, just use "out": info is: _connect_1 out: test_fnc2: v_info is: _connect_1

  

 

6.附加:Is table of:原生的使用方法,不需要轉為數組和游標進行處理

--創建測試對象

DROP TYPE test_ty CASCADE ;
DROP TYPE test_ty_Array CASCADE ;

CREATE TYPE test_ty AS 
(
id int,
name varchar(32),
birthday timestamp
);

CREATE type test_ty_Array as table of test_ty ;

  

 

--使用is table of直接使用,需要注意兩個地方:
--1)需要對數組進行實例化。
--2)使用時,如果往里面加對象,需要先extend

DO
$$
DECLARE 
	ret_array test_ty_Array; 
	one_row test_ty;
	idx int;
	CURSOR ret_cur IS SELECT * FROM test;
BEGIN 
	idx := 1;
	ret_array := test_ty_Array();

    FOR one_ret IN ret_cur loop
		raise notice 'id is: %, name is: %, birthday is: %', one_ret.id, one_ret.name, one_ret.birthday;
		
    	one_row.id := one_ret.id;
    	one_row.name := one_ret.name;
    	one_row.birthday := one_ret.birthday;
		
    	ret_array.extend;
    	ret_array(idx) := one_row;
		
    	idx := idx + 1;
    END LOOP;
    
    raise notice '---------------------------------------------------------------------------------------------------------';
    FOR idx IN 1..ret_array.count loop
    	one_row = ret_array(idx);
    	raise notice 'idx: %, --> id is: %, name is: %, birthday is: %', idx, one_row.id, one_row.name, one_row.birthday;
    END loop;
END 
$$

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM