删除username的索引
-- 删除index_name 索引
drop index index_name on user;
show index from user \G;
-- 创建新索引列组成,index_pinyin为复合索引名称
create index index_pinyin on user(username,pinyin);
-- 这里省略主键索引
show index from user \G;
像这样由两个以上组成的索引称为复合索引,由于是复合索引因此索引的名称相同,注意Seq_in_index代表索引字段的顺序,
前面我们说过在查询条件中使用了复合索引的第一个字段(这里指username),索引才会被使用。因此,在复合索引中索引列
的顺序至关重要。
唯一索引
创建唯一索引必须制定关键字UNIQUE,唯一索引和单列索引类似,只要的区别在于,唯一索引限制列的值必须唯一,但允许有空值。
对于多个字段,唯一索引规定列值的组合必须唯一。如创建username为唯一索引,那么username的值是不可以重复的
-- 创建唯一索引
create unique index index_name on tbl_name(index_col_name[,.....]);
-- 添加 (通过修改表结构)
alter table tbl_name add unique index index_name on (index_col_name[,.....]);
-- 创建表时直接指定
create table `table` (
`id` int(11) not null auto_increment,
name varchar(32) not null,
...... -- 其他字段
primary key (‘id’),
unique indexName (name(32))
);
下面为user表的username字段创建唯一索引:
-- 仅为演示
create unique index idx_name on user(username);
事实上这里讲username 设置为唯一索引是不合理的,毕竟用户可能存在相同username,因此在实际生产环节中username是不应该
设置为唯一索引的。否则当有相同的名称插入时,数据库表将会报错。
主键索引
主键索引也称丛生索引,是一种特殊的唯一索引,不允许有空值。创建主键索引语法如下:
alter table tbl_name add primary key (index_col_name);
一般情况下在创建表时,指明了主键时,主键索引就已自动创建了,因此无需我们手动创建。
-- 创建表时直接指定
create table `table`(
`id` int(11) not null auto_increment,
..... -- 其他字段
primary key(`id`), -- 主键索引
);
索引的设计
where子句中的列可能最适合作为索引
不要尝试为性别或者有无这类字段等建立索引(因为类似性别的列,一般只含有 '0' 和 '1'),无论搜索结果如何都会大约得出一半
的数据)
如果创建符合索引,要遵循最左前缀法则。即查询从索引的最左前列开始,并且不跳过索引中的列
不要过度使用索引。每一次的更新,删除,插入都会维护该表的索引,更多的索引意味着占用更多的空间
使用InnoDB存储引擎时,记录(行)默认会按照一定的顺序存储,如果已定义主键,则按照主键顺序存储,
由于普通索引都会保存主键的键值,因此主键应尽可能的选择较短的数据类型,以便节省存储空间
不要尝试在索引列上使用函数。
存储过程
为什么需要存储过程
迄今为止,我们所使用的大多数SQL语句都针对一个或多个表的单条语句,当需要通过处理流程来达到预期目标时,
单条sql语句就很难做到了,这是因为sql语句无法编写处理流程的语句,所有的sql都只能通过一个个命令执行,比如想
循环执行某个sql语句,对于没有处理流程的sql显然是无法实现的,此时就需要通过存储过程来达到目的了,简单的理解存储过程就是数据库中
保存的一系列sql命令的集合,也就是说通过存储过程就可以编写流程语句,如循环操作语句等,下面看看如何使用存储过程。
存储过程的创建和使用
可以通过以下语法创建存储过程:
create procedure 存储过程名称(参数种类 参数 数据类型)
begin
处理内容
end
存储过程的名称可以自由定义,但不可与存在的函数或存储过程名称重复,命令时建议以【sp_】开头,需要处理的内容
则编辑在begin 和 end 之间。参数的种类分3种,分别是 in out inout 其中in为输入参数类型,out为输出参数类型,而
input既是输入类型又是输出类型,下面我们创建一个存储过程,已达到对user表的用户名称进行模糊查询的目的,存储过程
名称为 sp_search_user:
-- 改变分隔符
delimiter //
create procedure sp_search_user (in name varchar(20));
begin
if name is null or name =" " then
select * from user;
else
select * from user where username like name;
end if;
end
// -- 执行sql
delimiter; -- 恢复分隔符
其中delimiter 可以用于改变分隔符,由于存储过程中流程语句需要使用分号结尾与 mysql 命令行的sql语句结尾的分号冲突m
于是改变分隔符为//, 执行完存储过程后在恢复我i分号即可。从存储过程创建语句中,我们设置一个name的输出参数语句并在
begin与end之间编写了流程语句,当名称为空时查询所有用户否则按传入的条件查询。现在可以使用该存储过程了,调用
语法如下:
call 存储过程名称(参数,.....)
call sp_search_user(null);
-- 查询以为name以任开头的用户
call sp_search_user("任%");
输入输出参数类型
前面提到了三种输入输出的参数类型,IN输入参数类型,out输出参数类型,而input既是输入类型又是输出类型,所谓的IN
输入参数类型就是把要传递的参数输入到存储过程的内部以便编写存储过程流程语句时可以使用。上述演示过的例子就是
这种类型。关键字out则是指明相应参数用来从存储过程传出的一个值,也可以理解为存储过程的返回值,而对于input则是
两者的结合体。现在我们创建一个存储过程,用于返回商品的最大值、最小值和品均值,命名为sp_item_price
delimter //
-- 创建存储过程
create procedure sp_item_price(out plow decimal(8,2),out phigh decimal(8,2),out pavg decimal(8,2))
begin
select min(price) into plow form items;
select max(price) into phight form items;
select avg(price) into pavg from items;
end;
//
-- 恢复分隔符
delimiter ;
-- 调用存储过程
call sp_item_price(@privelog,@pricehight,@priceavg);
select @pricelow;
正如我们所看到的,创建sp_item_price时,使用了3个out参数,在存储过程内部将会把执行结果分别存入这个三个变量中,
存入关键字使用的是into,完成存储过程创建后,使用call sp_item_price (@pricelog,@pricehigh,@priceavg);调用sp_item_price,
传入用于存储返回值的3个变量,注意mysql的用户量必须以@开头,名称可自定义,但不能重复,调用完成后语句并没有这些变量。
这里有点要明白的, 上述存储过程中使用对输出变量的赋值语句:
select 列名1,... into 变量名1, .... from 表名 where 语句等...
请注意如果检索出多个列名,与之对英国的赋值变量也必须有多个
delimiter //
-- 创建存储过程
create procedure sp_order_sun_price(in numberf int , out ptotal decimal(8,2))
begin
select sum(price * items_sum) from items inner join orderdetail as od on items.id = od.items where od.orders_id = numbers
into ptotal; -- 放到语句后面也可行
end;
//
-- 恢复分隔符
delimiter;
-- 执行存储过程
call sp_order_sum_price(3,@priceTotal);
-- 查询结果
select @priceTotal;
删除存储过程
如果创建存储过程有误,可以删除后重新创建,当然也可以修改,不过感觉不如删除重建来的更简单,删除存储过程可以使用
一下语句
drop procedure [if exists] 存储过程名称;
查看存储过程的状态
show procedure status [like 'pattern']
如查看的sp_order_sun_price 状态
-- 查看的sp_order_sum_price 状态
show procedure status like 'sp_order_sum_price' \G;
查看存储过程的创建语句
查看已创建的存储过程,可以使用以下语法
show create procedure 存储过程名;
例
show create prrcedure sp_order_sum_price \G;
存储过程的流程控制语句
以下是存储过程中可以使用的流程控制语句
......
定义变量
使用declare 定义局部变量
在流程语句的分析中,我们在存储过程中使用变量的声明与设置,由于这些变量也只能在存储过程中使用,因此也称为局部变量,变量
的声明可以使用以下语法:
declare 变量名[,变量名2...] 数据类型(type) [default value];
-- 定义变量num,数据类型为int型,默认值为10
declare num int default 10;
其中,declare 关键字是用来声明变量的;变量名即变量的名称,这里可以同时定义多个变量;type参数用来指定变量的类型;
default value 子句将变量默认值设置为value,没有使用default 子句时,默认值为null,声明后,我们就可以在存储过程使用该
变量,设置变量值可以使用过以下语法;
set 变量名1 = expr [,变量名2 = expr] ...
其中,set关键字使用来我i变量赋值的;expr 参数是赋值表达式或某个值,一个set 语句可以同时为多个变量赋值,各个变量的
赋值语句之间用逗号隔开。除了这种赋值方式,前面我们还提到过使用select into 语句为变量赋值,那也是可行的,。
了解其他类型的变量
用户变量:"@" 开始, 形式为"@变量名" ,用户变量跟mysql客户端是绑定的,设置的变量,只对当前用户使用的客户端生效,
声明或者定义用户变量使用set语句,如 set @var 若没有指定global 或session ,那么默认将会定义用户变量。
全局变量:定义时,以如下两种形式出现,set global 变量名,或者 set @@ global .name 对所有客户端生效,只有具有
super 权限才可以设置全局变量,如下:
set blobal sort_buffer_size=value;
set @@global.sort_buffer_size=value;
会话变量:只对链接的客户端有效。
set session sort_buffer_size=value;