CallableStatement 和 PreparedStatement用法特別相似,只是CallableStatement 可以用來(lái)調(diào)用存儲(chǔ)過(guò)程。
存儲(chǔ)過(guò)程簡(jiǎn)介調(diào)用簡(jiǎn)介
SQL語(yǔ)句需要先編譯然后執(zhí)行,而存儲(chǔ)過(guò)程(Stored Procedure)是一組為了完成特定功能的SQL語(yǔ)句集,經(jīng)編譯后存儲(chǔ)在數(shù)據(jù)庫(kù)中,用戶通過(guò)指定存儲(chǔ)過(guò)程的名字并給定參數(shù)(如果該存儲(chǔ)過(guò)程帶有參數(shù))來(lái)調(diào)用執(zhí)行它。
存儲(chǔ)過(guò)程是可編程的函數(shù),在數(shù)據(jù)庫(kù)中創(chuàng)建并保存,可以由SQL語(yǔ)句和控制結(jié)構(gòu)組成。當(dāng)想要在不同的應(yīng)用程序或平臺(tái)上執(zhí)行相同的函數(shù),或者封裝特定功能時(shí),存儲(chǔ)過(guò)程是非常有用的。數(shù)據(jù)庫(kù)中的存儲(chǔ)過(guò)程可以看做是對(duì)編程中面向?qū)ο蠓椒ǖ哪M,它允許控制數(shù)據(jù)的訪問(wèn)方式。
存儲(chǔ)過(guò)程的優(yōu)點(diǎn):
(1). 增強(qiáng)SQL語(yǔ)言的功能和靈活性:存儲(chǔ)過(guò)程可以用控制語(yǔ)句編寫(xiě),有很強(qiáng)的靈活性,可以完成復(fù)雜的判斷和較復(fù)雜的運(yùn)算。
(2). 標(biāo)準(zhǔn)組件式編程:存儲(chǔ)過(guò)程被創(chuàng)建后,可以在程序中被多次調(diào)用,而不必重新編寫(xiě)該存儲(chǔ)過(guò)程的SQL語(yǔ)句。而且數(shù)據(jù)庫(kù)專業(yè)人員可以隨時(shí)對(duì)存儲(chǔ)過(guò)程進(jìn)行修改,對(duì)應(yīng)用程序源代碼毫無(wú)影響。
(3). 較快的執(zhí)行速度:如果某一操作包含大量的Transaction-SQL代碼或分別被多次執(zhí)行,那么存儲(chǔ)過(guò)程要比批處理的執(zhí)行速度快很多。因?yàn)榇鎯?chǔ)過(guò)程是預(yù)編譯的。在首次運(yùn)行一個(gè)存儲(chǔ)過(guò)程時(shí)查詢,優(yōu)化器對(duì)其進(jìn)行分析優(yōu)化,并且給出最終被存儲(chǔ)在系統(tǒng)表中的執(zhí)行計(jì)劃。而批處理的Transaction-SQL語(yǔ)句在每次運(yùn)行時(shí)都要進(jìn)行編譯和優(yōu)化,速度相對(duì)要慢一些。
(4). 減少網(wǎng)絡(luò)流量:針對(duì)同一個(gè)數(shù)據(jù)庫(kù)對(duì)象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語(yǔ)句被組織進(jìn)存儲(chǔ)過(guò)程,那么當(dāng)在客戶計(jì)算機(jī)上調(diào)用該存儲(chǔ)過(guò)程時(shí),網(wǎng)絡(luò)中傳送的只是該調(diào)用語(yǔ)句,從而大大減少網(wǎng)絡(luò)流量并降低了網(wǎng)絡(luò)負(fù)載。
(5). 作為一種安全機(jī)制來(lái)充分利用:通過(guò)對(duì)執(zhí)行某一存儲(chǔ)過(guò)程的權(quán)限進(jìn)行限制,能夠?qū)崿F(xiàn)對(duì)相應(yīng)的數(shù)據(jù)的訪問(wèn)權(quán)限的限制,避免了非授權(quán)用戶對(duì)數(shù)據(jù)的訪問(wèn),保證了數(shù)據(jù)的安全。
MySQL的存儲(chǔ)過(guò)程
存儲(chǔ)過(guò)程是數(shù)據(jù)庫(kù)的一個(gè)重要的功能,MySQL 5.0以前并不支持存儲(chǔ)過(guò)程,這使得MySQL在應(yīng)用上大打折扣。好在MySQL 5.0開(kāi)始支持存儲(chǔ)過(guò)程,這樣即可以大大提高數(shù)據(jù)庫(kù)的處理速度,同時(shí)也可以提高數(shù)據(jù)庫(kù)編程的靈活性。
1. 創(chuàng)建MySQL存儲(chǔ)過(guò)程
DELIMITER //
create procedure findById(IN pid INTEGER)
BEGIN
SELECT * FROM `user` WHERE id= pid;
END //
DELIMITER;
2. 調(diào)用存儲(chǔ)過(guò)程
package com.jdbc;
import java.sql.*;
/**
* Created by Fant.J.
* 2018/3/5 20:14
*/
public class CallableStatementTest {
static String url = "jdbc:mysql://localhost:3306/user";
static String user = "root";
static String password = "root";
public static void main(String[] args) {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, user, password);
String sql = "CALL findById(?)";
CallableStatement stmt = connection.prepareCall(sql);
stmt.setInt(1,27);
ResultSet resultSet = stmt.executeQuery();
while (resultSet.next()){
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String birthday = resultSet.getString("birthday");
String sex = resultSet.getString("sex");
String address = resultSet.getString("address");
System.out.println(" " + username + " " + birthday + " " + sex
+ " " + address);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Fant.J reUseTest 2017-04-20 男 xxxx
3. 全面科普
通過(guò)前面的講解和例子,我想你肯定已經(jīng)了解調(diào)用存儲(chǔ)過(guò)程到底是個(gè)什么東西,但是你肯定也能看到,這例子只是一個(gè)特例,所以我在這里把 調(diào)用存儲(chǔ)代碼中的sql做個(gè)詳解。
存儲(chǔ)過(guò)程參數(shù)詳解
- in:往過(guò)程里傳參。 (參考我創(chuàng)建存儲(chǔ)過(guò)程中的代碼(IN pid INTEGER))
- out:往過(guò)程外傳參。
- inout:in and out
相對(duì)于oracle數(shù)據(jù)庫(kù)來(lái)說(shuō),MySQL的存儲(chǔ)過(guò)程相對(duì)功能較弱,使用較少。
創(chuàng)建的存儲(chǔ)過(guò)程保存在數(shù)據(jù)庫(kù)的數(shù)據(jù)字典中。