本文已轉到我的博客空間 明月工做室http://www.freebytes.net/it/database/mysql-cunchu.htmlhtml
存儲過程 Procedure 是一組爲了完成特定功能的 SQL 語句集合,經編譯後存儲在數據庫中,用戶經過指定存儲過程的名稱並給出參數來執行。存儲過程當中能夠包含邏輯控制語句和數據操縱語句,它能夠接受參數、輸出參數、返回單個或多個結果集以及返回值。java
以上是官方的定義。簡單來講,若是把sql當成是代碼,其實存儲過程就至關於函數。把一組具有特定功能的sql語句封裝成起來而已。因此他的本質是爲了更好的執行對數據庫的操做。那麼好在哪裏呢?mysql
1. 性能。存儲過程在建立時就已經在數據庫服務器中編譯好並存儲起來,調用時只需提供過程名和參數,就能夠直接使用。而sql語句,沒執行一句就要編譯一次,這在sql語句發送並不頻繁的狀況下還好,可是若是短期大量發送sql語句的狀況下,不只會下降網絡性能也會增長數據庫負擔。sql
2. 可完成更復雜的數據庫控制。因爲存儲過程當中能夠包含邏輯控制語句和數據操縱語句,相似遍歷、if這種邏輯能夠直接卸載過程當中。數據庫
3.我在程序中寫了一段代碼,發送一千條sql插入語句到本地數據庫,大概花了6672ms,而在存儲過程當中只花了4689ms。如下分別是代碼和存儲過程sql:服務器
@Autowired private JdbcTemplate jdbcTemplate; public static final String INSERT_SQL="insert into user (id, name, age) values(?,?,?)"; public void insert(){ long begin = System.currentTimeMillis(); for (int i = 600000; i < 601000; i++) { jdbcTemplate.update(INSERT_SQL,i,"林"+i,10+Math.random()*10); } long end = System.currentTimeMillis(); System.out.println(end-begin); }
CREATE PROCEDURE test_insert2 () BEGIN DECLARE i INT DEFAULT 601000; WHILE i<602000 DO insert into `user` (id,NAME,age) values (i,CONCAT('林',i),18); SET i=i+1; END WHILE; COMMIT; END; CALL test_insert2()
1. delimiter // 該語句指定MySQL把「//」看成分隔符。也就是說,若是你在MySQL client中輸入這句,則「;」符號再也不被看成結束符。網絡
2. create procedure getAllUser() 表示建立存儲過程,其名爲getAllUser()。dom
3. call getAllUser ; 調用存儲過程getAllUser。函數
4. drop procedure getAllUser; 刪除存儲過程。性能
5. begin...end 之間編寫過程體,即寫sql語句和邏輯代碼。
6. 存儲過程根據須要可能會有輸入、輸出、輸入輸出參數,若是有多個參數用","分割開。MySQL存儲過程的參數用在存儲過程的定義,共有三種參數類型,IN,OUT,INOUT:
最後輸入 還原分隔符爲 「;」
調用過程
刪除過程
右鍵新建函數,選擇過程
在這裏寫邏輯語句吧,完整以下:
BEGIN DECLARE i INT DEFAULT initValue; WHILE i<=endValue DO insert into `user` (id,NAME,age) values (i,CONCAT('林',i),18); SET i=i+1; END WHILE; COMMIT; END
這裏的意思是 把第一個參數賦給變量i,當i小於第二個參數值時,一直進行while循環,每次循環i+1。
Navicat裏面點擊sql預覽能夠看到完整的代碼:
按下ctrl+s保存:
而後運行,輸入兩個參數,逗號隔開:
就能夠插入數據了。
@Autowired private DataSource dataSource; public List<User> getUser() { List<User> users = new ArrayList<User>(10000); User user = new User(); try { CallableStatement callableStatement = dataSource.getConnection().prepareCall("{call getUser}"); ResultSet rs = null; //執行查詢操做,並獲取結果集 rs = callableStatement.executeQuery(); while (rs.next()){ user.setName(rs.getString("name")); user.setAge(rs.getInt("age")); user.setId(rs.getInt("id")); users.add(user); } } catch (SQLException e) { e.printStackTrace(); } return users; }
調用一個getUser()的存儲過程,並將結果封裝成實體。主要是 CallableStatement callableStatement = dataSource.getConnection().prepareCall("{call getUser}");這句代碼。這裏我認爲應該有更成熟的調用方式纔對,可是我也懶得找資料了。反正原理都同樣。
mysql的自定義函數其實就是咱們本身去定義相似sum(...)、max(...)這種函數,很簡單,建立起來跟存儲過程差很少,就很少作講解了。
create function sum1(x int,y int) returns int(20)
begin
//編寫函數體
return xxx ;
end ;
使用 select sum1(215,555)
刪除 drop sum1