Ref Cursor 為伺服器端結果集參考。開啟時不回傳資料,僅回傳伺服器端地址,客戶端自主決定提取時機與方式。舊版 ODP.NET 僅支援輸出參數接收 Ref Cursor,無法作為輸入參數傳遞。
可將客戶端持有的 Ref Cursor 直接傳入 PL/SQL 程序處理,極大擴展應用彈性。
CREATE TABLE processing_result (status VARCHAR2(64));
CREATE OR REPLACE PACKAGE cursor_in_out AS
TYPE emp_cur_type IS REF CURSOR RETURN employees%ROWTYPE;
PROCEDURE process_cursor(p_cursor IN emp_cur_type);
END;
/
CREATE OR REPLACE PACKAGE BODY cursor_in_out AS
PROCEDURE process_cursor(p_cursor IN emp_cur_type) IS
emp_rec employees%ROWTYPE;
BEGIN
LOOP
FETCH p_cursor INTO emp_rec;
EXIT WHEN p_cursor%NOTFOUND;
INSERT INTO processing_result VALUES(
'Processed employee #' || emp_rec.employee_id || ': ' ||
emp_rec.first_name || ' ' || emp_rec.last_name
);
END LOOP;
END;
END;
/
using System; using System.Data; using Oracle.DataAccess.Client; using Oracle.DataAccess.Types;
string connStr = "User Id=hr;Password=hr;Data Source=oramag;Pooling=false";
using (OracleConnection con = new OracleConnection(connStr)) {
con.Open();
// 步驟 1:取得 Ref Cursor (OUTPUT)
OracleCommand cmd = con.CreateCommand();
cmd.CommandText = "BEGIN OPEN :1 FOR SELECT * FROM employees WHERE manager_id=101; END;";
OracleParameter p_rc = cmd.Parameters.Add("p_rc", OracleDbType.RefCursor, DBNull.Value, ParameterDirection.Output);
cmd.ExecuteNonQuery();
// 步驟 2:將 Ref Cursor 作為 INPUT 傳入存儲過程
cmd.Parameters.Clear();
cmd.CommandText = "cursor_in_out.process_cursor";
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter p_input = cmd.Parameters.Add("p_input", OracleDbType.RefCursor, p_rc.Value, ParameterDirection.Input);
cmd.ExecuteNonQuery();
// 清理
p_input.Dispose(); p_rc.Dispose(); cmd.Dispose();
}
SQL> SELECT * FROM processing_result; STATUS ---------------------------------------- Processed employee #108: Nancy Greenberg Processed employee #200: Jennifer Whalen Processed employee #203: Susan Mavris Processed employee #204: Hermann Baer Processed employee #205: Shelley Higgins