關於存儲過程的知識,很多人好像就熟悉我們所討論的這些。如果這是存儲過程的全部功能,那麼存
儲過程就不是其它遠程執行機制的替換方案了。存儲過程的功能比這強大得多。
creat proc proc_select
@pid varchar(20)
@address varchar(20) output
as
select @address=address from userinfo where pid=@pid
go
用java調用:
class.forName(/"sun.jdbc.odbc.JdbcOdbcDriver/"); //加載驅動
Connection con=DriverManager.getConnection(/"Jdbc:Odbc:test/",/"sa/",/"/"); //獲得連接
String call=/"{call proc_select(?,?)}; /" //調用語句
CallableStatement proc=con.preparecall(call); //調用存儲過程
proc.setString(1,/"12345678/"); //給輸入參數傳值
proc.registerOutParameter(2,Type.varchar); //聲明輸出參數是什麼類型的
proc.execute(); //執行
String address=proc.getString(2); //獲得輸出參數
java調用存儲過程2
存儲過程可以有返回值,所以CallableStatement類有類似getResultSet這樣的方法來獲取返回值。
當存儲過程返回一個值時,你必須使用registerOutParameter方法告訴JDBC驅動器該值的SQL類型是什麼
。你也必須調整存儲過程調用來指示該過程返回一個值。
下面接着上面的例子。這次我們查詢Dylan Thomas逝世時的年齡。這次的存儲過程使用PostgreSQL的
pl/pgsql:
create function snuffed_it_when (VARCHAR) returns integer ’declare
poet_id NUMBER;
poet_age NUMBER;
begin
--first get the id associated with the poet.
SELECT id INTO poet_id FROM poets WHERE name = $1;
--get and return the age.
SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id; [Page]
return age;
end; ’ language ’pl/pgsql’;
另外,注意pl/pgsql參數名通過Unix和DOS腳本的$n語法引用。同時,也注意嵌入的註釋,這是和
Java代碼相比的另一個優越性。在Java中寫這樣的註釋當然是可以的,但是看起來很凌亂,並且和SQL語
句脫節,必須嵌入到Java String中。
下面是調用這個存儲過程的Java代碼:
connection.setAutoCommit(false);
CallableStatement proc = connection.prepareCall(/"{ ? = call snuffed_it_when(?) }/");
proc.registerOutParameter(1, Types.INTEGER);
proc.setString(2, poetName);
cs.execute();
int age = proc.getInt(2);
如果指定了錯誤的返回值類型會怎樣?那麼,當調用存儲過程時將拋出一個RuntimeException,正如
你在ResultSet操作中使用了一個錯誤的類型所碰到的一樣。
複雜的返回值
關於存儲過程的知識,很多人好像就熟悉我們所討論的這些。如果這是存儲過程的全部功能,那麼存
儲過程就不是其它遠程執行機制的替換方案了。存儲過程的功能比這強大得多。
當你執行一個SQL查詢時,DBMS創建一個叫做cursor(遊標)的數據庫對象,用於在返回結果中迭代每
一行。ResultSet是當前時間點的遊標的一個表示。這就是爲什麼沒有緩存或者特定數據庫的支持,你只
能在ResultSet中向前移動。
某些DBMS允許從存儲過程中返回遊標的一個引用。JDBC並不支持這個功能,但是Oracle、PostgreSQL
和DB2的JDBC驅動器都支持在ResultSet上打開到遊標的指針(pointer)。
設想列出所有沒有活到退休年齡的詩人,下面是完成這個功能的存儲過程,返回一個打開的遊標,同
樣也使用PostgreSQL的pl/pgsql語言:
create procedure list_early_deaths () return refcursor as ’declare
toesup refcursor;
begin
open toesup for SELECT poets.name, deaths.age FROM poets, deaths
-- all entries in deaths are for poets. -- but the table might become generic.
WHERE poets.id = deaths.mort_id AND deaths.age < 60;
return toesup;
end; ’ language ’plpgsql’;
下面是調用該存儲過程的Java方法,將結果輸出到PrintWriter:
PrintWriter:
static void sendEarlyDeaths(PrintWriter out){
Connection con = null;