RUNOOB
-- 将语句的结束符号从分号;临时改为两个$$(可以是自定义)mysql> delimiter $$-- 如果想指定存储过程创建在某个特定的数据库下,那么在过程名前面加数据库名做前缀。mysql > DELIMITER //mysql > CREATE PROCEDURE proc1-> (IN parameter1 INTEGER)-> BEGIN-> DECLARE variable1 CHAR(10);-> IF parameter1 = 17 THEN-> SET variable1 = 'birds';-> ELSE-> SET variable1 = 'beasts';-> END IF;-> INSERT INTO table1 VALUES (variable1);-> END-> //-- 将语句的结束符号恢复为分号mysql > DELIMITER;mysql > call proc1(18);
-- 没有BEGIN和ENDmysql > CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World');mysql > SET @greeting='Hello';mysql > CALL GreetWorld( );
存储过程体
存储过程体包含了在过程调用时必须执行的语句,例如:dml、ddl语句,if-then-else和while-do语句、声明变量的declare语句等
label1: BEGINlabel2: BEGINlabel3: BEGINstatements;END label3 ;END label2;END label1
存储过程的参数
CREATE PROCEDURE 存储过程名([[IN |OUT |INOUT ] 参数名 数据类型…])
变量
变量定义
放在存储过程体的开始
DECLARE l_int int unsigned default 4000000;DECLARE l_numeric number(8,2) DEFAULT 9.95;DECLARE l_date date DEFAULT '1999-12-31';
变量赋值
-- 存储过程体中set p_in=2;-- 用户变量名一般以@开头set @greeting='Hello'-- 读取SELECT @greeting;
MySQL存储过程的查询、修改、删除
MySQL存储过程的控制语句
见参考链接。
Mosh

多个参数、IFNULL、参数验证抛出错误
USE sql_invoice;DROP PROCEDURE IF EXISTS get_payments;DELIMITER $$CREATE PROCEDURE get_payments(client_id INT(4),payment_method_id TINYINT(2))BEGINIF client_id <= 0 OR payment_method_id <= 0 THENSIGNAL SQLSTATE '22023'SET MESSAGE_TEXT = 'Invalid client_id or payment_method_id';END IF;SELECT * FROM payments pwhere p.client_id = IFNULL(client_id, p.client_id)and p.payment_method = IFNULL(payment_method_id, p.payment_method);END$$DELIMITER ;CALL get_payments(NULL, NULL);CALL get_payments(3, NULL);CALL get_payments(NULL, 2);CALL get_payments(3, 1);CALL get_payments(-1, -1);
验证原则:最少、应用优先、数据库兜底
因为付款总计列本就不允许空值,所以如果你给这个过程传递了空值,MYSQL会自动标注这一错误,所以尽量利用最少的验证逻辑,只保留最最关键的那些。相比访问数据库,在应用中检测和报告错误会更快速,把参数验证作为终极备选方案,以防有人在没有通过应用直接调用了你的存储过程的情况。
-输出参数,DECIMAL数据类型
尽量避免输出参数
DROP PROCEDURE IF EXISTS sql_invoice.get_unpaid_invoices_for_client;DELIMITER $$$$CREATE PROCEDURE sql_invoice.get_unpaid_invoices_for_client(client_id INT,OUT invoice_count INT,OUT invoice_total DECIMAL(9,2))BEGINSELECT COUNT(*), SUM(i.invoice_total)INTO invoice_count, invoice_totalFROM invoices iWHERE i.client_id = client_idAND i.payment_total = 0;END$$DELIMITER ;
