[JDBC] Preparecall, createStatement, preparedstatement

前言...,繼上周報告完JDBC+Mysql後,我一直以為prepareStatement跟createStatement是一樣功能,但用在不同Database上,星期一一早我主管叫我進會議室後,幫我指正這是可以用在同樣的Database上,只是會導致後用對SQL下指令的方法不一樣,所以我又特地回頭研究了一下,不過又引發我另一個問題...,等我研究完再提出來,呵呵。


Wiki 上,可以看到這三個的解釋,不過通常看完之後,我只覺得他媽的我怎麼還是覺得非常難理解!?

  • Statement:用以執行SQL查詢和更新(針對靜態SQL語句和單次執行)。
  • PreparedStatement:用以執行包含動態參數的SQL查詢和更新(在伺服器端編譯,允許重複執行以提高效率)。
  • CallableStatement:用以呼叫資料庫中的儲存過程
然後再看到一堆,關於preparecall、createStatement和preparedstatement的example code。


createStatement - 

//创建一个简单的Statement对象
 Statement Ex1Stmt = Ex1Con.createStatement();
 //创建SQL串,传送到DBMS并执行SQL语句
 ResultSet Ex1rs = Ex1Stmt.executeQuery("SELECT StudentID, FirstName, LastName FROM Students");
 //处理每一个数据行,直到不再有数据行
 System.out.println("Student Number   First Name   Last Name");


preparedstatement - 

 ps = conn.prepareStatement( "SELECT i.*, j.* FROM Omega i, Zappa j
      WHERE i = ? AND j = ?" );
 // 使用问号作为参数的标示
 
 // 进行参数设置
 // 与大部分Java API中下标的使用方法不同,字段的下标从1开始,1代表第一个问号
 // 当然,还有其他很多针对不同类型的类似的PreparedStatement.setXXX()方法
 ps.setString(1, "Poor Yorick");
 ps.setInt(2, 8008);
 
 // 结果集
 rs = ps.executeQuery();



preparecall - 
  1. CREATE PROCEDURE prc_getStuname(  
  2. @stuno VARCHAR(16),  
  3. @stuname VARCHAR(16) OUTPUT  
  4. )  
  5. AS  
  6. BEGIN  
  7. SELECT @stuname=STUNAME FROM T_STUDENT WHERE STUNO=@stuno  
  8. END 

  1. Connection conn = DriverManager.getConnection("jdbc:odbc:DSSchool");  
  2.         CallableStatement cs=conn.prepareCall("{call prc_getStuname(?, ?)}");  
  3.         //设置IN参数  
  4.         cs.setString(1,"0001");  
  5.         //注册OUT参数  
  6.         cs.registerOutParameter(2, java.sql.Types.CHAR);  
  7.         //执行存储过程  
  8.         cs.executeQuery();  
  9.         //获取参数值  
  10.         String result=cs.getString(2);  



我不知道這樣的結果,你是不是真的看明白這些用法了?小弟我資質愚鈍..不是很瞭解,所以又要重新再整理一下這一部分的資訊....。


createStatement我想是裡面最單純,最簡單的用法,直接createStatement(),再利用queryUpdate、queryExecute的方法,去執行SQL的command,如下。
     Statement Ex1Stmt = Ex1Con.createStatement();
ResultSet Ex1rs = Ex1Stmt.executeQuery("SELECT StudentID, FirstName, LastName FROM Students");
     以上就等於在Mysql的command如下。
     Shell>mysql
     Mysql>SELECT StudentID, FirstName, LastName FROM Students;


createStatement也是在網路上搜尋,就非常容易找到它的用法。
ps = conn.prepareStatement("SELECT i.*, j.* FROM Omega i, Zappa j WHERE i = ? AND j = ?");

 ps.setString(1, "Poor Yorick");
 ps.setInt(2, 8008);
在prepareStatement中,就將?當成一個可更換的填充參數,你可以不只一次去更換它,透過ps.setString/setInt,去將參數填入問號的位置中,set的過程中,第一個參數是指第幾個"?",如ps.setString(1, "Poor Yorick");就是將"i = ?"變成"i = Poor Yorick",而整句就變成,如下。
 Mysql>SELECT Poor i.*, j.* FROM Omega i, Zappa j WHERE i = Poor Yorick AND j = 8008;

如此一來,就可提升這段程式可重複利用的可能性了。


Preparecall我自己以為,這是比較複雜的使用方法,不過見人見智了啦。
   CallableStatement cs=conn.prepareCall("{call prc_getStuname(?, ?)}");
   cs.setString(1,"0001"); 
   cs.registerOutParameter(2, java.sql.Types.CHAR);
   cs.executeQuery();
在prepareCall的設定參數中,就可以看到prc_getStuname(?,?),簡單看來這是在事前就已經設計好的類似像function的東西,透過SetString(1,"0001")及registerOutParameter(2,...)去設定這兩個?的參數。
因為在CREATE PROCEDURE prc_getStuname(@stuno VARCHAR(16),@stuname VARCHAR(16) OUTPUT)中就已經指定了第一個(?)參數跟第二個(?)參數的用途,所以在example code中,cs.setString(1,"0001")是指設定第一個?的值為0001,而sc.registerOutParameter(2, java ...)是將第二個?參數型別設定為java.sql.Types.CHAR,如此一來,我就可以透過cs.getString(2);得stuname。如果以Mysql的command,看來應該如下面所示。
   Mysql>SELECT * FROM T_STUDENT WHERE STUNO="0001";

以上是我整理下來的結論,不知道有沒有缺失,當然prepareCall跟prepareStatement在應用上的變化會更多,但大概規則都是差不多是上面的介紹。JAVA對我這個菜鳥來說果然還是難度頗高。





留言

這個網誌中的熱門文章

[Security] wpa_supplicant setup

[Wordpress] 登出時出現 404 Error

[OpenNMS Note] OpenNMS SNMP的誕生