1ストアドプロシージャの概要
ストアドプロシージャは、データベースサーバーに格納されている一連のSQLステートメントであり、一連のコマンドをカプセル化する関数のように、クエリで指定された名前を呼び出すことによって実行されます。これらのコマンドは、関数名が呼び出されたときに実行されます。
ストアドプロシージャの2つの利点
(1)SQL言語の機能と柔軟性の強化:ストアドプロシージャは、強力な柔軟性を持ち、複雑な判断やより複雑な計算を完了することができる制御ステートメントを使用して記述できます。
(2)標準コンポーネントプログラミング:ストアドプロシージャの作成後、ストアドプロシージャのSQLステートメントを書き直すことなく、プログラム内で複数回呼び出すことができます。また、データベースの専門家は、アプリケーションのソースコードに影響を与えることなく、いつでもストアドプロシージャを変更できます。
(3)実行速度の高速化:操作に大量のTransaction-SQLコードが含まれている場合、または複数回実行される場合、ストアドプロシージャの実行速度はバッチ処理の実行速度よりもはるかに高速です。ストアドプロシージャがプリコンパイルされているためです。ストアドプロシージャを初めてクエリするとき、オプティマイザはそれを分析して最適化し、最終的にシステムテーブルに格納される実行プランを提供します。ただし、バッチTransaction-SQLステートメントは、実行するたびにコンパイルおよび最適化する必要があり、速度は比較的遅くなります。
(4)ネットワークトラフィックの削減:同じデータベースオブジェクトに対する操作(クエリや変更など)の場合、この操作に関連するTransaction-SQLステートメントがストアドプロシージャに編成されていると、クライアントでストアドプロシージャが呼び出されます。コンピュータ、callステートメントのみがネットワーク上で送信されます。これにより、ネットワークトラフィックが大幅に削減され、ネットワークの負荷が軽減されます。
(5)セキュリティメカニズムとして最大限に活用する:ストアドプロシージャを実行する権限を制限することにより、対応するデータアクセス権限を制限し、不正なユーザーによるデータへのアクセスを回避し、データのセキュリティを確保できます。
3ストアドプロシージャの構文を作成します
语法
CREATE PROCEDURE 过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型…]]) [特性 ...] 过程体
DELIMITER //
CREATE PROCEDURE myproc(OUT s int)
BEGIN
SELECT COUNT(*) INTO s FROM students;
END
//
DELIMITER ;
分隔符
MySQL默认以";"为分隔符,如果没有声明分割符,则编译器会把存储过程当成SQL语句进行处理,因此编译过程会报错,所以要事先用“DELIMITER //”声明当前段分隔符,让编译器把两个"//"之间的内容当做存储过程的代码,不会执行这些代码;“DELIMITER ;”的意为把分隔符还原。
参数
存储过程根据需要可能会有输入、输出、输入输出参数,如果有多个参数用","分割开。MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT:
IN参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
OUT:该值可在存储过程内部被改变,并可返回
INOUT:调用时指定,并且可被改变和返回
过程体
过程体的开始与结束使用BEGIN与END进行标识。
4基本操作
-- 存储过程
/**
创建存储过程,并不代表执行存储过程
*/
delimiter //
create
procedure test()
begin
insert into a values (null,'11');
insert into a values (null,'33');
insert into a values (null,'99');
insert into a values (null,'11');
end//
delimiter ;
-- 执行调用存储过程
call test();
-- 有输入参数的存储过程
/*
test2(参数。。) in或者out,inout 参数名字 参数的类型
添加多个参数用,隔开 参数类型可以一样,但是名字要不一样。
*/
delimiter //
create
procedure test2(in number2 varchar(22),number1 varchar(22))
begin
insert into a values (null,number1);
end//
delimiter ;
call test2('张三','李四');
-- 有输出参数的存储过程
delimiter //
create
procedure test3(out number int)
begin
select count(*)into number from a;
end//
delimiter ;
-- 调用该存储过程 输出参数number的值,保存在aa中
call test3(@aa);
-- 查看aa的值
select @aa;
-- 有输出和输入参数的存储过程
delimiter //
create
procedure test4(message varchar(22),out number int)
begin
select count(*)into number from a;
insert into a values(null,message);
end//
delimiter ;
-- 调用存储过程
call test4('admin',@number);
select @number;
/*****************控制流************/
-- 变量
/*
变量 : 会变的程度
变:变化
量:程度
1 定义
2 赋值
*/
-- if
/**
number 1 在a 表中a_name 就为张三
number 2 在a 表中a_name 就为李四
number 3 在a 表中a_name 就为王武
nubmer为其他数字,就添加aa
*/
delimiter //
create
procedure test5(number int )
begin
if number=1 then
insert into a values (null,'张三');
elseif number=2 then
insert into a values (null,'李四');
elseif number=3 then
insert into a values (null,'王武');
else
insert into a values (null,'aa');
end if;
end//
delimiter ;
-- 调用存储过程
call test5(44);
-- 变量 1 declare message varchar(22);
delimiter //
create
procedure test6(number int )
begin
/*声明变量 保存值
*/
declare message varchar(22);
if number=1 then
/**赋值*/
set message ='张三';
elseif number=2 then
set message ='李四';
elseif number=3 then
set message ='王武';
else
set message ='aa';
end if;
insert into a values (null,message);
end//
delimiter ;
call test6(3);
-- 变量 2set @message ='张三';
delimiter //
create
procedure test7(number int )
begin
if number=1 then
/**赋值*/
set @message ='张三';
elseif number=2 then
set @message ='李四';
elseif number=3 then
set @message ='王武';
else
set @message ='aa';
end if;
insert into a values (44,@message);
end//
delimiter ;
-- 调用
call test7(1);
-- case语句
delimiter //
create
procedure test8(number int )
begin
case
when number =1 then
set @message ='张三';
when 2 then
set @message ='李四';
when 3 then
set @message ='王武';
else
set @message ='aa';
end case;
insert into a values (44,@message);
end//
delimiter ;
call test8(33);
-- 循环 LOOP_LABLE
delimiter //
create
procedure test9( )
begin
declare v int default 1;
LOOP_LABLE:loop
set v=v+1;
/*打印*/
select concat('v=',v);
if v >10 then
leave LOOP_LABLE;
end if;
end loop;
end//
delimiter ;
call test9();