-------------------------------開篇基礎簡介--------:
存儲過程通常有以下優點:
(1).存儲過程增強了SQL語言的功能和靈活性。存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成復雜的判斷和較復雜的運算。
(2).存儲過程允許標准組件是編程。存儲過程被創建后,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。
(3).存儲過程能實現較快的執行速度。如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那么存儲過程要比批處理的執行速度 快很多。因為存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計划。而批處理的 Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。
(4).存儲過程能過減少網絡流量。針對同一個數據庫對象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語句被組織程存儲過程,那么當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增加了網絡流量並降低了網絡負載。
(5).存儲過程可被作為一種安全機制來充分利用。系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。
----------------------------------------------------------------------------------------
1、語法:
刪除> drop procedure if exists procedureName;
創建> create procedure(IN/OUT/INOUT 參數名稱 數據類型) BEGIN .... END;
----說明:
IN 輸入參數:表示該參數的值必須在調用存儲過程時指定,在存儲過程中修改該參數的值不能被返回,為默認值
OUT 輸出參數:該值可在存儲過程內部被改變,並可返回
INOUT 輸入輸出參數:調用時指定,並且可被改變和返回
調用存儲過程> call procedureName()/call procedureName(params);
2、mysql的變量聲明:
DECLARE variable_name[,variable_name2,variable_name3...] 數據類型 [DEFAULT variable_value];
[]的內容表示可選。來看幾個示例:
DECLARE my_date date DEFAULT '2012-12-31';
DECLARE my_datetime datetime DEFAULT '2012-12-31 23:59:59';
DECLARE my_varchar varchar(255) DEFAULT 'This will not be padded';
3、變量賦值
SET variable_name=variable_value;
4、mysql內置函數
------------------字符操作函數----------------------------
CHARSET(str) //返回字串字符集
CONCAT (string2 [,... ]) //連接字串
INSTR (string ,substring ) //返回substring首次在string中出現的位置,不存在返回0
LCASE (string2 ) //轉換成小寫
LEFT (string2 ,length ) //從string2中的左邊起取length個字符
LENGTH (string ) //string長度
LOAD_FILE (file_name ) //從文件讀取內容
LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定開始位置
LPAD (string2 ,length ,pad ) //重復用pad加在string開頭,直到字串長度為length
LTRIM (string2 ) //去除前端空格
REPEAT (string2 ,count ) //重復count次
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替換search_str
RPAD (string2 ,length ,pad) //在str后用pad補充,直到長度為length
RTRIM (string2 ) //去除后端空格
STRCMP (string1 ,string2 ) //逐字符比較兩字串大小,
SUBSTRING (str , position [,length ]) //從str的position開始,取length個字符,
注:mysql中處理字符串時,默認第一個字符下標為1,即參數position必須大於等於1
TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
UCASE (string2 ) //轉換成大寫
RIGHT(string2,length) //取string2最后length個字符
SPACE(count) //生成count個空格
---------------------------數學函數---------------------------------
ABS (number2 ) //絕對值
BIN (decimal_number ) //十進制轉二進制
CEILING (number2 ) //向上取整
CONV(number2,from_base,to_base) //進制轉換
FLOOR (number2 ) //向下取整
FORMAT (number,decimal_places ) //保留小數位數
HEX (DecimalNumber ) //轉十六進制
注:HEX()中可傳入字符串,則返回其ASC-11碼,如HEX('DEF')返回4142143
也可以傳入十進制整數,返回其十六進制編碼,如HEX(25)返回19
LEAST (number , number2 [,..]) //求最小值
MOD (numerator ,denominator ) //求余
POWER (number ,power ) //求指數
RAND([seed]) //隨機數
ROUND (number [,decimals ]) //四舍五入,decimals為小數位數]
注:返回類型並非均為整數,如:
(1)默認變為整形值
select round(1.23); //打印輸出1
select round(1.56); //打印輸出2
(2)可以設定小數位數,返回浮點型數據
select round(1.567,2); //打印輸出1.57
SIGN (number2 ) //在進行SQL查詢時,我們通常會有這樣一種需求:
對一個自然數進行判斷,如果為零,返回0,如果為負數,統一返回-1, 如果為正數,統一返回1。
-----------------------------日期函數-------------------------------------
ADDTIME (date2 ,time_interval ) //將time_interval加到date2
CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //轉換時區
CURRENT_DATE ( ) //當前日期
CURRENT_TIME ( ) //當前時間
CURRENT_TIMESTAMP ( ) //當前時間戳
DATE (datetime ) //返回datetime的日期部分
DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或時間
DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式顯示datetime
DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上減去一個時間
DATEDIFF (date1 ,date2 ) //兩個日期差
DAY (date ) //返回日期的天
DAYNAME (date ) //英文星期
DAYOFWEEK (date ) //星期(1-7) ,1為星期天
DAYOFYEAR (date ) //一年中的第幾天
EXTRACT (interval_name FROM date ) //從date中提取日期的指定部分
MAKEDATE (year ,day ) //給出年及年中的第幾天,生成日期串
MAKETIME (hour ,minute ,second ) //生成時間串
MONTHNAME (date ) //英文月份名
NOW ( ) //當前時間
SEC_TO_TIME (seconds ) //秒數轉成時間
STR_TO_DATE (string ,format ) //字串轉成時間,以format格式顯示
TIMEDIFF (datetime1 ,datetime2 ) //兩個時間差
TIME_TO_SEC (time ) //時間轉秒數]
WEEK (date_time [,start_of_week ]) //第幾周
YEAR (datetime ) //年份
DAYOFMONTH(datetime) //月的第幾天
HOUR(datetime) //小時
LAST_DAY(date) //date的月的最后日期
MICROSECOND(datetime) //微秒
MONTH(datetime) //月
MINUTE(datetime) //分返回符號,正負或0
SQRT(number2) //開平方
5、在存儲過程中使用邏輯判斷
還是從實例中看比較直觀:
(1)、if then else end if
CREATE PROCEDURE proc2(IN parameter int)
begin
declare var int;
set var=parameter+1;
if var=0 then
insert into t values(17);
end if;
if parameter=0 then
update t set s1=s1+1;
else
update t set s1=s1+2;
end if;
end;
(2)、case語句
CREATE PROCEDURE proc3 (in parameter int)
begin
declare var int;
set var=parameter+1;
case var
when 0 then
insert into t values(17);
when 1 then
insert into t values(18);
else
insert into t values(19);
end case;
end;
(3)、while... end while
CREATE PROCEDURE proc4()
begin
declare var int;
set var=0;
while var<6 do
insert into t values(var);
set var=var+1;
end while;
end;
(4)、loop ... end loop
CREATE PROCEDURE proc5 ()
begin
declare v int;
set v=0;
LOOP_LABLE:loop
insert into t values(v);
set v=v+1;
if v >=5 then
leave LOOP_LABLE;
end if;
end loop;
end;
(5)、迭代Iterate
CREATE PROCEDURE proc6 ()
begin
declare v int;
set v=0;
LOOP_LABLE:loop
if v=3 then
set v=v+1;
ITERATE LOOP_LABLE;
end if;
insert into t values(v);
set v=v+1;
if v>=5 then
leave LOOP_LABLE;
end if;
end loop;
end;
6、Java調用存儲過程訪問mysql示例
(1)、定義不同數據庫實現接口(適用於mysql,sqlserver,oracle等數據庫存儲過程)
package com.boonya.procedure.service;
/**
* 文件:ProcedureService.java
* 功能: 實現mysql數據庫存儲過程的操作
* 注釋:對於功能相同而實現類型不同而言最好先定義接口
* @author PengJunlin
* @date 2013-02-19
*/
public interface ProcedureService {
void createProcedure(String myprocedure,String procedureName);
void usingProcedure(String myprocedure,String param);
void alertProcedure(String myprocedure,String procedureName);
void dropProcedure(String procedureName);
}
(2)、實現接口和測試
package com.boonya.procedure.mysql;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.boonya.procedure.service.ProcedureService;
import com.boonya.procedure.utils.JDBCConnection;
/**
* 文件:MysqlProcedure.java
* 功能: 實現mysql數據庫存儲過程的操作
* 注釋:對於功能相同而實現類型不同而言最好先定義接口,已實現接口
* @author PengJunlin
* @date 2013-02-19
*/
public class MysqlProcedure implements ProcedureService{
static CallableStatement cstmt=null;
static Connection conn=null;
static Statement stmt=null;
static ResultSet rs=null;
static{
JDBCConnection.setConn("mysql");
conn=JDBCConnection.getConn();
}
/**
* 創建數據庫表///溫故而知新
*/
public void createTable(String createSql,String tableName){
try {
stmt=conn.createStatement();
stmt.execute("drop table if exists "+tableName+" ;");
stmt.executeUpdate(createSql);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void createProcedure(String myprocedure,String procedureName){
try {
stmt=conn.createStatement();
stmt.execute("drop procedure if exists "+procedureName+" ;");
stmt.executeUpdate(myprocedure);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void alertProcedure(String myprocedure,String procedureName){
try {
stmt=conn.createStatement();
stmt.execute("drop procedure if exists "+procedureName+" ;");
stmt.executeUpdate(myprocedure);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void usingProcedure(String procedureName,String param){
try {
cstmt=conn.prepareCall("call "+procedureName+"("+param+")");
rs=cstmt.executeQuery();
System.out.println("存儲過程查詢結果:");
while (rs.next()) {
System.out.println(rs.getInt("sno")+" "+rs.getString("sname")
+" "+rs.getInt("sage")+" "+rs.getString("sdept"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void dropProcedure(String procedureName){
try {
String dorpProcedure="drop procedure if exists "+procedureName+" ;";
stmt=conn.createStatement();
stmt.executeUpdate(dorpProcedure);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
class MysqlProcedureTest{
public static void main(String[] args) {
MysqlProcedure mysqlProcedure=new MysqlProcedure();
String mytableString=" create table mytable_mysql " //建表語句
+"("
+" uid int(11) primary key ,"
+" uname varchar(30) ,"
+" uage int(11) , "
+" ubackground varchar(100)"
+");";
mysqlProcedure.createTable(mytableString,"mytable_mysql"); //創建數據表
String myprocedure=" create procedure snoquery(IN no int) "//存儲過程語句
+" BEGIN"
+" declare s_no int;"
+" set s_no=no;"
+" select sno,sname,sage,ssex,sdept "
+" from student where sno=s_no ;"
+" END;";
mysqlProcedure.createProcedure(myprocedure,"snoquery"); //創建存儲過程
mysqlProcedure.usingProcedure("snoquery","12"); //調用存儲過程
String alertProcedure="create procedure snoquery(IN name varchar(30))"
+" BEGIN"
+" declare s_name varchar(30);"
+" set s_name=name;"
+" select sno,sname,sage,ssex,sdept "
+" from student where sname=s_name;"
+" END;";
mysqlProcedure.alertProcedure(alertProcedure,"snoquery"); //修改存儲過程
mysqlProcedure.usingProcedure("snoquery","'boonya007'"); //調用存儲過程
mysqlProcedure.dropProcedure("snoquery"); //刪除存儲過程
}
}
注意:(1) 刪除和創建數據庫表或存儲過程是兩個操作,不能在同一個數據庫聲明語句中執行,否則報SQL語法錯誤。
(2)java中調用存儲過程時,如果參數是字符串一定要加單引號,如:"'sds'";否則拋出異常:Unknown column '字符串參數' in 'field list'
轉自:http://blog.csdn.net/boonya/article/details/8592342