簡單的存儲過程各個關鍵字的用法:php
CREATE DEFINER = CURRENT_USER PROCEDURE `NewProc`(in _xnb varchar(50)) BEGIN ## 定義變量 DECLARE _num FLOAT(14,6) DEFAULT 0; ## @表示全局變量 至關於php $ ## 拼接賦值 INTO 必需要用全局變量否則語句會報錯 ## //CONCAT會把'SELECT SUM('和_xnb和') INTO @tnum FROM btc_user_coin'拼接起來,CONCAT的各個參數中間以","號分割 SET @strsql = CONCAT('SELECT SUM(',_xnb,') INTO @tnum FROM btc_user_coin'); ## 預處理須要執行的動態SQL,其中stmt是一個變量 PREPARE stmt FROM @strsql; ## 執行SQL語句 EXECUTE stmt; ## 釋放掉預處理段 deallocate prepare stmt; ## 賦值給定義的變量 SET _num = @tnum; SELECT _num END;;
Mysql 5.0 之後,支持了動態sql語句,咱們能夠經過傳遞不一樣的參數獲得咱們想要的值html
這裏介紹兩種在存儲過程當中的動態sqljava
1.set sql = (預處理的sql語句,能夠是用concat拼接的語句)mysql
set @sql = sqlsql
PREPARE stmt_name FROM @sql;數據庫
EXECUTE stmt_name;函數
{DEALLOCATE | DROP} PREPARE stmt_name;spa
過程過程示例:.net
CREATE DEFINER = `root`@`%` PROCEDURE `NewProc`(IN `USER_ID` varchar(36),IN `USER_NAME` varchar(36)) BEGIN declare SQL_FOR_SELECT varchar(500); -- 定義預處理sql語句 set SQL_FOR_SELECT = CONCAT("select * from user where user_id = '",USER_ID,"' and user_name = '",USER_NAME,"'"); -- 拼接查詢sql語句 set @sql = SQL_FOR_SELECT; PREPARE stmt FROM @sql; -- 預處理動態sql語句 EXECUTE stmt ; -- 執行sql語句 deallocate prepare stmt; -- 釋放prepare END;
上述是一個簡單的查詢用戶表的存儲過程,當咱們調用此存儲過程,能夠根據傳入不一樣的參數得到不一樣的值。code
可是:上述存儲過程當中,咱們必須在拼接sql語句以前把USER_ID,USER_NAME定義好,並且在拼接sql語句以後,咱們沒法改變USER_ID,USER_NAME的值,以下:
CREATE DEFINER = `root`@`%` PROCEDURE `NewProc`(IN `USER_ID` varchar(36),IN `USER_NAME` varchar(36)) BEGIN declare SQL_FOR_SELECT varchar(500); -- 定義預處理sql語句 set SQL_FOR_SELECT = CONCAT("select * from user where user_id = '",USER_ID,"' and user_name = '",USER_NAME,"'"); -- 拼接查詢sql語句 set @sql = SQL_FOR_SELECT; PREPARE stmt FROM @sql; -- 預處理動態sql語句 EXECUTE stmt ; -- 執行sql語句 deallocate prepare stmt; -- 釋放prepare set USER_ID = '2'; -- 主動指定參數USER_ID的值 set USER_NAME = 'lisi'; set @sql = SQL_FOR_SELECT; PREPARE stmt FROM @sql; -- 預處理動態sql語句 EXECUTE stmt ; -- 執行sql語句 deallocate prepare stmt; -- 釋放prepare END;
咱們用call aa('1','zhangsan');來調用該存儲過程,第一次動態執行,咱們獲得了‘張三’的信息,而後咱們在第14,15行將USER_ID,USER_NAME改成lisi,咱們但願獲得李四的相關信息,可查出來的結果依舊是張三的信息,說明咱們在拼接sql語句後,不能再改變參數了。
爲了解決這種問題,下面介紹第二中方式:
2.set sql = (預處理的sql語句,能夠是用concat拼接的語句,參數用 ?代替)
set @sql = sql
PREPARE stmt_name FROM @sql;
set @var_name = xxx;
EXECUTE stmt_name USING [USING @var_name
[, @var_name
] ...];
{DEALLOCATE | DROP} PREPARE stmt_name;
上述的代碼咱們就能夠改爲 :
CREATE DEFINER = `root`@`%` PROCEDURE `NewProc`(IN `USER_ID` varchar(36),IN `USER_NAME` varchar(36)) BEGIN declare SQL_FOR_SELECT varchar(500); -- 定義預處理sql語句 set SQL_FOR_SELECT = "select * from user where user_id = ? and user_name = ? "; -- 拼接查詢sql語句 set @sql = SQL_FOR_SELECT; PREPARE stmt FROM @sql; -- 預處理動態sql語句 set @parm1 = USER_ID; -- 傳遞sql動態參數 set @parm2 = USER_NAME; EXECUTE stmt USING @parm1 , @parm2; -- 執行sql語句 deallocate prepare stmt; -- 釋放prepare set @sql = SQL_FOR_SELECT; PREPARE stmt FROM @sql; -- 預處理動態sql語句 set @parm1 = '2'; -- 傳遞sql動態參數 set @parm2 = 'lisi'; EXECUTE stmt USING @parm1 , @parm2; -- 執行sql語句 deallocate prepare stmt; -- 釋放prepare END;
這樣,咱們就能夠真正的使用不一樣的參數(固然也能夠在存儲過程當中經過邏輯生成不一樣的參數)來使用動態sql了。
幾個注意:
即便 preparable_stmt 語句中的 ? 所表明的是一個字符串,你也不須要將 ? 用引號包含起來。
由於有可能我不肯定in語句裏有幾個參數,因此我試過這麼寫
set @sql = "select * from user where user_id in (?) "
而後參數我傳的是 "'1','2','3'" 我覺得程序會將個人動態sql解析出來(select * from user where user_id in ('1','2','3')) 可是並無解析出來,在寫存儲過程in裏面的列表用個傳入參數代入的時候,就須要用到以下方式:
1.使用find_in_set函數
select * from table_name t where find_in_set(t.field1,'1,2,3,4');
2.還能夠比較笨實的方法,就是組裝字符串,而後執行
DROP PROCEDURE IF EXISTS photography.Proc_Test; CREATE PROCEDURE photography.`Proc_Test`(param1 varchar(1000)) BEGIN set @id = param1; set @sel = 'select * from access_record t where t.ID in ('; set @sel_2 = ')'; set @sentence = concat(@sel,@id,@sel_2); -- 鏈接字符串生成要執行的SQL語句 prepare stmt from @sentence; -- 預編釋一下。 「stmt」預編釋變量的名稱, execute stmt; -- 執行SQL語句 deallocate prepare stmt; -- 釋放資源 END;
https://blog.csdn.net/www1056481167/article/details/83343341
存儲過程:
一、減小編譯次數
二、簡化操做
三、減小了變異次數減小了和數據庫的連接次數,提升效率
關於存儲過程的方法:
一、刪除存儲過程
DROP PROCEDURE 存儲過程的名稱;
二、查看存儲過程信息
show create procedure 存儲過程名稱;
三、沒有存儲過程的修改
建立語法:
CREATE PROCEDURE 存儲過程名稱(參數列表)
BEGIN
方法體(存儲過程體)一組方法語句;
END
⭐⭐⭐⭐注意:參數列表包括三部分
一、參數模式 參數名 參數類型
eg: IN stuname varchar(20)
參數模式
IN : 該參數能夠做爲輸入,也就是須要調用方傳入值
OUT: 該參數做爲輸出,也就是該參數能夠做爲返回值
INOUT: 既能夠做爲輸入參數,也能夠做爲輸出參數
二、若是存儲過程提僅僅只有一句話,那麼BEGIN END 能夠省略
三、存儲過程當中的每一條sql語句的結尾都必須加封號,須要申明結尾符號 DELIMITER 從新設置
如下在建立的過程當中使用DELIMITER $開始,DELIMITER ;結束,是由於mysql是以;結束的,此處建立存儲過程的時候須要指定結尾符號爲$,整個存儲過程執行完成後,再還原爲mysql的結束符;便可
1、空參存儲過程
DELIMITER $ CREATE PROCEDURE test1() BEGIN INSERT INTO admin(username,`password`) VALUES ('JOHN1','000001'); INSERT INTO admin(username,`password`) VALUES ('JOHN2','000002'); INSERT INTO admin(username,`password`) VALUES ('JOHN3','000003'); INSERT INTO admin(username,`password`) VALUES ('JOHN4','000004'); INSERT INTO admin(username,`password`) VALUES ('JOHN5','000005'); END $
調用:CALL test1();
2、入參存儲過程(此處直接舉例有多個入參的存儲過程的寫法)
# 示例,查詢是否登錄成功
DELIMITER $ CREATE PROCEDURE testParams(IN username varchar(20),IN password varchar(20)) BEGIN DECLARE RESULT VARCHAR(20) DEFAULT '';#申明並初始化 select COUNT(1) INTO RESULT #賦值將統計到的count(1) 賦值給RESULT結果 from admin where admin.username=username #若是參數名相同的話指明參數是那個表的字段便可 and admin.password=password; END $ DELIMITER ;
調用:call testParams('11','22');
3、多個出參的存儲過程(此處直接舉例有多個出餐的存儲過程的寫法)
#根據女神名,查詢男神名和魅力值
DELIMITER $ CREATE PROCEDURE myp7(IN beautyName varchar(20),OUT boyName VARCHAR(20),OUT userCP varchar(20)) BEGIN SELECT bo.boyName,bo.userCP INTO boyName,userCP #此處賦值的時候多個直接INTO爲對應位置的出參對象便可 FROM boys bo INNER JOIN beauty b on bo.id=b.boyfriend_id WHERE b.name=beautyName; END $ DELIMITER ;
調用:CALL myp7('小昭',@boyName,@userCP);
#此處存儲過程的兩個入參(也即出參)用@符號定義便可,也能夠先定義好傳入到裏面
SELECT @boyName AS boyName,@userCP as userCP #查詢存儲過程運行的結果
4、建立帶有INOUT的存儲過程
#案例 傳入a,b 最終a,b翻倍,並返回
DELIMITER $ CREATE PROCEDURE ccgc(INOUT a int,INOUT b int) BEGIN SET a=a*2; SET b=b*2; END $ DELIMITER ;
調用:
###此處須要提早定義參數值,相似於java的入參, SET @m=10; SET @n=30; call ccgc(@m,@n); #而後調用,並打印輸出 select @m,@n ---------------------