mysql基础易错总结

一、MySQL数据库基础

数据库泛型(范式)

第一范式:表中不能有重复字段,并且不能拆分。

二、MYSQL基本操作

数据库类型

整数类型:tinyint(4),smallint(6),mediumint(9),int(11),bigint(20)

浮点类型:FLOAT(4),DOUBLE(8)

定点数类型:DECIMAL(M,D)(M+2) 

注意:DECIMAL的取值范围和DOUBLE相同,但是有效范围由M和D决定,字节数是M+2,存储空间是由其精度确定的。

特别注意:mysql中定点数以字符串形式存储。因此,精度比浮点数要高。而且浮点数会有误差。

日期和时间类型:YEAR(1),DATE(4)TIME(3)DATETIME(8)TIMESTAMP(4)

字符串类型:CHAR,VARCHAR,BLOB,TEXT,ENUM,SET

注意:SET和ENUM类型对取值在一定范围的离散值有效,SET可在取值列表中取多个值,且都不是直接插入数据,而是插入列表中编号。

二进制类型:BINARY,VAARBINARY,BIT,TINYBLOB,BLOB,MEDIUMBLOB,LONGBLOB

数据库引擎

InnoDB存储引擎:提供事务,回滚,崩溃修复和多版本并发控制的事务安全。支持自增长列。支持外键。读写效率差,占用空间大。

MuISAM存储引擎:占用空间小,处理速度快。不支持事务的完整性和并发性。

索引

索引是创建在表上对列进行排序的一种结构。

普通索引:可以创建在任何数据类型中。

唯一性索引:需限制索引的值必须是唯一的。

全文索引:使用FULLTEXT设置,且只能创建在CHAR,VARCHAR和TEXT字段

单列索引:只对应一个字段

多列索引:多个字段创建索引,但是只有查询条件中使用这些字段的第一个字段时才被使用。

空间索引:使用SPATIAL参数设置,只能创建在GEOMETRY,POINT,LINESTRING和POLYGON上,目前只有MyISAM存储引擎支持空间索引。

索引设计原则

1.选择唯一性索引

2.经常需要排序,分组和联合操作的字段

3.作为查询条件的字段

4.限制索引的数目

5.尽量使用前缀来索引

触发器

创建只有一个执行语句的触发器:

create trigger 触发器名 before|after 触发事件 on 表名 for each row 执行语句

eg:create trigger dept_trig before insert on department for each row insert into trigger_time values(now());

创建有多个执行语句的触发器:

create trigger 触发器名 before|after 触发事件

        on 表名 for each row

        begin        

                执行语句

        end

eg:

delimiter &&

create trigger dept_trig after delete on department for each row

begin

        insert into trigger_time values('value');

        insert into trigger_time values('value2');

end

&&

delimiter

注意:

问题:mysql创建多条执行语句触发器总是遇到分号就结束创建,然后报错?

一般情况下,mysql默认是以;为结束执行语句,在创建触发器时用到;,为解决这个问题,可以用delimiter语句,如使用“deliniter &&”,可以将结束符号编程“&&”。当触发器创建完成后,可以用“deliniter;“来将结束符号编程”;“

mysql中,一个表在相同触发时间的相同触发事件,只能创建一个触发器

查看触发器:

show triggers;  //查看触发器的基本信息

select * from information_schema.triggers;  //查看数据库中所有触发器详细信息

select * from information_schema.triggers where trigger_name = '触发器名'

备注:所有触发器信息都存储在information_schema数据库下的triggers表中。

触发器的使用:

在Mysql中,触发器执行顺序是before触发器,表操作(insert,update和delete)和after触发器。

//创建before insert触发器

create trigger before_insert before insert

        on department for each row

        insert into trigger_test values(null,"before_insert");

在目标表中插入数,如果执行成功,则可在trigger_test表中查看。

删除触发器:

drop trigger 触发器名;

二、MySql查询语句

分组查询:

GROUP BY 属性名 [HAVING 条件表达式] [WITHROLLUP]

//“属性名”:指按照该字段的值进行分组;“HAVING条件表达式”:用来限制分组后的显示;“WITH ROLLUP”:将会在所有记录的最后加上一条记录,该记录是上面所有记录的和。

GROUP BY关键字与GROUP——CONCAT()函数一起使用

select sex,group_concat(name) from employee group by sex;

//group_concat()函数会把每个分组中指定字段值显示出来。

GROUP BY关键字与HAVING一起使用

select sex,count(sex) from employee group by sex having count(sex) >= 3;

//HAVING条件表达式 与 WHERE条件表达式 都是用来限制显示的。但是,两者起作用的地方不一样。WHERE作用于表或视图,是表和视图的查询条件。HAVING作用于分组后的记录,用于选择满足条件的组。

GROUP BY关键字与WITH ROLLUP一起使用

select sex,group_concat(name) from employee group by sex with rollup;

//使用with rollup时,将会在所有记录的最后加上一条记录,这条记录是上面所有记录的总和。

LIMIT关键字

LIMIT 初始位置,记录数

//初始位置参数指定从哪开始,记录数参数表示显示记录的条数。

注意:limit关键字是mysql中所特有的,limit关键字可以指定需要显示的记录的初始位置。

集合函数使用注意事项:

1.sum()函数只能计算数值类型的字段,包括int类型,float类型,double类型,decimal类型。字符类型的字段不能使用sum函数进行计算,结果会是0

2.max(),min()等函数使用字符对应的ASCII码进行计算。

子查询

带EXISTS关键字的子查询

(NOT)EXISTS关键字表示存在,使用EXISTS,内查询不返回查询的记录,而是返回一个真假值。

eg:select* from employee where exists(select d_name from department where id = 1);

带ANY关键字的子查询

ANY关键字表示满足任一条件。ALL表示满足所有

eg: select * from computer_stu where score >= any(select score from sholarship);

合并查询

注意:UNION和UNION ALL关键字都可以合并查询结果,区别:union会将相同的记录清除掉,union all不会消除记录。

正则表达式查询

正则表达式的模式字符
正则表达式的模拟字符含义
^匹配字符串开始的部分
$匹配字符串结束的部分
.代表字符串中的任意一个字符,包括回车和换行
[字符集合]匹配“字符集合”中的任何一个字符
[^字符集合]匹配除了“字符集合”以外的任何一个字符
S1|S2|S3匹配S1,S2和S3中的任意字符
*代表多个该符号之前的字符,包括0和1个
+代表多个该符号之前的字符,包括1个
字符串{N}字符串出现N次
字符串{M,N}字符串出现至少M次,最多N次

正则用于匹配一类字符串的方式。使用REGEXP关键字来匹配查询正则表达式。

eg:

查询以L开头名字:select * from info where name regexp '^L';

查询以L开头,以字母y结尾,中间有两个任意字符的记录:

select * from info where name regexp '^L..y$'

查询字段中包含c、e和o3个字母的任意一个记录:

select * from info where name regexp '[ceo]'

(常用)查询字段中包含0-9数字和a-c字母的字段:

select * from info where name regexp '[0-9a-c]';  #[a-z]所有字母 [0-9]所有数字

查询包含a到w字母和数字以外的字符记录:

select * from info where name regexp '[^a-w0--9]';

查询包含'ic'、'uc'和'ab'这3个任意一个:

select * from info where name regexp 'ic|uc|ab';

查询c之前出现过a的记录:

select * from info where name regexp 'a*b';  #注意*和+的区别

查询字段中ab最少一次,最多3次的记录

select * from info where name regexp 'ab{1,3}';

注意:使用[]匹配需要的字符时,使用[abc]指定字符集合,每个字符不要隔开。

常见问题:

1.MySql中通配符与正则表达式的区别?

同配和正则都是用来字符串匹配的,两者都可以及进行模糊查询。通配符与LIKE关键字一起使用。正则要与REGEXP关键字使用。

2.使用limit来限制查询结果数量?

查询5-8名的信息,就可以使用LIMIT从第5条开始,显示4条记录。

插入、删除数据

将查询结果插入到表中

insert into product(id,function) selectid,function from medicine;

如何进行联表删除?

通过外键进行删除,联表删除可以保证数据库中数据的一致性。

MySQL运算符

mysql算术运算符
符号表达式的形式作用(如果y是0,则结果是null)
/x / y除法,返回x除以y商
DIVx DIV y除发,返回商。同/
%x % y求余,返回x除以y的余数
MODMOD(x,y)求余,返回余数,同%

 运算符=,<=>

=不能判空,使用ASCII进行判断

<=> 与=是一样的,但是<=>可以判断null

注意:=,<>,!=,>,>=,<,<=等操作都不能用来判空,如果要判空,可以使用<=>,is null,is not null。

运算符like

like和'_'和'%'使用,'_'代表单个字符,'%'代表任意长度字符

 逻辑运算符
符号名称符号名称
&&或者AND!或者NOT
||或者ORXOR异或

注意:mysql中所有异或中,大于-1小于1的数字都被视为逻辑0,其他为逻辑1

位运算符
符号名称符号名称
&按位与^按位异或
|按位或<<按位左移
~按位取反>>按位右移

注意:位运算都是在二进制上进行的。

问题:

运算符优先级?

!最高,=最低,其他自行百度

位运算的禁止问题?

位运算必须是十进制的。十进制和二进制之间的互换是数据库实现的。如果操作数是二进制,八进制,十六进制时,要先通过conv()函数将操作数转换为十进制数。

MySQL函数

数学函数(部分)
函数作用
ceil(x),ceiling(x)返回大于x最小整数
sign(x)返回x的符号
truncate(x,y),round(x,y)保留小数,后者四舍五入
pow(x,y),sqrt(x)次方,开方
字符串函数(部分)
函数作用
char_length(s),length(s)返回s的字符数,长度
concat(s1,s2)

将字符s1,s2合并

concat_ws(x,s1,w2)合并每个字符串前+x
insert(s1,x,len,s2)将字符串s2替换s1的x位置开始长度为len的字符串
lpad(s1,len,s2)字符串s2填充s1的开始处,使长度到len
trim(s1 from s)去掉s开始处和结尾处的空格
strcmp(s1,s2)比较s1和s2
locate(s1,s),position(s1 in s),instr(s,s1)从s处获取s1的开始位置
reverse(s)逆序
field(s,s1,s2)返回第一个与字符串s匹配的字符串位置
日期和时间函数
函数作用
curdate(),current_timestamp(),now()返回日期,时间
month(d),monthname(d)返回月份1-12,名称
dayname(d),daofweek(d),weekday(d),week(d),weekofyear(d)

返回d星期名称,开始日期分别是日或一的格式,本年0-53或1-53

dayofyear(d),dayofmonth(),year(d)返回本年,本月第几天和年份值
quarter(d)返回季度1-4
hour(t),minute(t),second(t)返回t的小时,分钟,秒
time_to_sec(t),sec_to_time(t)t和秒互转
to_days(d),from_day(d)d~0000年1月1号天数互转
datediff(d1,d2)d1~d2间隔天数
adddate(d,n),subdate(d,n)d加上减去n天
adddate(d interval xepr type),subdate(d interval xepr type)d日期加上减去一个时间端后的日期

addtime(t,n),subtime(t,n)

计算t加减n秒的时间
get_format(type,s)s获取type类型数据的显示格式
MySQL的日期间隔类型
类型expr表达式的形式
YEARYY
MONTHMM
DAYDD
HOURhh
MINUTEmm
SECONDss
YEAR_MONTHYY和MM之间任意符号隔开

注意:adddate(d interval expr type)的type必须是上表中的。

MySQL日期时间格式
%Y2022
%y 2位数年22
%m 2位数字月份01,02
%c 数字月份1,2
%M 月份January
%b 月份Jan
%U 星期,Sun是第一天00-52
%u 星期,Mon是第一天00-52
%j 3位年中天数001-336
%d 2位数字月份日期01,02,...,31
%e 数字月份日期1,2,...,31
%D 英文月份1st,2nd,...
%w 数字星期0:Sunday,1Monday
%W 星期Monday,...,Sunday
%a 星期Mon,...,Sun
%T 24小时00:00:00-23:59:59
%r12小时制AM12:00:00AM
%p AM
%k 24小时制0,1,...,23
%l 12小时制1,2,...,12
%H 小时00,01,...,23
%h,%I 小时01,02,...,12
%i 分00,01,...,59
%S,%s 时00,01,...,23
%%%

加密函数

加密函数PASSWORD(str)

selet password('abcd'); #PASSWORD(str)加密不可逆

加密函数MD5(str)

select md5('abcd');

加密函数encode(str,pswd_str)

insert into b values(encode('abcd','aa')); #encode(str,pswd_str)函数使用pswd_str来加密str,加密结果是一个二进制,必须使用blob类型保存。

解密函数decode(crypt_str,pswd_str)

select decode('encode('abcd','aa'),'aa'); #decode(crypt_str,pswd_str)函数使用pswd_str来为crpt_str解密,

其他函数

IP地址与数字转换函数

select INET_ATON('59.65.226.15'),INET_NTOA(994173455)

加锁函数和解锁函数

select get_lock('MYSQL',10); #增加一个名为MYSQL的锁,10s

注意:当执行release_lock()、一个新的get_lock获取线程终止,那么之前的锁都会解除。

重复执行指定操作函数

select benchmark(10000,now()); #返回系统时间10000次

问题:如何改变字符串的字符集?

MySQL可以重新配置字符集来修改,也可以在MySQL的安装路径下修改my.ini。将default-charset-set的值改变来修改字符集。如果只是修改某个字符串的字符集,可以使用convert(s using cs)函数

存储过程和函数

创建存储过程:创建存储过程和哈数是指将常用的一组SQL语句的组合起来,并将这些SQL语句当作一个整体存储在MYSQL服务器中。

create procedure sp_name ([proc_parameter[,...]]) [characteristic ...] routine_body 

#sp_name 参数是存储过程的名称;proc_parameter表示存储过程的参数列表,characteristic参数指定存储过程的特性;routine_body参数是SQL代码的内容。可以用BEGIN...END来标志开始结束。

#proc_parameter中每个参数由3部分组成 [IN|OUT|INOUT] param_name type

技巧:创建存储过程时,系统默认指定contains sql,表示存储过程中使用了sql语句,但是,如果存储过程中没有使用sql语句,最好设置no sql,而且。存储过程中最好在comment部分对存储过程进行简单的注释。

创建一个名称num_from_employee的存储过程。

create procedure num_from_employee(IN emp_id INT,OUT count_num INT)

        reads sql data

        begin

                select count(*) into count_num from employee where d_id = emp_id;

        end

#存储过程名num_from_employee,输入变量emp_id,输出变量ount_num。select语句

从employee表查询d_id等于emp_id的记录,并用count激素那条数,最后将结果存入count_num中。

创建存储函数

create function sp_name ([func_parameter[,...]]) returns type [characteristic ...] routine_body

创建一个名为name_from_employee的存储函数

create function name_from_employee (emp_id INT)

        returns varchar(20)

        begin

                retrun (select name from employee where num = emp_id);

        end

定义变量

declare my int default 10; #定义变量my 类型int 默认10

set my = 30; #赋值

select d_id into  my from employee where id = 2; #将id-2的记录赋给my

定义条件

#定义“ERROR 1146(42S02)”这个错误,名称为can_not_find

//方法一

declare can_not_find condition for SQLSTATE '42S02';

//方法二

declare can_not_find condition for 1146;

定义处理程序

//捕获sqlstate_value

declare continue handler for sqlstate '42S02' set @info='CAN NOT FIND'

//捕获mysql_error_code

declare continue handler for 1146 set @info='CAN NOT FOUND'

//先定义条件在使用

declare can_bot_find condition for 1146;

declare continue handler for can_not_find set @info='CAN NOT FOUND'

//使用sqlwarning

declare exit handler for sqlwarning set @info='ERROR'

//使用not found

declare exit handler for not found set @info='CAN NOT FOUND'

//使用sqlexception

declare exit handler for sqlexception set @info='ERROR'

注意:执行过程中遇到错误应该立刻停止执行下面的语句,并且撤回前面的操作。但是MySQL不支持UNDO操作。因此遇到错误最好执行EXIT操作。如果能事先预知错误类型并且相应处理,那么可以执行continue操作。

流程控制语句的使用:

if语句,case语句,loop语句,leave语句,iterate语句,repeat语句,wehile语句

LOOP语句:loop可实现简单的循环,但是不能停止,需要leave语句才能停止。

add_num:loop set @count = @count + 1; end loopadd_num;  //死循环+1

add_num:loop set @count = @count + 1;if @count = 100 then leave add_num; end loop add_num;  //当count=100跳出循环

ITERATE语句:跳出本次循环,然后进入下一次循环。

add_num:loop set @count = @count+1; if @count = 100 then leave add_num; else if mod(@count,3) = 0 then iterate add_num; select * from employee; end loop add_num;

//如果count能够整除3.则跳出本次循环,不再执行select语句

WHILE语句:当条件满足是执行循环语句

while @count < 100 do set @count = @count + 1; end while;

调用存储过程:mysql使用call来调用存储过程。

//创建存储过程

delimiter &&

create procedure num_from_employee(in emp_id int,out count_num int)

reads sql data

begin

select count(*) into count_num from employee where d_id = emp_id;

end &&

delimiter;

//调用存储过程
call num_from_employee(1002,@n);

调用存储函数:同上

查看存储过程和函数:

show procedure status like 'num_from_employee'\G  

注意:show status语句支持能查看存储过程是哪个数据库,详细定义需要使用show create语句。

从informaation_schema.Routines表中查看存储过程

select * from information_schema.Routines where routine_name = 'sp_name' //查看sp_nama的存储信息

修改,删除存储过程:Alter、DROP

问题:

1.一个存储过程中可以调用其他的存储过程吗?

可以,用户通过call语句调用已经定义好的sql语句。

2.存储过程和存储函数的区别是什么?

存储过程的参数有3类:IN,OUT和INOUT,通过OUT,INOUT将存储过程的执行结果输出,而且存储过程中可以有多个OUT,INOUT类型的变量,可输出多个值。

存储函数中的参数都是输入参数,函数中的运算结果通过return语句来返回且只能返回一个结果。

3.存储函数和mysql内部函数有什么区别?

存储函数是用户自己定义的函数。并且通过调用来执行函数中的sql语句,函数执行完成后,通过return语句来执行返回执行结果。

四、MySQL数据库高级管理

用户管理

权限表:安装Mysql会自动创建一个名为mysql的数据库。mysql数据库下存储的都是权限表,用户登录后,会为每个用户赋予相应的权限,其中user、db和host表比较重要。

user表中重要字段:

Gran_priv:是否拥有GRANT权限,Shutdown_priv:是否拥有停止mysql服务的权限,Super_priv:是否拥有超级权限,Execue_priv:是否拥有execute权限。

db表和host表:db表存储某个用户对一个数据库的权限。

数据备份

mysqldump:mysqldump命令可以将数据库中的数据备份成一个文本文件,表的结构和表中的数据将存储在生成的文本文件中。

mysqldump-u username -p dbname table1 tables2 > BackupName.sql  //也可生成txt文件

mysqlhotcopy:如果备份不能停止mysql服务,可采用此工具

mysqlhotcopy [option] dbname1 dbname2 backupDir/

数据还原:

mysql -u root -p [dbname] < backup.sql

数据库迁移:

相同版本的数据库迁移:

mysqldump -h name1 -u root ==password = password1 --all -databases | mysql -h host2 -u root --password = password2

//“|”:代表管道,password1是name1主机上root用户的密码

不同版本的数据库迁移:

建议使用ETL工具

MySQL日志

Mysql日志可分为二进制日志,错误日志,通用日志和慢查询日志。除二进制日志外,其他都是文本文件。

注意:默认只启动错误日志功能,启动日志会降低MySQL数据库的执行速度,并且日志文件会占用大量硬盘空间。

二进制日志(update log):以二进制文件的形式记录了数据库中的操作,但不记录查询语句

开启二进制日志

#my.ini

log-bin [=DIR\[filename]]

//DIR指二进制文件的存储路径,filename指二进制文件名。每次重启都会生成一个新的二进制文件

注意:二进制文件和数据库数据文件最好分开存储,即使一个硬盘坏了,也不会丢失数据

 查看二进制文件

mysqlbinlog filename.number //mysqlbinlog命令将在当前文件夹下查找指定的二进制日志。

mysqlbinlog C:\log\mylog.000001  //绝对路径查找

删除二进制文件

RESET MASTER  //删除所有

PURGE MASTER LOGS TO 'filename.number' //根据编号删除二进制文件

二进制文件还原数据库

mysqlbinlog filename.number | mysql -u root -p  //注意还原的文件编号的时序性

错误日志:记录MySQL服务器的启动,关闭和运行错误等消息,默认开启,无法禁止

设置错误日志存储位置

#my.ini

log-error=DIR/[filename]  //重启后参数生效

删除

mysqladmin -u root -p flush-logs

通用日志:记录用户登录和记录查询的信息

开启通用日志

#my.ini

log=[=DIR\[filename]]

慢查询日志:记录执行时间超过指定时间的操作

开启

#my.ini

log-slow0queries [=DIR\[filename]]

long_query_time=n  //n:设定的时间值单位秒

性能优化

优化查询:使用EXPLAIN和DESCRIBE语句分析语句。

explain select * from staudent\G

//id:表示select语句的编号

//select_type:表示select语句的类型(SIMPLE、PRIMARY、UNION)

//table:表

//type:连接类型

//possible_keys:可能使用的索引

//key:使用的索引

//key_len:索引长

//ref:列或常数与索引一起来查询记录

//rows:查询的行数

//Extra:查询中的附件信息

索引失效:

1.查询语句中使用LIKE关键字

如果匹配字符第一个字符为%,索引不生效,如果%不是第一个位置,索引生效。

2.查询语句中使用多列索引

多列索引是在表的多个字段上创建一个索引。只有查询条件中使用这些字段第一个字段是,索引才会被使用。

3.查询中使用OR关键字

如果OR关键字前后两个参数都有索引时,查询中将使用索引,如果有一个不是,则不使用。

4.字段类型不匹配

数值类型字段使用字符类型查询

优化插入记录速度

插入记录时,索引,唯一性校验都会影响速度。

1.禁用索引后开启

ALTER TABLE 表名 DISABLE KEYS

ALTER TABLE 表名 ENABLE KEYS

2.禁用唯一性检查后开启

SET UNIQUE_CHECKS=0

SET UNIQUE_CHECKS=1

优化INSERT语句

采用拼接sql的方式插入数据

优化表

通过OPTIMIZE TABLE 语句可以消除删除和更新造成的磁盘碎片,从而减少空间浪费

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值