http://my.oschina.net/zerotime/blog/113126
Mysql命令行創建存儲過程時,首先要輸入分隔符
DELIMITER //
CREATE PROCEDURE proc ()
begin
……
end
//
OK,可以創建完成了。
顯示存儲過程命令
show create procedure 存儲過程名;
刪除存儲過程命令
drop procedure 存儲過程名;
http://database.51cto.com/art/201011/235017.htm
MYSQL命令行的使用是學習MYSQL數據庫過程中的基礎知識,那么應該如何用MYSQL命令行創建存儲過程呢?
也嘗試了一些方法,但是第一個分號mysql就以為語句結束了,就舉個例子來說:
- CREATE PROCEDURE p7 (IN b INTEGER(12))
- begin
- declare a INTEGER(12);
- set a=5;
- INSERT INTO t VALUES (a);
- SELECT s1*a FROM t WHERE b<=s1;
- End
這個存儲過程,在命令行直接創建的話,在第三排你輸入分號后就報錯了……因為MYSQL以為這個語句結束了,那對於MYSQL而言
- CREATE PROCEDURE p7 (IN b INTEGER(12))
- begin
- declare a INTEGER(12);
肯定是個錯誤語句。
然后看了些東西,原來要加分隔符- -……….
- DELIMITER //
- CREATE PROCEDURE p7 (IN b INTEGER(12))
- begin
- declare a INTEGER(12);
- set a=5;
- INSERT INTO t VALUES (a);
- SELECT s1*a FROM t WHERE b<=s1;
- End
- //
就OK了…………意思就是說在//……//之間的當成一個語句執行所以MYSQL接到的才是這個存儲過程完整的創建語句。
http://zhuixue.iteye.com/blog/375353
查詢數據庫中的存儲過程
方法一:
select `name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE'
方法二:
show procedure status;
查看存儲過程或函數的創建代碼
show create procedure proc_name;
show create function func_name;
http://www.111cn.net/database/mysql/35817.htm
方法一:(直接查詢)
select `specific_name` from mysql.proc where db = 'your_db_name' and `type` = 'procedure'
方法二:(查看數據庫里所有存儲過程+內容)
show procedure status;
方法三:(查看當前數據庫里存儲過程列表)
select specific_name from mysql.proc ;
方法四:(查看某一個存儲過程的具體內容)
select body from mysql.proc where specific_name = 'your_proc_name';
查看存儲過程或函數的創建代碼 :
show create procedure your_proc_name;
show create function your_func_name;
刪除存儲過程:
drop procedure your_proc_name;
=============
http://543197.blog.51cto.com/533197/114141
文章引用:
[url]http://bbs.tarena.com.cn/viewthread.phptid=166328[/url]
“pr_add” 是個簡單的 MySQL 存儲過程,這個存儲過程有兩個 int 類型的輸入參數 “a”、“b”,返回這兩個參數的和。
drop procedure if exists pr_add;
-- 計算兩個數之和
create procedure pr_add
(
a int,
b int
)
begin
declare c int;
if a is null then
set a = 0;
end if;
if b is null then
set b = 0;
end if;
set c = a + b;
select c as sum;
/*
return c; -- 不能在 MySQL 存儲過程中使用。return 只能出現在函數中。
*/
end;
二、調用 MySQL 存儲過程
call pr_add(10, 20);
執行 MySQL 存儲過程,存儲過程參數為 MySQL 用戶變量。
set @a = 10;
set @b = 20;
call pr_add(@a, @b);
三、MySQL 存儲過程特點
創建 MySQL 存儲過程的簡單語法為:
create procedure 存儲過程名字()
(
[in|out|inout] 參數 datatype
)
begin
MySQL 語句;
end;
MySQL 存儲過程參數如果不顯式指定“in”、“out”、“inout”,則默認為“in”。習慣上,對於是“in” 的參數,我們都不會顯式指定。
1. MySQL 存儲過程名字后面的“()”是必須的,即使沒有一個參數,也需要“()”
2. MySQL 存儲過程參數,不能在參數名稱前加“@”,如: “@a int”。下面的創建存儲過程語法在 MySQL 中是錯誤的(在 SQL Server 中是正確的)。 MySQL 存儲過程中的變量,不需要在變量名字前加“@”,雖然 MySQL 客戶端用戶變量要加個“@”。
create procedure pr_add
(
@a int, -- 錯誤
b int -- 正確
)
3. MySQL 存儲過程的參數不能指定默認值。
4. MySQL 存儲過程不需要在 procedure body 前面加 “as”。而 SQL Server 存儲過程必須加 “as” 關鍵字。
create procedure pr_add
(
a int,
b int
)
as -- 錯誤,MySQL 不需要 “as”
begin
mysql statement ...;
end;
5. 如果 MySQL 存儲過程中包含多條 MySQL 語句,則需要 begin end 關鍵字。
create procedure pr_add
(
a int,
b int
)
begin
mysql statement 1 ...;
mysql statement 2 ...;
end;
6. MySQL 存儲過程中的每條語句的末尾,都要加上分號 “;”
...
declare c int;
if a is null then
set a = 0;
end if;
...
end;
7. MySQL 存儲過程中的注釋。
/*
這是個
多行 MySQL 注釋。
*/
declare c int; -- 這是單行 MySQL 注釋 (注意 -- 后至少要有一個空格)
if a is null then # 這也是個單行 MySQL 注釋
set a = 0;
end if;
...
end;
8. 不能在 MySQL 存儲過程中使用 “return” 關鍵字。
set c = a + b;
select c as sum;
/*
return c; -- 不能在 MySQL 存儲過程中使用。return 只能出現在函數中。
*/
end;
9. 調用 MySQL 存儲過程時候,需要在過程名字后面加“()”,即使沒有一個參數,也需要“()”
call pr_no_param();
10. 因為 MySQL 存儲過程參數沒有默認值,所以在調用 MySQL 存儲過程時候,不能省略參數。可以用 null 來替代。
call pr_add(10, null);
===================================================
http://www.cnblogs.com/gaizai/archive/2013/03/15/2961868.html
一.本文所涉及的內容(Contents)
二.背景(Contexts)
之前我寫過關於SQL Server的數據遷移自動化的文章:SQL Server 數據庫遷移偏方,在上篇文章中設計了一張臨時表,這個臨時表記錄搬遷的配置信息,用一個存儲過程讀取這張表進行數據的遷移,再由一個Job進行迭代調用這個存儲過程。
在這次MySQL的實戰中,我的數據庫已經做了4個分片,分布在不同的4台機器上,每台機器上的數據量有1.7億(1.7*4=6.8億),占用空間260G(260*4=1040G),這次遷移的目的就是刪除掉一些歷史記錄,減輕數據庫壓力,有人說這為什么不使用表分區呢?這跟我們的業務邏輯有關造成無法使用表分區,至於為什么,參考閱讀:MySQL表分區實戰,其中最重要就是唯一索引的問題,擴展閱讀:MySQL當批量插入遇上唯一索引,這篇文章需要了解MySQL的定時器的一些知識:MySQL定時器Events
本文與SQL Server 數據庫遷移偏方最大的不同就是MySQL的Events不是串行執行的,當作業調用的存儲過程還沒有執行完畢,但又到了調度的時間,MySQL不會等待上次作業完成之后再調度,所以會造成重復調用讀取到相同的數據;而SQL Server並不存在上面的問題。
三.設計思路(Design)
1. 創建一個臨時表TempBlog_Log,這個表用於保存每次轉移數據的ID起始值和結束值,以及搬遷的開始時間和結束時間;(這個ID是我們要遷移表的主鍵,自增字段,唯一標識)
2. 創建一個存儲過程InsertData(),這個存儲過程用於在TempBlog_Log表中插入記錄,創建這個存儲過程是因為MySQL跟SQL Server有些不同,MySQL不支持匿名存儲過程,SQL Server直接執行SQL就可以了,無需為這些SQL再創建一個存儲過程,這就是匿名存儲過程了;
3. 創建一個存儲過程MoveBlogData(),這個存儲過程用於在TempBlog_Log表中讀取記錄,再批量把BlogA數據轉移到BlogB中;這個是核心邏輯,解決了定時器重復調度的問題,詳情見代碼的解釋;
4. 創建一個定時器e_Blog, 這個定時器定時調用存儲過程MoveBlogData(),但是這里存在重復調度的問題,只能通過存儲過程MoveBlogData()進行控制。
四.遷移自動化特點(Points)
1. 該設計適應於大數據的遷移;
2. 可以最小化宕機時間(在轉移的過程中BlogA還是一直在進數據的,只是在最后一部分數據的時候需要短時間的停入庫操作);
3. 可以防止MySQL定時器重復執行所帶來的問題;
4. 可以實時監控數據轉移的進度;
5. 數據遷移可能需要持續好幾天的時間,它能保證BlogB的數據會無限的接近BlogA的數據;
五.實現代碼(SQL Codes)
(一) 創建臨時表TempBlog_Log
-- 創建表
CREATE TABLE TempBlog_Log(
BeginId INT NOT NULL,
EndId INT NOT NULL,
IsDone BIT DEFAULT b'0' NOT NULL,
BeginTime DATETIME DEFAULT NULL,
EndTime DATETIME DEFAULT NULL,
PRIMARY KEY(BeginId)
);
下面就對表結構進行字段解釋:
1) BeginId、EndId都是ServerA遷移表的主鍵值,BeginId表示一次數據遷移的起始值,EndId表示一次數據遷移的結束值,兩個值的差就是這次數據轉移的數據量;
2) IsDone 表示是否已經成功轉移數據;
3) BeginTime表示轉移的開始時間,EndTime表示轉移的結束時間,這兩個字段設置缺省值為NULL很關鍵,是后面進行判斷是否重復執行的依據;
(二) 創建存儲過程InsertData()
-- 存儲過程
DELIMITER $$
USE `DataBaseName`$$
DROP PROCEDURE IF EXISTS `InsertData`$$
CREATE DEFINER=`root`@`%` PROCEDURE `InsertData`()
BEGIN
DECLARE ids_begin,ids_end,ids_increment INT;
SET ids_begin=130000000;-- 需要轉移開始Id值
SET ids_end=210000000;-- 需要轉移結束Id值
SET ids_increment=200000;-- 每次轉移的Id量
WHILE ids_begin < ids_end DO
INSERT INTO TempBlog_Log(BeginId,EndId) VALUES(ids_begin,ids_begin+ids_increment);
SET ids_begin = ids_begin + ids_increment;
END WHILE;
END$$
DELIMITER ;
MySQL中不支持匿名存儲過程,所以為了在臨時表TempBlog_Log插入記錄,只能創建一個存儲過程了,如果你還沒寫過MySQL的存儲過程,那么這是一個很好的例子。
1) 為了能在存儲過程中使用MySQL的分隔符“;”,DELIMITER $$表示你以“$$”作為分隔符,你也可以使用“//”;
2) 定義變量時,你需要把所有的變量定義完了,之后再進行賦值,不然會報錯,這跟SQL Server是有區別的;
3) WHILE條件后面需要加DO,而且要以END WHILE;作為結束標記;
4) 作為存儲過程的結束,再次出現“$$”表示已經結束,跟上一個“$$”形成一個整體、過程,並重新設置“;”為分隔符;
5) 執行CALL InsertData();調用上面的存儲過程,插入數據,調用完畢的結果如下圖Figure1所示:
(Figure1:轉移前狀態)
(三) 創建保留數據的新表BlogB
做完上面的准備工作,接下來就是創建與BlogA相同結構的BlogB表了,有些不同的就是不需要在BlogB創建太多的索引,只需要存儲兩個索引就可以了,一個是ID的聚集索引,一個是唯一索引(在批量插入的時候需要判重);
上面索引是根據我業務上的需求決定的,你需要視情況而定;
(四) 創建存儲過程MoveBlogData()
DELIMITER $$
USE `DataBaseName`$$
DROP PROCEDURE IF EXISTS `MoveBlogData`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `MoveBlogData`()
BEGIN
DECLARE blog_ids_begin INT;-- Id起始值
DECLARE blog_ids_end INT;-- Id結束值
DECLARE blog_ids_max INT;-- BlogA表現在的最大值
DECLARE blog_begintime INT;-- 執行開始時間
DECLARE blog_endtime INT;-- 執行結束時間
-- 查詢TempBlog_Log表還沒有done的記錄
SELECT BeginId,EndId,BeginTime,EndTime INTO blog_ids_begin,blog_ids_end,blog_begintime,blog_endtime FROM TempBlog_Log WHERE IsDone = 0 ORDER BY BeginId LIMIT 0,1;
-- 防止了定時器的重復執行
IF(blog_begintime IS NULL AND blog_endtime IS NULL) THEN
-- 設置當前最大的Id值
SELECT MAX(ids) INTO blog_ids_max FROM BlogA;
-- 防止轉移超過當前最大值的Id數據
IF(blog_ids_begin != 0 AND blog_ids_end != 0 AND blog_ids_max >= blog_ids_end) THEN
-- 更新執行開始時間
UPDATE TempBlog_Log SET BeginTime = NOW() WHERE BeginId = blog_ids_begin;
-- 插入Id段數據,忽略重復值
INSERT IGNORE INTO BlogB (ID,AuthorID,Content,QUOTE,QuoteID,Author,TIME,Url,ImageUrl,Transmits,Comments,HASH,Site,AuthorUID,TYPE,HotTopic,AddOn,QuoteAuthorID,IDs)
SELECT ID,AuthorID,Content,QUOTE,QuoteID,Author,TIME,Url,ImageUrl,Transmits,Comments,HASH,Site,AuthorUID,TYPE,HotTopic,AddOn,QuoteAuthorID,IDs
FROM BlogA WHERE IDs >= blog_ids_begin AND IDs < blog_ids_end;
-- 更新執行結束時間
UPDATE TempBlog_Log SET IsDone = 1,EndTime = NOW() WHERE BeginId = blog_ids_begin;
END IF;
END IF;
END$$
DELIMITER ;
這個存儲過程是整個搬遷數據的核心代碼,之所以說是核心,是因為它把比較多的細節考慮進去,基本上實現自動化的目的。
1) 代碼中IF(blog_begintime IS NULL AND blog_endtime IS NULL) 防止了定時器的重復執行,兩個值都為NULL的時候表示這個Id段的數據還沒有被轉移,這樣就可以跳過,不執行下面的邏輯;
2) 查詢BlogA的最大值可以防止轉移超過當前BlogA最大值的Id數據,只有當blog_ids_max>=blog_ids_end才符合轉移的條件;
3) 在MySQL中對唯一索引約束的數據操作有很多的關鍵字支持,INSERT IGNORE INTO就是在批量插入過程中只插入沒有的數據,忽略重復的數據;更多唯一索引的信息:MySQL當批量插入遇上唯一索引
4) 查詢中FROM BlogA WHERE IDs >= blog_ids_begin AND IDs < blog_ids_end;需要注意IDs值的閉合關系,不然造成重復數據或者丟失數據;
(五) 創建定時器e_Blog
DELIMITER $$ CREATE DEFINER=`root`@`localhost` EVENT `e_blog` ON SCHEDULE EVERY 30 SECOND STARTS '2012-12-07 14:58:53' ON COMPLETION PRESERVE DISABLE DO CALL MoveBlogData()$$ DELIMITER ;
這定時器e_Blog的作用是在每隔30 SECOND調用一次存儲過程MoveBlogData(),至於有沒轉移數據那就是存儲過程判斷了,跟定時器的調度頻率完全沒有關系,更多關於定時器的信息:MySQL定時器Events
(六) 監控數據轉移的狀態
當定時器啟動后,可以查看TempBlog_Log表監控調度的進度:
(Figure2:轉移中狀態)
Figure2表示正在轉移Id>=225200000到Id<225400000這20W的數據;
你也可以通過下面的SQL進行統計:
SELECT IsDone,COUNT(1) FROM tempblog_log GROUP BY IsDone ORDER BY IsDone DESC;
(七) 創建索引
創建保留數據的新表BlogB的時候不要創建不必要的索引,等轉移完數據之后再創建回相關的索引;這樣做的目的是在插入數據的時候不需要對索引進行維護,並且到轉移完之后再創建索引可以讓索引更加沒有索引碎片;
(八) 禁用定時器
當TempBlog_Log表不再更新的時候,我們就可以禁用定時器了。因為BlogA表是一直在進數據的,所以當TempBlog_Log不再更新就說明數據已經基本轉移完畢了(新增的數據量小於20W),這個時候就可以禁用定時器了。
(九) 轉移最后數據
首先停止對BlogA表的入庫操作,通過SQL轉移最后一部分的數據到BlogB中,轉移完之后修改表名就大功告成了。
六.參考文獻(References)
=========================================================
http://liuer.blog.51cto.com/1519559/1084499
? [root@localhost bin]# mysqldump -uroot -p -hlocalhost -P3306 -n -d -t -R DBName > procedure_name.sql
參數說明:
-n: --no-create-db
-d: --no-data
-t: --no-create-info
-R: --routines Dump stored routines (functions and procedures)
Mysqldump是客戶端工具用來備份數據庫或在不同數據庫之間進行數據遷移。備份內容包含創建活裝載表的 SQL語句:
主要參數介紹:
1.連接選項
-u,--user=name
-p,--password=name
-h,--host=name
-P,--port=#
2.輸出內容選項
--add-drop-database
--add-drop-table
-n;--no-create-db
-d;--no-data
-t;--no-create-info
3.輸出格式選項
--compact
-c --complete-insert
-T(指定數據表中的數據備份為單純的數據文件和建表SQL兩個文件)
注意:xx.sql建表文件是以linux的root用戶創建,而xx.txt文件則是一linux的mysql用戶創建,因此這兩個文件的存放路徑一定要保證mysql用戶有讀寫創建文件的權限。
--fields-terminated-by=name(域分隔符)
--fields-enclosed-by=name(域引用符)
--fields-optionally-enclosed-by=name(域引用可選字符)
--fields-escaped-by=name(轉義字符)
4.字符集選項
--default--character-set=xx
5.其他選項
-F --flush-logs(備份前刷新日志)
-l --lock-tables(給所有的表加讀鎖)
http://www.netingcn.com/mysqldump-procedure.html
mysqldump是mysql自帶的一個備份數據庫的工具,使用mysqldump可以很方便的把已有的數據庫導出來,使用
mysqldump --help 如果MYSQL_HOME/bin沒有加入PATH,需要指定去路徑
可以看到有很多可選參數。
需要注意:默認情況下,mysqldump並不會導出數據庫的存儲過程和函數,如果數據庫上創建了存儲過程且備份是需要備份存儲過程,那就需要用參數 -R 來指定,例如:
mysqldump -u root -p passwd -R testDB > db.sql
http://www.2cto.com/database/201211/168571.html
需要注意:默認情況下,mysqldump並不會導出數據庫的存儲過程和函數,如果數據庫上創建了存儲過程且備份是需要備份存儲過程,那就需要用參數 -R 來指定,
例如:
| 代碼如下 | 復制代碼 |
| root@localhost bin]# mysqldump -uroot -p -hlocalhost -P3306 -n -d -t -R DBName > procedure_name.sql |
|
http://www.linuxidc.com/Linux/2012-07/66140.htm
今天使用mysqldump導出數據庫,導入到新庫的時候,發現沒有存儲過程。
默認居然不是完整的啊。
加上“-R”,就好了。
-R, --routines Dump stored routines (functions and procedures).
現在用:
mysqldump -uroot -ppassword -R dbname> dbname.sql
導入更方便:
mysql -uroot -ppassword dbname< dbname.sql
記得導入之前先建庫。
CREATE DATABASE dbname DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
==================================================
http://blog.csdn.net/mchdba/article/details/12159239
-- 大表數據遷移,每天凌晨1點到5點執行,執行間隔時間10分鍾,遷移舊數據到歷史表。
DELIMITER $$
USE `dbx`$$
DROP PROCEDURE IF EXISTS `pro_xx`$$
CREATE PROCEDURE `pro_xx`()
BEGIN
DECLARE p_oalid INT DEFAULT 0;
DECLARE STOP INT DEFAULT 0;
DECLARE cur_oalid CURSOR FOR
SELECToal.id FROM oal_xxx oal WHERE oal.`ymd` <CONCAT(YEAR(DATE_ADD(NOW(),INTERVAL -1 MONTH)),'-',MONTH(DATE_ADD(NOW(),INTERVAL -1 MONTH )),'-',DAY(DATE_ADD(NOW(),INTERVAL-1 MONTH ))) LIMIT 1000;
DECLARE EXIT HANDLER FOR SQLSTATE '02000' /**包含游標not found*/
BEGIN
SET STOP=1;
INSERTINTO db_logs(log_type,table_name,action_name,log_msg,create_time)
SELECT1, 'oal_xxx','pro_oal_log_move',CONCAT('primary key:',p_oalid,' 游標執行正常結束!'),NOW();
END;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SETSTOP=1;
INSERTINTO db_logs(log_type,table_name,action_name,log_msg,create_time)
SELECT2, 'oal_xxx','pro_oal_log_move',CONCAT('primary key:',p_oalid,' 移動執行失敗'),NOW();
END;
OPEN cur_oalid;
-- 讀取一行數據到變量
FETCH cur_oalid INTO p_oalid;
-- 這個就是判斷是否游標已經到達了最后
WHILE STOP <> 1 DO
-- select p_id;
START TRANSACTION;
-- 進行數據遷移
REPLACE INTO oal_xxx_history SELECT oal.*FROM oal_xxx oal WHERE oal.id=p_oalid ;
DELETE FROM oal_xxx WHERE id=p_oalid;
-- INSERT INTO t (tid) VALUES (p_tid);
COMMIT;
-- 讀取下一行的數據
FETCH cur_oalid INTO p_oalid;
END WHILE;
CLOSE cur_oalid; -- 關閉游標
END$$
DELIMITER ;
http://www.jb51.net/article/27068.htm
mysql 數據遷移用的一個存儲過程,需要的朋友可以收藏下。
代碼如下:
DELIMITER $$
USE `servant_591up`$$
DROP PROCEDURE IF EXISTS `sp_move_data`$$
CREATE PROCEDURE `sp_move_data`()
BEGIN
DECLARE v_exit INT DEFAULT 0;
DECLARE v_spid BIGINT;
DECLARE v_id BIGINT;
DECLARE i INT DEFAULT 0;
DECLARE c_table INT;
DECLARE v_UniqueKey VARCHAR(57);
DECLARE v_TagCatalogId INT;
DECLARE v_RootCatalogId INT;
DECLARE v_UserId BIGINT;
DECLARE v_QuestionId CHAR(36);
DECLARE v_CorrectCount INT;
DECLARE v_ErrorCount INT;
DECLARE v_LastIsCorrect INT;
DECLARE v_LastAnswerXML TEXT CHARSET utf8;
DECLARE v_TotalCostTime INT;
DECLARE v_Reviews VARCHAR(200) CHARSET utf8;
DECLARE v_AnswerResultCategory INT;
DECLARE v_LastCostTime INT;
DECLARE v_LastAnswerTime DATETIME;
DECLARE v_IsPublic INT;
DECLARE v_SUBJECT INT;
DECLARE v_TotalCount INT;
DECLARE v_AnswerMode SMALLINT(6);
DECLARE v_ExerciseWeight FLOAT;
DECLARE c_ids CURSOR FOR SELECT UniqueKey,TagCatalogId,RootCatalogId,UserId,QuestionId,CorrectCount,ErrorCount,LastIsCorrect,LastAnswerXML,TotalCostTime,Reviews,AnswerResultCategory,LastCostTime,LastAnswerTime,IsPublic,SUBJECT,TotalCount,AnswerMode,ExerciseWeight FROM ol_answerresult_56;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_exit=1;
OPEN c_ids;
REPEAT
FETCH c_ids INTO v_UniqueKey,v_TagCatalogId,v_RootCatalogId,v_UserId,v_QuestionId,v_CorrectCount,v_ErrorCount,v_LastIsCorrect,v_LastAnswerXML,v_TotalCostTime,v_Reviews,v_AnswerResultCategory,v_LastCostTime,v_LastAnswerTime,v_IsPublic,v_SUBJECT,v_TotalCount,v_AnswerMode,v_ExerciseWeight;
IF v_exit = 0 THEN
SET @vv_id = v_id;
SELECT MOD(v_UserId,100) INTO c_table;
SET @SQL_CONTEXT =
CONCAT('INSERT INTO new_answerresult_',
c_table,'
(UniqueKey,TagCatalogId,RootCatalogId,UserId,QuestionId,CorrectCount,ErrorCount,LastIsCorrect,LastAnswerXML,TotalCostTime,Reviews,AnswerResultCategory,LastCostTime,LastAnswerTime,IsPublic,SUBJECT,TotalCount,AnswerMode,ExerciseWeight)values(',
'''',v_UniqueKey,'''',',',
v_TagCatalogId,',',
v_RootCatalogId,',',
v_UserId,',',
'''',v_QuestionId,'''',',',
v_CorrectCount,',',
v_ErrorCount,',',
v_LastIsCorrect,',',
'''',v_LastAnswerXML,'''',',',
v_TotalCostTime,',',
'''',REPLACE(IFNULL(v_Reviews,''),'''',''),'''',',',
v_AnswerResultCategory,',',
v_LastCostTime,',',
'''',v_LastAnswerTime,'''',',',
v_IsPublic,',',
v_SUBJECT,',',
v_TotalCount,',',
v_AnswerMode,',',
v_ExerciseWeight,')');
PREPARE STMT FROM @SQL_CONTEXT;
EXECUTE STMT ;
DEALLOCATE PREPARE STMT;
END IF;
SET i=i+1;
#100
#IF MOD(i,100)=0 THEN COMMIT;
#END IF;
UNTIL v_exit=1
END REPEAT;
CLOSE c_ids;
#COMMIT;
END$$
DELIMITER ;
存儲過程如同一門程序設計語言,同樣包含了數據類型、流程控制、輸入和輸出和它自己的函數庫。
--------------------基本語法--------------------
一.創建存儲過程
create procedure sp_name()
begin
.........
end
二.調用存儲過程
1.基本語法:call sp_name()
注意:存儲過程名稱后面必須加括號,哪怕該存儲過程沒有參數傳遞
三.刪除存儲過程
1.基本語法:
drop procedure sp_name//
2.注意事項
(1)不能在一個存儲過程中刪除另一個存儲過程,只能調用另一個存儲過程
四.其他常用命令
1.show procedure status
顯示數據庫中所有存儲的存儲過程基本信息,包括所屬數據庫,存儲過程名稱,創建時間等
2.show create procedure sp_name
顯示某一個mysql存儲過程的詳細信息
--------------------數據類型及運算符--------------------
一、基本數據類型:
略
二、變量:
自定義變量:DECLARE a INT ; SET a=100; 可用以下語句代替:DECLARE a INT DEFAULT 100;
變量分為用戶變量和系統變量,系統變量又分為會話和全局級變量
用戶變量:用戶變量名一般以@開頭,濫用用戶變量會導致程序難以理解及管理
1、 在mysql客戶端使用用戶變量
mysql> SELECT 'Hello World' into @x;
mysql> SELECT @x;
mysql> SET @y='Goodbye Cruel World';
mysql> select @y;
mysql> SET @z=1+2+3;
mysql> select @z;
2、 在存儲過程中使用用戶變量
mysql> CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World');
mysql> SET @greeting='Hello';
mysql> CALL GreetWorld( );
3、 在存儲過程間傳遞全局范圍的用戶變量
mysql> CREATE PROCEDURE p1( ) SET @last_procedure='p1';
mysql> CREATE PROCEDURE p2( ) SELECT CONCAT('Last procedure was ',@last_procedure);
mysql> CALL p1( );
mysql> CALL p2( );
三、運算符:
1.算術運算符
+ 加 SET var1=2+2; 4
- 減 SET var2=3-2; 1
* 乘 SET var3=3*2; 6
/ 除 SET var4=10/3; 3.3333
DIV 整除 SET var5=10 DIV 3; 3
% 取模 SET var6=10%3 ; 1
2.比較運算符
> 大於 1>2 False
< 小於 2<1 False
<= 小於等於 2<=2 True
>= 大於等於 3>=2 True
BETWEEN 在兩值之間 5 BETWEEN 1 AND 10 True
NOT BETWEEN 不在兩值之間 5 NOT BETWEEN 1 AND 10 False
IN 在集合中 5 IN (1,2,3,4) False
NOT IN 不在集合中 5 NOT IN (1,2,3,4) True
= 等於 2=3 False
<>, != 不等於 2<>3 False
<=> 嚴格比較兩個NULL值是否相等 NULL<=>NULL True
LIKE 簡單模式匹配 "Guy Harrison" LIKE "Guy%" True
REGEXP 正則式匹配 "Guy Harrison" REGEXP "[Gg]reg" False
IS NULL 為空 0 IS NULL False
IS NOT NULL 不為空 0 IS NOT NULL True
3.邏輯運算符
4.位運算符
| 或
& 與
<< 左移位
>> 右移位
~ 非(單目運算,按位取反)
注釋:
mysql存儲過程可使用兩種風格的注釋
雙橫杠:--
該風格一般用於單行注釋
c風格:/* 注釋內容 */ 一般用於多行注釋
--------------------流程控制--------------------
一、順序結構
二、分支結構
if
case
三、循環結構
for循環
while循環
loop循環
repeat until循環
注:
區塊定義,常用
begin
......
end;
也可以給區塊起別名,如:
lable:begin
...........
end lable;
可以用leave lable;跳出區塊,執行區塊以后的代碼
begin和end如同C語言中的{ 和 }。
--------------------輸入和輸出--------------------
mysql存儲過程的參數用在存儲過程的定義,共有三種參數類型,IN,OUT,INOUT
Create procedure|function([[IN |OUT |INOUT ] 參數名 數據類形...])
IN 輸入參數
表示該參數的值必須在調用存儲過程時指定,在存儲過程中修改該參數的值不能被返回,為默認值
OUT 輸出參數
該值可在存儲過程內部被改變,並可返回
INOUT 輸入輸出參數
調用時指定,並且可被改變和返回
IN參數例子:
CREATE PROCEDURE sp_demo_in_parameter(IN p_in INT)
BEGIN
SELECT p_in; --查詢輸入參數
SET p_in=2; --修改
select p_in;--查看修改后的值
END;
執行結果:
mysql> set @p_in=1
mysql> call sp_demo_in_parameter(@p_in)
略
mysql> select @p_in;
略
以上可以看出,p_in雖然在存儲過程中被修改,但並不影響@p_id的值
OUT參數例子
創建:
mysql> CREATE PROCEDURE sp_demo_out_parameter(OUT p_out INT)
BEGIN
SELECT p_out;/*查看輸出參數*/
SET p_out=2;/*修改參數值*/
SELECT p_out;/*看看有否變化*/
END;
執行結果:
mysql> SET @p_out=1
mysql> CALL sp_demo_out_parameter(@p_out)
略
mysql> SELECT @p_out;
略
INOUT參數例子:
mysql> CREATE PROCEDURE sp_demo_inout_parameter(INOUT p_inout INT)
BEGIN
SELECT p_inout;
SET p_inout=2;
SELECT p_inout;
END;
執行結果:
set @p_inout=1
call sp_demo_inout_parameter(@p_inout) //
略
select @p_inout;
略
附:函數庫
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
mysql> select substring(’abcd’,0,2);
+———————–+
| substring(’abcd’,0,2) |
+———————–+
| |
+———————–+
1 row in set (0.00 sec)
mysql> select substring(’abcd’,1,2);
+———————–+
| substring(’abcd’,1,2) |
+———————–+
| ab |
+———————–+
1 row in set (0.02 sec)
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)默認變為整形值
mysql> select round(1.23);
+————-+
| round(1.23) |
+————-+
| 1 |
+————-+
1 row in set (0.00 sec)
mysql> select round(1.56);
+————-+
| round(1.56) |
+————-+
| 2 |
+————-+
1 row in set (0.00 sec)
(2)可以設定小數位數,返回浮點型數據
mysql> select round(1.567,2);
+—————-+
| round(1.567,2) |
+—————-+
| 1.57 |
+—————-+
1 row in set (0.00 sec)
SIGN (number2 ) //返回符號,正負或0
SQRT(number2) //開平方
三、日期類型
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) //分
注:可用在INTERVAL中的類型:DAY ,DAY_HOUR ,DAY_MINUTE ,DAY_SECOND ,HOUR ,HOUR_MINUTE ,HOUR_SECOND ,MINUTE ,MINUTE_SECOND,MONTH ,SECOND ,YEAR
DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
其中,datatype為mysql的數據類型,如:INT, FLOAT, DATE, VARCHAR(length)
例:
DECLARE l_int INT unsigned default 4000000;
DECLARE l_numeric NUMERIC(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';



