Ⅰ mysql中,访问量可以用触发器或存储过程么select某些数据一次相当于访问量加1
select是不能用触发器的。只有UPDATE或DELETE操作才能定义触发器。
如果真的在select上定义了触发器有什么后果?不单单是你访问页面时会查询数据,在你修改数据的时候同样也要查询数据。这时怎么区分到底是访问了还是没有访问呢?
存储过程是预先定义好的mysql“函数”。函数不调用就无法生效,因此不能实现你的需求。
关系数据库的触发器和存储过程是一个非常可选的功能,在大部分情况下,是不需要用到的。触发器的目的是在你修改数据库内容时,自动帮助你完成一些工作,保证数据的完整性。存储过程实质上是把你的一部分操作数据库的代码逻辑存储起来以备调用。其实这些特性都可以用普通的SQL和事务来实现,而且更灵活,更利于设计。因此在使用触发器或存储过程之前要慎重。
Ⅱ mysql存储过程为什么不推荐使用
维护不方便,对数据库压力不较大,不易于数据库集群的扩展和迁移。
能够在业务系统层面做的逻辑尽量不要用存储过程来做。
以后做数据库的迁移的时候,换了数据库,存储过程可能要重写或重构。但是如果放在业务代码层去实现对应的逻辑,数据库换了之后,更改对应的连接驱动,业务代码不用做任何吸怪。
Ⅲ mysql 存储过程怎么进行性能优化
在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用存储过程来封装数据库操作。如果项目的存储过程较多,书写又没有一定的规范,将会影响以后的系统维护困难和大存储过程逻辑的难以理解,另外如果数据库的数据量大或者项目对存储过程的性能要求很,就会遇到优化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的存储过程要比一个性能差的存储过程的效率甚至高几百倍。下面介绍某一个MySQL存储过程优化的整个过程。
在本文中,需要被优化的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
insert into tb_testnum select boxnumber,usertype from tb_testnum_tmp where boxnumber= p_boxnumber;
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnumok';
在存储过程中使用到的表tb_testnum结构如下:
drop table if exists tb_testnum;
create table tb_testnum
(
boxnumber varchar(30) not null,
usertype int not null
);
create unique index idx1_tb_testnum ontb_testnum(boxnumber);
在存储过程中使用到的另外一张表tb_testnum_tmp结构如下:
drop table if exists tb_testnum_tmp;
create table tb_testnum_tmp
(
boxnumber varchar(30) not null,
usertype int not null
);
create unique index idx1_tb_testnum_tmp ontb_testnum_tmp(boxnumber);
从两个表的结构可以看出,tb_testnum和tb_testnum_tmp所包含的字段完全相同,存储过程pr_dealtestnum的作用是根据输入参数将tb_testnum_tmp表的数据插入到tb_testnum表中。
很明显,虽然能够实现预期的功能,但存储过程pr_dealtestnum的代码还有改进的地方。
下面,我们一步一步来对其进行优化。
优化一
存储过程pr_dealtestnum的主体是一条insert语句,但这条insert语句里面又包含了select语句,这样的编写是不规范的。因此,我们要把这条insert语句拆分成两条语句,即先把数据从tb_testnum_tmp表中查找出来,再插入到tb_testnum表中。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
declare p_usertype int;
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
insert into tb_testnum values(p_boxnumber,p_usertype);
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化二
在向tb_testnum表插入数据之前,要判断该条数据在表中是否已经存在了,如果存在,则不再插入数据。同理,在从tb_testnum_tmp表中查询数据之前,要先判断该条数据在表中是否存在,如果存在,才能从表中查找数据。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype fromtb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum values(p_boxnumber,p_usertype);
leave pr_dealtestnum_label;
end;
else
begin
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化三
不管向tb_testnum表插入数据的操作执行成功与否,都应该有一个标识值来表示执行的结果,这样也方便开发人员对程序流程的追踪和调试。也就是说,在每条leave语句之前,都应该有一个返回值,我们为此定义一个输出参数。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum values(p_boxnumber,p_usertype);
set p_result = 0;
leave pr_dealtestnum_label;
end;
else
begin
set p_result = 2;
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化四
我们注意到“insert into tb_testnum values(p_boxnumber,p_usertype);”语句中,tb_testnum表之后没有列出具体的字段名,这个也是不规范的。如果在以后的软件版本中,tb_testnum表中新增了字段,那么这条insert语句极有可能会报错。因此,规范的写法是无论tb_testnum表中有多少字段,在执行insert操作时,都要列出具体的字段名。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype);
set p_result = 0;
leave pr_dealtestnum_label;
end;
else
begin
set p_result = 2;
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化五
在执行insert语句之后,要用MySQL中自带的@error_count参数来判断插入数据是否成功,方便开发人员跟踪执行结果。如果该参数的值不为0,表示插入失败,那么我们就用一个返回参数值来表示操作失败。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount> 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0then
begin
insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype);
if @error_count<>0 then
begin
set p_result= 3;
end;
else
begin
set p_result= 0;
end;
end if;
end;
else
begin
set p_result = 2;
end;
end if;
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
Ⅳ 在MYSQL中使用存储过程要设置什么地方吗解决办法
几个去 IBM 面试的兄弟回来抱怨:去了好几个不同的 IBM
项目组,几乎每个面试官问到数据库的时候都要问用没用过存储过程,烦人不?大家去面的程序员,又不是
笔者认为,存储过程说白了就是一堆 SQL 的合并。中间加了点逻辑控制。
但是存储过程处理比较复杂的业务时比较实用。
比如说,一个复杂的数据操作。如果你在前台处理的话。可能会涉及到多次数据库连接。但如果你用存储过程的话。就只有一次。从响应时间上来说有优势。
也就是说存储过程可以给我们带来运行效率提高的好处。
另外,程序容易出现 BUG
数据量小的,或者和钱没关系的项目不用存储过程也可以正常运作。mysql 的存储过程还有待实际测试。如果是正式项目,建议你用 sql
server 或 oracle
的存储过程。数据与数据之间打交道的话,过程会比程序来的快的多。面试官问有没有用存储,实际上就是想知道前来面试的程序员到底做过数据量大的项目没。如
果是培训出来的,或者小项目小公司出来的,对存储肯定接触的少了。
所以,要想进大公司,没有丰富存储过程经验,是不行的。
错。存储过程不仅仅适用于大型项目,对于中小型项目,使用存储过程也是非常有必要的。其威力和优势主要体现在:
1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL
语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
2.当对数据库进行复杂操作时(如对多个表进行
Update,Insert,Query,Delete
时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。这些操作,如果用程序来完成,就变成了一条条的 SQL
语句,可能要多次连接数据库。而换成存储,只需要连接一次数据库就可以了。
3.存储过程可以重复使用,可减少数据库开发人员的工作量。
4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权。存储过程的缺点
1:调试麻烦,但是用 PL/SQL Developer 调试很方便!弥补这个缺点。
2:移植问题,数据库端代码当然是与数据库相关的。但是如果是做工程型项目,基本不存在移植问题。
3:重新编译问题,因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译(不过也可以设置成运行时刻自动编译)。
4:如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的。维护起来更加麻烦
Ⅳ mysql 的存储过程可以封装数据库操作吗
存储过程不存在操作或是不操作触发器的问题,要先理解触发器的含义。
触发器分两类,一类是基于表数据的触发,一类是基于数据库对象的触发。
实际应用中第一类比较常用,它是在对表数据进行 插入 修改 删除 的操作时触发,执行触发器中的脚本,换言之,就是如果你的存储过程有涉及到对该表的 插入 修改 删除 数据操作,而且该表也存在这些操作对应的触发器,那么肯定会触发也就是执行这个触发器,反之,不会执行。
Ⅵ mysql存储过程的基本用法有哪些
mysql存储过程的基本用法有哪些
在外部程序访问数据库时(例如 PHP),要组织很多 SQL 语句。
特别是业务逻辑复杂的时候,一大堆的 SQL 和条件夹杂在 PHP 代码中,让人不寒而栗。现在有了 MySQL 存储过程,业务逻辑可以封装存储过程中,这样不仅容易维护,而且执行效率也高。
一、MySQL 创建存储过程
"pr_add" 是个简单的 MySQL 存储过程,这个MySQL 存储过程有两个 int 类型的输入参数 "a"、"b",返回这两个参数的和。
复制代码 代码如下:
drop procere if exists pr_add;
计算两个数之和
复制代码 代码如下:
create procere 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 procere 存储过程名字()
(
[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 procere pr_add
(
@a int, -- 错误
b int -- 正确
)
3. MySQL 存储过程的参数不能指定默认值。
4. MySQL 存储过程不需要在 procere body 前面加 "as"。而 SQL Server 存储过程必须加 "as" 关键字。
复制代码 代码如下:
create procere pr_add
(
a int,
b int
)
as -- 错误,MySQL 不需要 "as"
begin
mysql statement ...;
end;
5. 如果 MySQL 存储过程中包含多条 MySQL 语句,则需要 begin end 关键字。
复制代码 代码如下:
create procere 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;
Ⅶ mysql 存储过程 执行报错 我创建了一个简单的存储过程,成功了,但是在call执行调用的时候怎么老是报错呢
create procere proprice() is
begin
select avg(price) as average from procts;
end;
以上就是规范的格式,请不要添加额外的东西,执行之后调用即可。
如果有其他问题,你可以先网络一下存储过程的规范应用
Ⅷ mysql存储过程 和 触发器的优缺点 问题
缺点是触发器的缺点,
而有点是存储过程的优点,
所以推荐使用存储过程。