原文地址: https://blog.csdn.net/H_Rhui/article/details/96920260css
最近看到觸發器以後,就想了解一下 存儲過程。觸發器是一種和表關聯的特殊的存儲過程。mysql
MySQL 5.0 版本開始支持存儲過程。sql
存儲過程(Stored Procedure)是一種在數據庫中存儲複雜程序,以便外部程序調用的一種數據庫對象。數據庫
存儲過程是爲了完成特定功能的SQL語句集,經編譯建立並保存在數據庫中,用戶可經過指定存儲過程的名字並給定參數(須要時)來調用執行。express
存儲過程思想上很簡單,就是數據庫 SQL 語言層面的代碼封裝與重用。編程
聲明語句結束符,能夠自定義: DELIMITER $$ 或 DELIMITER // 聲明存儲過程: CREATE PROCEDURE demo_in_parameter(IN p_in int) 存儲過程的開始和結束符號: BEGIN …… END 變量賦值: SET @p_in=1 變量定義: DECLARE l_int int unsigned default 5000000; 建立過程體: create function 存儲函數名(參數)
存儲過程體緩存
BEGIN BEGIN BEGIN statements; END END END
注意:每一個嵌套塊及其中的每條語句,必須以分號結束,表示過程體結束的begin-end塊(又叫作複合語句compound statement),則不須要分號。安全
爲語句塊貼標籤: 服務器
[begin_label:] BEGIN [statement_list] END [end_label]
例如: 網絡
label1: BEGIN label2: BEGIN label3: BEGIN statements; END label3 ; END label2; END label1
MySQL存儲過程的參數用在存儲過程的定義,共有三種參數類型,IN,OUT,INOUT,形式如:
CREATEPROCEDURE 存儲過程名([[IN |OUT |INOUT ] 參數名 數據類型...])
1)in 輸入參數
mysql> delimiter $$ mysql> create procedure in_param(in p_in int) -> begin -> select p_in; -> set p_in=2; -> select P_in; -> end$$ mysql> delimiter ; mysql> set @p_in=1; mysql> call in_param(@p_in); +------+ | p_in | +------+ | 1 | +------+ +------+ | P_in | +------+ | 2 | +------+ mysql> select @p_in; +-------+ | @p_in | +-------+ | 1 | +-------+
以上能夠看出,p_in 在存儲過程當中被修改,但並不影響 @p_id 的值,由於前者爲局部變量、後者爲全局變量。
使用 Navicat 建立存儲過程:
BEGIN SELECT p_in; SET p_in = 2; SELECT p_in; END
2) out輸出參數
mysql> delimiter // mysql> create procedure out_param(out p_out int) -> begin -> select p_out; -> set p_out=2; -> select p_out; -> end -> // mysql> delimiter ; mysql> set @p_out=1; mysql> call out_param(@p_out); +-------+ | p_out | +-------+ | NULL | +-------+ #由於out是向調用者輸出參數,不接收輸入的參數,因此存儲過程裏的p_out爲null +-------+ | p_out | +-------+ | 2 | +-------+ mysql> select @p_out; +--------+ | @p_out | +--------+ | 2 | +--------+ #調用了out_param存儲過程,輸出參數,改變了p_out變量的值
3) inout 輸入參數
mysql> delimiter $$ mysql> create procedure inout_param(inout p_inout int) -> begin -> select p_inout; -> set p_inout=2; -> select p_inout; -> end -> $$ mysql> delimiter ; mysql> set @p_inout=1; mysql> call inout_param(@p_inout); +---------+ | p_inout | +---------+ | 1 | +---------+ +---------+ | p_inout | +---------+ | 2 | +---------+ mysql> select @p_inout; +----------+ | @p_inout | +----------+ | 2 | +----------+ #調用了inout_param存儲過程,接受了輸入的參數,也輸出參數,改變了變量
注意:
一、若是過程沒有參數,也必須在過程名後面寫上小括號例:
CREATE PROCEDURE sp_name ([proc_parameter[,...]]) ……
二、確保參數的名字不等於列的名字,不然在過程體中,參數名被當作列名來處理
建議:
1) 變量定義
局部變量聲明必定要放在存儲過程體的開始:
datatype 爲 MySQL 的數據類型,如: int, float, date,varchar(length)
DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
例如:
DECLARE l_int int unsigned default 4000000; DECLARE l_numeric number(8,2) DEFAULT 9.95; DECLARE l_date date DEFAULT '1999-12-31'; DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59'; DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded';
2)變量賦值
SET 變量名 = 表達式值 [,variable_name = expression ...]
3)用戶變量
在MySQL客戶端使用用戶變量:
mysql > SELECT 'Hello World' into @x; mysql > SELECT @x; +-------------+ | @x | +-------------+ | Hello World | +-------------+ mysql > SET @y='Goodbye Cruel World'; mysql > SELECT @y; +---------------------+ | @y | +---------------------+ | Goodbye Cruel World | +---------------------+ mysql > SET @z=1+2+3; mysql > SELECT @z; +------+ | @z | +------+ | 6 | +------+
在存儲過程當中使用用戶變量
CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World'); SET @greeting='Hello'; CALL GreetWorld( ); -- 輸出: hello World
在存儲過程間傳遞全局範圍的用戶變量
CREATE PROCEDURE p1() SET @last_procedure='p1'; CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_procedure); CALL p1(); CALL p2(); -- 輸出 Last procedure was p1
注意:
-- 查詢存儲過程 show procedure status where db='test'; -- 刪除存儲過程 DROP PROCEDURE p1; DROP PROCEDURE p2;
1) 變量做用域
DELIMITER // CREATE PROCEDURE proc3() BEGIN declare x1 varchar(5) default 'outer'; BEGIN DECLARE x1 VARCHAR (5) DEFAULT 'inner' ; SELECT x1 ; END; SELECT x1 ; END;// DELIMITER ; CALL proc3(); -- 輸出 inner -- 輸出 outer
2). 條件語句
-- 建立表用來測試 CREATE TABLE `t` ( `s` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- 初始化一條數據 INSERT INTO `test`.`t` (`s`) VALUES (0); DELIMITER // CREATE PROCEDURE proc2(IN parameter int) BEGIN declare var int; set var=parameter+1; if var=0 THEN INSERT INTO t VALUES(1); end if; if parameter=0 then update t set s=s+1; else update t set s=s+2; end if; END;// DELIMITER ; // 調用存儲過程 CALL proc2(1); // 刪除存儲過程 drop PROCEDURE proc2;
查詢是否開啓了慢查詢:
show variables like '%slow%'; -- Mysql 默認是關閉的
-- 開啓慢查詢 set global slow_query_log=1; -- 查看統計的時長 show variables like 'long_query_time'; --修改統計的時長爲一秒。 請注意,修改以後,當前會話無效,從新鏈接以後能夠看到修改效果 set global long_query_time=1;
-- 查看當前安裝的數據庫 支持哪些 引擎 show engines; -- 查看當前數據庫使用的哪一種引擎 SHOW VARIABLES LIKE 'storage_engine';
經常使用的存儲引擎 :Myisam innodb(目前應該是默認使用 innodb) memory
Myisam 存儲引擎:MyISAM基於ISAM存儲引擎,並對其進行擴展。它是在Web、數據倉儲和其餘應用環境下最常使用的存儲引擎之一。MyISAM擁有較高的插入、查詢速度,但不支持事物。
Innodb 存儲引擎:InnoDB是事務型數據庫的首選引擎,支持事務安全表(ACID),支持行鎖定和外鍵
Memory :MEMORY存儲引擎將表中的數據存儲到內存中,當咱們的數據頻繁變化的時候,並且不須要入庫,這個時候用memory存儲引擎。
優化小技巧
1. 對查詢進行優化,要儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引。2. 應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描3. 應儘可能避免在 where 子句中使用 != 或 <> 操做符,不然將引擎放棄使用索引而進行全表掃描。4. 應儘可能避免在 where 子句中使用 or 來鏈接條件,若是一個字段有索引,一個字段沒有索引,將致使引擎放棄使用索引而進行全表掃描,如select id from t where num=10 or Name = 'admin'能夠這樣查詢:select id from t where num = 10 union all select id from t where Name = 'admin'5. select count(*) from table;這樣不帶任何條件的count會引發全表掃描,而且沒有任何業務意義,是必定要杜絕的。調優參數:6. back_log:back_log值指出在MySQL暫時中止回答新請求以前的短期內多少個請求能夠被存在堆棧中。也就是說,若是MySql的鏈接數據達到max_connections時,新來的請求將會被存在堆棧中,以等待某一鏈接釋放資源,該堆棧的數量即back_log,若是等待鏈接的數量超過back_log,將不被授予鏈接資源。7. wait_timeout:數據庫鏈接閒置時間,閒置鏈接會佔用內存資源。8. max_user_connection: 最大鏈接數,默認爲0無上限,最好設一個合理上限9. thread_concurrency:併發線程數,設爲CPU核數的兩倍10. skip_name_resolve:禁止對外部鏈接進行DNS解析,消除DNS解析時間,但須要全部遠程主機用IP訪問11. key_buffer_size:索引塊的緩存大小,增長會提高索引處理速度,對MyISAM表性能影響最大。對於內存4G左右,可設爲256M或384M,經過查詢show status like 'key_read%',保證key_reads / key_read_requests在0.1%如下最好12. innodb_buffer_pool_size:緩存數據塊和索引塊,對InnoDB表性能影響最大。經過查詢show status like 'Innodb_buffer_pool_read%',保證(Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests越高越好13. innodb_additional_mem_pool_size:InnoDB存儲引擎用來存放數據字典信息以及一些內部數據結構的內存空間大小,當數據庫對象很是多的時候,適當調整該參數的大小以確保全部數據都能存放在內存中提升訪問效率,當太小的時候,MySQL會記錄Warning信息到數據庫的錯誤日誌中,這時就須要該調整這個參數大小14. innodb_log_buffer_size:InnoDB存儲引擎的事務日誌所使用的緩衝區,通常來講不建議超過32MB15. query_cache_size:緩存MySQL中的ResultSet,也就是一條SQL語執行的結果集,因此僅僅只能針對select語句。當某個表的數據有任何任何變化,都會致使全部引用了該表的select語句在Query Cache中的緩存數據失效。因此,當咱們的數據變化很是頻繁的狀況下,使用Query Cache可能會得不償失。根據命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進行調整,通常不建議太大,256MB可能已經差很少了,大型的配置型靜態數據可適當調大.能夠經過命令show status like 'Qcache_%'查看目前系統Query catch使用大小16. read_buffer_size:MySql讀入緩衝區大小。對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會爲它分配一段內存緩衝區。若是對錶的順序掃描請求很是頻繁,能夠經過增長該變量值以及內存緩衝區大小提升其性能17. sort_buffer_size:MySql執行排序使用的緩衝大小。若是想要增長ORDER BY的速度,首先看是否可讓MySQL使用索引而不是額外的排序階段。若是不能,能夠嘗試增長sort_buffer_size變量的大小18. read_rnd_buffer_size:MySql的隨機讀緩衝區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀緩存區。進行排序查詢時,MySql會首先掃描一遍該緩衝,以免磁盤搜索,提升查詢速度,若是須要排序大量數據,可適當調高該值。但MySql會爲每一個客戶鏈接發放該緩衝空間,因此應儘可能適當設置該值,以免內存開銷過大。19. record_buffer:每一個進行一個順序掃描的線程爲其掃描的每張表分配這個大小的一個緩衝區。若是你作不少順序掃描,可能想要增長該值20. thread_cache_size:保存當前沒有與鏈接關聯可是準備爲後面新的鏈接服務的線程,能夠快速響應鏈接的線程請求而無需建立新的21. table_cache:相似於thread_cache_size,但用來緩存表文件,對InnoDB效果不大,主要用於MyISAM