基础篇
MySQL 是一种关系型数据库,主要用于持久化存储我们的系统中的一些数据比如用户信息。
SQL 语言包括数据定义(DDL)、数据操纵(DML),数据控制(DCL)和数据查询(DQL) 四个部分。
数据定义:Create Table,Alter Table,Drop Table, Craete/Drop Index 等
数据操纵:Select ,insert,update,delete,
数据控制:grant,revoke
数据查询:select
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
防止SQL注入
1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。
防止sql注入的方式
1.开启配置文件中的 magic_quotes_gpc 和 magic_quotes_runtime 设置
2.执行 sql 语句时使用 addslashes 进行 sql 语句转换
3.Sql 语句书写尽量不要省略双引号和单引号。
4.过滤掉 sql 语句中的一些关键词:update、insert、delete、select、 * 。
5.提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的。
关于数据库语句
//创建数据库
create database h_test;
//查看数据库
show databases;
//查看数据库信息
show create database h_test;
//修改数据库的编码,可使用上一条语句查看是否修改成功
alter database h_test default character set gbk collate gbk_bin;
//删除数据库
drop database h_test;
//综上,可以直接创建数据库且设置编码方式
CREATE DATABASE h_test DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
关于数据表
//首先选定操作的数据库
use h_test;
//创建表student
create table student(
id int(11),
name varchar(20),
age int(11)
);
//查看数据表
show tables;
//查看数据表信息,后面加上参数/G可使结果更加美观
show create table student;
//查看表的的字段信息
desc student;
//修改表名
alter table student rename [to] h_student;
//修改字段名
alter table h_student change name stu_name varchar(20);
//修改字段的数据类型
alter table h_student modify id int(20);
//添加字段
alter table h_student add grade float;
//删除字段
alter table h_student drop grade;
//修改字段的位置
alter table h_student modify stu_name varchar(20) first;
alter table h_student modify id int(11) after age;
//删除数据表
drop table h_student;
关于表约束
约束条件 说明
PRIMARY KEY 主键约束,用于唯一标识对应的记录
FOREIGN KEY 外键约束
NOT NULL 非空约束
UNIQUE 唯一性约束
DEFAULT 默认值约束,用于设置字段的默认值
关于索引
作用:提高表中数据的查询速度
//一.创建表的时候创建索引
create table 表名(
字段名 数据类型[完整性约束条件],
...
字段名 数据类型,
[UNIQUE|FULLTEXT|SPATIAL] INDEX|KEY
);
1.普通索引(字段+字段类型)
//1-1.创建普通索引
create table test1(
id INT,
name VARCHAR(20),
age INT,
INDEX (id)
);
//可以插入一条数据,查看索引是否被使用
explain select * from test1 where id=1
2.唯一性索引(字段+类型+unique修饰主键)
//1-2.创建唯一性索引
create table test2(
id INT,
name VARCHAR(20),
age INT,
UNIQUE INDEX unique_id(id asc)
);
3.全文索引(普通索引+fulltext修饰主键-)
//1-3.创建全文索引
create table test3(
id INT,
name VARCHAR(20),
age INT,
FULLTEXT INDEX fulltext_name(name)
)ENGINE=MyISAM;
4.单列索引
create table test4(
id INT,
name VARCHAR(20),
age INT,
INDEX single_name(name(20))
);
5.多列索引
//1-5.创建多列索引
create table test5(
id INT,
name VARCHAR(20),
age INT,
INDEX multi(id,name(20))
);
6.空间索引
//1-6.创建空间索引
create table test6(
id INT,
space GEOMETRY NOT NULL,
SPATIAL INDEX sp(space)
)ENGINE=MyISAM;
索引的区别
mysql索引类型:
①主键索引:与唯一索引之间的区别就在于不允许有空值,创建主键时会自动创建此索引。
②普通索引:最基本的索引,没有什么特殊的限制。
③唯一索引:与普通索引之间的区别就在于索引列的值必须是唯一的,但是可以有空值。
④全文索引:仅可在使用了Myisam存储引擎的表中使用,针对较大的数据列。
索引的优缺点
优点 :
- 使用索引可以大大加快 数据的检索速度(大大减少检索的数据量), 这也是创建索引的最主要的原因。
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
缺点 :
- 创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执行效率。
- 索引需要使用物理文件存储,也会耗费一定空间。
索引的底层数据结构
Hash表 & B+树
哈希表是键值对的集合,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。
为何能够通过 key 快速取出 value呢? 原因在于 哈希算法(也叫散列算法)。通过哈希算法,我们可以快速找到 value 对应的 index,找到了 index 也就找到了对应的 value。
创建索引的注意事项
1.选择合适的字段创建索引:
- 不为 NULL 的字段 :索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0,1,true,false 这样语义较为清晰的短值或短字符作为替代。
- 被频繁查询的字段 :我们创建索引的字段应该是查询操作非常频繁的字段。
- 被作为条件查询的字段 :被作为 WHERE 条件查询的字段,应该被考虑建立索引。
- 频繁需要排序的字段 :索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
- 被经常频繁用于连接的字段 :经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。
2.被频繁更新的字段应该慎重建立索引。
虽然索引能带来查询上的效率,但是维护索引的成本也是不小的。 如果一个字段不被经常查询,反而被经常修改,那么就更不应该在这种字段上建立索引了。
3.尽可能的考虑建立联合索引而不是单列索引。
因为索引是需要占用磁盘空间的,可以简单理解为每个索引都对应着一颗 B+树。如果一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是很多的,且修改索引时,耗费的时间也是较多的。如果是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操作效率也会提升。
4.注意避免冗余索引 。
冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。
5.考虑在字符串类型的字段上使用前缀索引代替普通
删除索引,有下面两种方式
//1.使用alter table删除索引fulltextidx
alter table student drop index fulltextidx;
//2.使用drop index删除索引spatidx
drop index spatidx on student;
添加数据
//插入一条数据,也可以少某个字段的同时也少对应的数据
insert into student(id,name,grade) values(1,'howie',70);
//也可以不指定字段名,但要注意顺序(不建议)
insert into student values(2,'howie',80);
//也可以这样添加数据
insert into student set id=3,name="howie",grade=90;
//同时添加多条数据
insert into student values
(4,'howie',80),
(5,'howie',80),
(6,'howie',80);`
更新数据
//更新id=1的数据
update student set name="howie1",grade=60 where id=1;
//批量更新,如果没有where子句,会更新表中所有对应数据
update student set grade=100 where id<4;
删除数据
//删除id=6的数据
delete from student where id=6;
//批量删除数据
delete from student where id>3;
//删除所有数据,DDL(数据定义语言)语句 truncate table student也可以删除表内所有数据
delete from student;
单表查询和多表操作
单表查询:如何从数据库中获取你需要的数据
多表查询:实际开发中,需要进行2张表以上进行操作
//单表查询
//in关键字查询,也可以使用not in
select * from student where id IN(1,2,3);
//between and关键字查询
select * from student where id between 2 and 5;
//空值(NULL)查询,使用IS NULL来判断
select * from student where grade is null;
//distinct关键字查询
select distinct name from student;
//like关键字查询,查询以h开头,e结尾的数据
select * from student where name like "h%e";
//and关键字多条件查询,or关键字的使用也是类似
select * from student where id>5 and grade>60;
//高级查询
//聚合函数
//count()函数,sum()函数,avg()函数,max()函数,min()函数
select count(*) from student;
select sum(grade) from student;
select avg(grade) from student;
select max(grade) from student;
select min(grade) from student;
//对查询结果进行排序
select * from student order by grade;
//分组查询
//1.单独使用group by分组
select * from student group by grade;
//2.和聚合函数一起使用
select count(*),grade from student group by grade;
//3.和having关键字一起使用
select sum(grade),name from student group by grade having sum(grade) >100;
//使用limit限制查询结果的数量
select * from student limit 5;
select * from student limit 2,2;
select * from student order by grade desc limit 2,2;
//函数,mysql提供了许多函数
select concat(id,':',name,':',grade) from student;
//为表取别名
select * from student as stu where stu.name="howie";
//为字段取别名,as关键字也可以不写
select name as stu_name,grade stu_grade from student;
外键是指引用另一个表中的一列或者多列,被引用的列应该具有主键约束或者唯一性约束,用于建立和加强两个数据表之间的连接。
//交叉连接
select * from student cross join class;
//内连接,该功能也可以使用where语句实现
select student.stu_name,class.classname from student join class on class.id=student.cid;
//外连接
//首先在student,class表中插入数据
insert into class values(3,"软件三班");
//左连接,右连接
select s.stu_id,s.stu_name,c.classname from student s left join class c on c.id=s.cid;
select s.stu_id,s.stu_name,c.classname from student s right join class c on c.id=s.cid;
//复合条件连接查询就是添加过滤条件
//子查询
//in关键字子查询跟上面的in关键字查询类似
select * from student where cid in(select id from class where id=2);
//exists关键字查询,相当于测试,不产生数据,只返回true或者false,只有返回true,外层才会执行,具体看下图
select * from student where exists(select id from class where id=12); -- 外层不会执行
select * from student where exists(select id from class where id=1); -- 外层会执行
//any关键字查询
select * from student where cid>any(select id from class);
//all关键字查询
select * from student where cid=any(select id from class);
1.左连接【left join】(左外连接)
左(外)连接,左表(a_table)的记录将会全部表示出来,而右表(b_table)只会显示符合搜索条件的记录。右表记录不足的地方均为NULL。
2.右连接【right join】(右外连接)
与左(外)连接相反,右(外)连接,左表(a_table)只会显示符合搜索条件的记录,而右表(b_table)的记录将会全部表示出来。左表记录不足的地方均为NULL。
3.内连接【inner join 】(等值连接)
只返回两个表中连接字段相等的行。
4.全外连接【full join】
返回左右表中所有的记录和左右表中连接字段相等的记录。
常见存储引擎
1.InnoDB
2.MyISAM
3、简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别
MyISAM:
(1)不支持事务,但是每次查询都是原子的;
(2)支持表级锁,即每次操作是对整个表加锁;
(3)存储表的总行数;
(4)一个 MYISAM 表有三个文件:索引文件、表结构文件、数据文件;
(5)采用菲聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。
InnoDb:
(1)支持 ACID 的事务,支持事务的四种隔离级别;
(2)支持行级锁及外键约束:因此可以支持写并发;
(3)不存储总行数:
(4)一个 InnoDb 引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空,表大小受操作系统文件大小限制,一般为 2G),受操作系统文件大小的限制;
(5)主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持 B+树结构,文件的大调整。
存储过程
delimiter // -- 将mysql的结束符设置为//
create procedure Proc()
begin
select * from student;
end //
delimiter ; -- 将mysql的结束符设置为;
call Proc(); -- 这样就可以调用该存储过程
//变量的使用,mysql中变量不用事前申明,在用的时候直接用“@变量名”使用就可以
set @number=100; -- 或set @num:=1;
//定义条件和处理程序
//光标的使用
//1.声明光标
DECLARE * cursor_name* CURSOR FOR select_statement
2. 光标OPEN语句
OPEN cursor_name
3. 光标FETCH语句
FETCH cursor_name INTO var_name [, var_name] ...
4. 光标CLOSE语句
CLOSE cursor_name
//流程控制的使用 不做介绍
//调用存储过程
call Proc("tom",@num);
//查看存储过程
show procedure status like 'p%' \G -- 获得以p开头的存储过程信息
//修改存储过程
alter {procedure|function} sp_name[characteristic...]
//删除存储过程
drop procedure proc1;
视图
//开始创建视图
create view stu_view as select math,chinese,math+chinese from student; -- 下图可看出创建成功
//也可以创建自定义字段名称的视图
create view stu_view2(math,chin,sum) as select math,chinese,math+chinese from student;
//查看视图
desc stu_class;
show table status like 'stu_class'\G
show create view stu_class\G
//修改视图
create or replace view stu_view as select * from student;
alter view stu_view as select chinese from student;
//更新视图
update stu_view set chinese=100;
insert into student values(null,'haha',100,100);
delete from stu_view2 where math=100;
//删除视图
drop view if exists stu_view2;