mysql存儲過程,觸發器


存儲過程:
  是在大型數據庫系統中,
  一組為了完成特定功能的SQL 語句集,
  存儲在數據庫中,經過第一次編譯后再次調用不需要再次編譯,
  用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。
  存儲過程是數據庫中的一個重要對象
優點:
  1允許模塊化程序設計(創建一次多次使用)
  2允許更快執行
  3減少網絡流量
  4更好的安全機制
格式:
DELIMITER //
CREATE PROCEDURE 儲存名([ IN ,OUT ,INOUT ]?參數名?數據類形...)
BEGIN
SQL語句
END //
DELIMITER ;


調用過程:
用call 過程名( )


查看所有的存儲過程show procedure status;
查看創建的存儲過程show create procedure 過程名;
刪除過程 drop procedure 過程名

 

In 表示參數從外部傳入到里面使用(過程內部使用)
Out 表示參數從過程里邊把數據保存到變量中,交給外部使用,所有傳入的必須是變量 如果說傳入的out變量本身在外部有數據,那么在進入過程之后,第一件事就是被清空,設為null
Inout 數據可以從外部傳入到過程內部使用,同時內部操作之后,又會將數據返回給外部

-- 聲明結束符
-- 創建存儲過程
DELIMITER $ -- 聲明存儲過程的結束符
CREATE PROCEDURE pro_test() --存儲過程名稱(參數列表)
BEGIN
-- 可以寫多個sql語句; -- sql語句+流程控制
SELECT * FROM employee;
END $ -- 結束 結束符

-- 執行存儲過程
CALL pro_test(); -- CALL 存儲過程名稱(參數);

-- 刪除存儲過程
DROP PROCEDURE pro_test;

參數:
IN: 表示輸入參數,可以攜帶數據帶存儲過程中
OUT: 表示輸出參數,可以從存儲過程中返回結果
INOUT: 表示輸入輸出參數,既可以輸入功能,也可以輸出功能


測試:
1、帶輸入參數
DELIMITER $
CREATE PROCEDURE pro_findById(IN eid INT) -- IN: 輸入參數
BEGIN
SELECT * FROM test01 WHERE id=eid;
END $

 

 

2、帶輸出參數
DELIMITER $
CREATE PROCEDURE pro_testOut(OUT str VARCHAR(20)) -- OUT:輸出參數
BEGIN
-- 給參數賦值
SET str='hellojava';
END $

 

 

3、帶輸入輸出的存儲過程
DELIMITER $
CREATE PROCEDURE pro_testInOut(INOUT n INT) -- INOUT: 輸入輸出參數
BEGIN
-- 查看變量
SELECT n;
SET n =500 + n;
END $

 

 

4、帶有條件判斷的存儲過程
DELIMITER $
CREATE PROCEDURE pro_testIf(in nu INT,out str VARCHAR(20)) -- if 輸入輸出參數
BEGIN
IF nu = 1 then
set str = "周一";
ELSEIF nu = 2 THEN
set str = "周二";
ELSE
set str = "錯誤";
END IF;
END $

 

 

觸發器:
觸發器是一種特殊類型的存儲過程,它又不同於存儲過程,
觸發器主要是通過事件進行觸發而被執行的,而存儲過程可以通過存儲過程名字而被直接調用
作用:
1.可在寫入數據表前,強制檢驗或轉換數據
2.觸發器發生錯誤時,異動的結果會被撤銷
格式
DELIMITER //
Create trigger 觸發器名字 觸發時機 觸發事件 on 表 for each
row
Begin
操作的內容
End //
DELIMITER ;
觸發對象 :on 表 for each row 觸發器綁定實質是表中的所有行,因此當每一行發生改變的時候,就會觸發觸發器
觸發時機:每張表中對應的行都會有不同的狀態,當SQL 指令發生的時候,
都會令行中的數據發生改變,每一行總會有兩個狀態。操作數據之前(before),操作數據(after)之后
觸發事件:
Mysql中觸發器針對的目標是數據發生改變,對應的操作只有(增,刪,改)查詢不發生數據的改變,
所以查詢沒有觸發事件
注意事項:
一張表中,每一個觸發器時機綁定的觸發事件對應的觸發器類型只能有一個;
一張表中只能有一個after insert 觸發器 因此,一張表中最多的觸發器只能有六個

案列
-------------------------------創建存儲過程---------------------------

DELIMITER //
CREATE PROCEDURE addUser
(IN uCode VARCHAR(50),IN uName VARCHAR(20),IN uRole INT,IN sex INT,IN tel VARCHAR(30))
BEGIN
INSERT INTO smbms_user (userCode,userName,userRole,gender,phone)
VALUES(uCode,uName,uRole,sex,tel);
END//
DELIMITER //

查看存儲過程 show procedure status;

java代碼:

<insert id="saveUser">
CALL addUser(#{userCode},#{userName},#{userRole},#{gender},#{phone})
</insert>
public int saveUser(
@Param("userCode") String userCode,
@Param("userName") String userName,
@Param("userRole") Integer userRole,
@Param("gender") Integer gender,
@Param("phone") String phone);

public List<User> findUserListPage(String queryUserName, 
Integer queryUserRole, 
Integer currentPageNo, Integer pageSzie);


public boolean saveUser(String userCode, String userName, Integer userRole,
Integer gender, String phone) {
SqlSession sqlSession = null;
int row = 0; // 受影響的行數
try {
sqlSession = MyBatisUtil.createSqlSession();
row = sqlSession.getMapper(UserMapper.class).saveUser(userCode, userName, userRole, gender, phone);
// 提交事務
sqlSession.commit();
} catch (Exception e) {
if (sqlSession != null) {
sqlSession.rollback();
}
row = 0;
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
if (row > 0) {
return true;
}
return false;
}
userService.saveUser("zhangcuishan", "亞索", 1, 2, "15645678941");

---------------------------------------end--------------------------------------------

創建觸發器

創建兩張表
create table my_goods(
id int primary key auto_increment,
name varchar(20) not null,
inv int
)

create table my_orders(
id int primary key auto_increment,
goods_id int not null,
goods_num int not null)

insert into my_goods values(null,'手機',1000),(null,'電腦',500),(null,'游戲機',100);

DELIMITER //
CREATE TRIGGER a_i_o_t AFTER INSERT ON my_orders FOR EACH ROW
BEGIN
UPDATE my_goods SET inv =inv -new.goods_num WHERE id=new.goods_id;
END
//
DELIMITER ;


DELIMITER //
CREATE TRIGGER b_i_o_t BEFORE INSERT ON my_orders FOR EACH ROW 
BEGIN 
SELECT inv FROM my_goods WHERE id=new.goods_id INTO @inv;
IF @inv <new.goods_num THEN 
INSERT INTO xxx VALUES('xx');
END IF;
END 
//
DELIMITER //

測試 insert into my_orders values(null,3,5);

 

面試相關:
1.存儲過程和函數

存儲過程重在處理數據,函數可以返回值。
(1)存儲過程是procedure用戶定義的一系列sql語句的集合,涉及特定表或其他對象的任務,用戶可以調用存儲過程。
(2)函數通常是數據庫已定義的方法,它接收參數並返回某種類型的值並且不涉及特定用戶表。
(3)可以理解函數是存儲過程的一種,都是預編譯的(塊語句每次運行都會編譯 存儲過程塊 一次編譯多次運行 效率更高)
plsql塊語句:
Begin
End
存儲過程塊
Create procedure prg_add()
As
Begin
End;
(4)函數可以沒有參數,但是一定要有一個返回值,存儲過程可以沒有參數,不需要返回值。
(5)函數return返回值沒有返回參數模式,存儲過程通過out參數返回值,如果需要返回多個參數則建議使用存儲過程(函數oracle 在函數可以使用in和out mysql不能使用out)
(6)在sql數據操縱(DML)語句中只能調用函數而不能調用存儲過程

2.存儲過程的概念,優點(或特點),寫一個簡單的存儲過程

存儲過程:是一組為了完成特定功能的SQL語句集,利用SQL Server所提供的T-SQL語言所編寫的程序,經編譯后存儲在數據庫中。
優點:
(1)執行速度快,存儲過程只在創建時進行編譯,以后每次執行不需要再重新編譯,一般sql語句每執行一次就編譯一次
(2)存儲過程可重復使用
(3)安全性高(可設定只有某些用戶才具有對指定存儲過程的使用權)
(4)當對數據庫進行復雜操作時,可完成復雜的判斷和比較復雜的運算,可用存儲過程封裝起來
(5)易於維護和集中控制,當企業規則變化時在服務器中改變存儲過程即可。無需修改 應用程序。
簡單的存儲過程:
create proc select_query @year int
as
select * from tmp where year=@year

3.觸發器

(1)觸發器:觸發器可以看成是一個特殊的存儲過程,存儲過程是要顯示調用去完成,而觸發器可以自動完成。比如:當數據庫中的表發生增刪改操作時,對應的觸發器就可以執行對應的PL/SQL語句塊
(2)作用:維護表的完整性,記錄表的修改來審計表的相關信息
分為:
DML觸發器:當數據庫服務器中發生數據操作語言事件時執行的存儲過程,分為:After觸發器和instead of觸發器
DDL觸發器:特殊的觸發器,在響應數據定義語言(DDL)語句時觸發,一般用於數據庫中執行管理任務。DDL觸發器是響應create、after、或drop開頭的語句而激活
觸發器用處還是很多的,比如校內網、開心網、Facebook,你發一個日志,自動通知好友,其實就是在增加日志時做一個后觸發,再向通知表中寫入條目。因為觸發器效率高

存儲函數:
什么是存儲函數: 封裝一段sql代碼,完成一種特定的功能,返回結果。
存儲函數的語法:
  create function 函數([函數參數[,….]]) Returns 返回類型
  Begin
    If(
      Return (返回的數據)
    Else
      Return (返回的數據)
    end if;
  end;
例如: create function count_news(hits int) returns int
  與存儲過程返回參數不同的是存儲函數在定義時沒用直接聲明哪個變量是返回參數,而只是使用了returns聲明了返回參數所屬的數據類型,返回參數是在函數體中使用return返回要返回的數據變量的形式來表示的。這就需要注意的是:
存儲函數只支持輸入參數,並且輸入參數前沒有IN或INOUT.
存儲函數中的限制
流控制(Flow-of-control)語句(IF, CASE, WHILE, LOOP, WHILE, REPEAT, LEAVE,ITERATE)也是合法的.
變量聲明(DECLARE)以及指派(SET)是合法的.
允許條件聲明.
異常處理聲明也是允許的.
但是在這里要記住函數有受限條件:不能在函數中訪問表.因此在函數中使用以下語句是非法的。
ALTER 'CACHE INDEX' CALL COMMIT CREATE DELETE
DROP 'FLUSH PRIVILEGES' GRANT INSERT KILL
LOCK OPTIMIZE REPAIR REPLACE REVOKE
ROLLBACK SAVEPOINT 'SELECT FROM table'
'SET system variable' 'SET TRANSACTION'
SHOW 'START TRANSACTION' TRUNCATE UPDATE

存儲函數與存儲過程的區別
一、 存儲函數有且只有一個返回值,而存儲過程不能有返回值。
二、 函數只能有輸入參數,而且不能帶in, 而存儲過程可以有多個in,out,inout參數。
三、 存儲過程中的語句功能更強大,存儲過程可以實現很復雜的業務邏輯,而函數有很多限制,如不能在函數中使用insert,update,delete,create等語句;存儲函數只完成查詢的工 作,可接受輸入參數並返回一個結果,也就是函數實現的功能針對性比較強。
四、 存儲過程可以調用存儲函數。但函數不能調用存儲過程。
五、 存儲過程一般是作為一個獨立的部分來執行(call調用)。而函數可以作為查詢語句的一個部分來調用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM