突然要弄MySQL存储过程
好久没有怎么接触过数据库存储过程了,都忘了,记在这里
create table email (id int auto_increment primary key, name text, content text, int size); create table email_trash (id int auto_increment primary key, name text, content text, int size); create table attachment (id int auto_increment primary key, email_id int, url text); create table attachment_trash (id int auto_increment primary key, email_id int, url text);
delimiter // drop procedure if exists fix_data_trash_magic //
CREATE PROCEDURE `fix_data_trash_magic`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE _amount INT DEFAULT 0;
DECLARE _size INT;
DECLARE _id INT;
DECLARE _newid LONG;
DECLARE email_loop CURSOR FOR select id, size from email_trash where name = 'jemmy';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN email_loop;
REPEAT
FETCH email_loop INTO _id, _size;
IF NOT done THEN
insert into email(name, content, size) select name,content,size from email_trash where id = _id;
select last_insert_id() into _newid;
insert into attachment(email_id, url) select _newid,url from attachment_trash where email_id = _id;
SET _amount = _size + _amount;
END IF;
UNTIL done END REPEAT;
CLOSE email_loop;
END
call fix_data_trash_magic()//
另外还有常用的几个命令
mysql> show procedure status; mysql> show create procedure procedure_name; // SHOW THE CREATING SQL OF THE SP
包含异常处理,保存点的存储过程
DELIMITER ;;
CREATE PROCEDURE ps_with_exception_etc(in_domain varchar(50), in_account varchar(32), in_passwd varchar(32), OUT out_no int, OUT out_msg varchar(50))
BEGIN
DECLARE s_fullid varchar(100);
DECLARE EXIT HANDLER FOR SQLSTATE '23000'
BEGIN
SET out_no = -1;
SET @prc_work_error = 'Repeated key';
ROLLBACK TO sp_01;
END;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET out_no = -1;
SET @prc_work_error = 'Unknown error';
ROLLBACK TO sp_01;
END;
-- 声明之类的都应该放在前面
SET AUTOCOMMIT = 0;
SELECT concat(in_account, '@', in_domain) INTO s_fullid;
START TRANSACTION;
SAVEPOINT sp_01;
-- DO OO HERE
-- DO XX HERE
COMMIT;
SET out_no = 1;
END
;;
DELIMITER ;
存储过程中的动态SQL
这里只是演示动态SQL的写法,要是真这么写太浪费了,直接可以写出来的SQL就不需要动态SQL
DELIMITER ;;
CREATE PROCEDURE ps_with_dynamic_sql(in_domain varchar(50), in_account varchar(32), OUT out_no int, OUT out_msg varchar(50))
BEGIN
DECLARE fullid varchar(100);
DECLARE DROP_USER_TABLEK varchar(500);
DECLARE DROP_USER_MAILS varchar(500);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET out_no = -1;
SET @prc_work_error = 'Unknown error';
ROLLBACK TO sp_01;
END;
SET AUTOCOMMIT = 0;
START TRANSACTION;
SAVEPOINT sp_01;
SET @MyQuery = concat('DELETE FROM tablek WHERE uuid = ', in_account);
PREPARE DROP_USER_TABLEK from @MyQuery;
SET @MyQuery = concat('DELETE FROM mails WHERE uuid = ', in_account);
PREPARE DROP_USER_MAILS from @MyQuery;
EXECUTE DROP_USER_TABLEK;
EXECUTE DROP_USER_MAILS;
COMMIT;
SET out_no = 1;
END
;;
DELIMITER ;
还有个简单的
CREATE PROCEDURE `insert_data`(in item integer)
BEGIN
DECLARE counter INT;
SET counter = item;
WHILE counter >= 1 DO
// DO YOUR BIZ HERE
SET counter = counter - 1;
END WHILE;
END
另外在存储过程中声明变量,游标,处理器是有一定的顺序的,否则会报语法错误
触发器
create trigger insert_after_addr after insert on addr for each row begin set @aid=new.id; insert into data(addr_id, type, value) values (@aid, 5, 'hello trigger'); end
show triggers// drop trigger insert_after_addr//
alter table data modify id int(22) not null auto_increment
CREATE trigger insert_before_tablek
before
insert on tablek
for each row
begin
set new.status = 25;
end