-- 存储过程---------------create database mysql7_procedure;
use mysql7_procedure;
-- 1:创建存储过程/*
delimiter 自定义结束符号
create procedure 储存名([ in ,out ,inout ] 参数名 数据类形...)
begin
sql语句
end 自定义的结束符合
delimiter ;
*/
delimiter $$
createprocedure proc01()
beginselect empno,ename from emp;
end $$
delimiter ;
-- 调用存储过程call proc01();
call proc01();
-- 变量定义/*
语法1: 声明变量 declare var_name type [default var_value];
语法2:
select col_name [...] into var_name[,...]
from table_name wehre condition
*/
delimiter $$
createprocedure proc02()
begindeclare var_name01 varchar(20) default'aaa'; -- 声明/定义变量set var_name01 ='zhangsan'; -- 给变量赋值select var_name01; -- 输出变量的值end $$
delimiter ;
call proc02();
/*
select col_name [...] into var_name[,...]
from table_name wehre condition
其中:
col_name 参数表示查询的字段名称;
var_name 参数是变量的名称;
table_name 参数指表的名称;
condition 参数指查询条件。
注意:当将查询结果赋值给变量时,该查询语句的返回结果只能是单行单列。
*/
delimiter $$
createprocedure proc03()
begindeclare my_ename varchar(20) ; -- 声明/定义变量select ename into my_ename from emp where empno =1001; -- 给变量赋值select my_ename; -- 输出变量的值end $$
delimiter ;
call proc03();
-- 用户变量
delimiter $$
createprocedure proc04()
beginset@var_nam01 ='beijing';
select@var_nam01;
end $$
delimiter ;
call proc04();
select@var_nam01; -- 也可以使用用户变量
use mysql7_procedure;
-- 系统变量-- 全局变量
use mysql7_procedure
-- 查看全局变量showglobal variables;
-- 查看某全局变量select @@global.auto_increment_increment;
-- 修改全局变量的值setglobal sort_buffer_size =40000;
set @@global.sort_buffer_size =33000;
select @@global.sort_buffer_size;
-- 会话变量-- 查看会话变量show session variables;
-- 查看某会话变量select @@session.auto_increment_increment;
-- 修改会话变量的值set session sort_buffer_size =50000;
set @@session.sort_buffer_size =60000 ;
select @@session.sort_buffer_size;
-- ---------传入参数:in---------------------------------
use mysql7_procedure;
-- 封装有参数的存储过程,传入员工编号,查找员工信息
delimiter $$
createprocedure proc06(in empno int )
beginselect*from emp where emp.empno = empno;
end $$
delimiter ;
call proc06(1001);
call proc06(1002);
-- -------------------------------------- 封装有参数的存储过程,可以通过传入部门名和薪资,查询指定部门,并且薪资大于指定值的员工信息
delimiter $$
createprocedure proc07(in param_dname varchar(50), in param_sal decimal(7,2))
beginselect*from dept a, emp b where a.deptno = b.deptno and a.dname = param_dname and b.sal > param_sal;
end $$
delimiter ;
call proc07('学工部',20000);
call proc07('销售部',10000);
-- ---------传出参数:out---------------------------------
use mysql7_procedure;
-- 封装有参数的存储过程,传入员工编号,返回员工名字
delimiter $$
createprocedure proc08(in in_empno int, out out_ename varchar(50))
beginselect ename into out_ename from emp where empno = in_empno;
end $$
delimiter ;
call proc08(1002, @o_ename);
select@o_ename;
-- -------------------------------------------- 封装有参数的存储过程,传入员工编号,返回员工名字和薪资
delimiter $$
createprocedure proc09(in in_empno int, out out_ename varchar(50), out out_sal decimal(7,2))
beginselect ename, sal into out_ename , out_sal
from emp
where empno = in_empno;
end $$
delimiter ;
call proc09(1002, @o_ename,@o_sal);
select@o_ename;
select@o_sal;
-- -------------------------------------- 封装有参数的存储过程,可以通过传入部门名和薪资,查询指定部门,并且薪资大于指定值的员工信息
delimiter $$
createprocedure proc07(in param_dname varchar(50), in param_sal decimal(7,2))
beginselect*from dept a, emp b where a.deptno = b.deptno and a.dname = param_dname and b.sal > param_sal;
end $$
delimiter ;
call proc07('学工部',20000);
call proc07('销售部',10000);
use mysql7_procedure;
-- 传入一个数字,传出这个数字的10倍值
delimiter $$
createprocedure proc10(inout num int)
beginset num = num *10;
end $$
delimiter ;
set@inout_num =3;
call proc10(@inout_num);
select@inout_num;
-- 传入员工名,拼接部门号,传入薪资,求出年薪-- 关羽 ----> 30_关羽
delimiter $$
createprocedure proc11(inout inout_ename varchar(50), inout inout_sal int)
beginselect concat_ws('_',deptno,ename) into inout_ename from emp where emp.ename = inout_ename;
set inout_sal = inout_sal *12;
end $$
delimiter ;
set@inout_ename ='关羽';
set@inout_sal =3000;
call proc11(@inout_ename,@inout_sal);
select@inout_ename ;
select@inout_sal;
-- 存储过程-if-- 案例1-- 输入学生的成绩,来判断成绩的级别:/*
score < 60 :不及格
score >= 60 , score <80 :及格
score >= 80 , score < 90 :良好
score >= 90 , score <= 100 :优秀
score > 100 :成绩错误
*/
delimiter $$
createprocedure proc_12_if(in score int)
begin
if score <60thenselect'不及格';
elseif score <80thenselect'及格' ;
elseif score >=80and score <90thenselect'良好';
elseif score >=90and score <=100thenselect'优秀';
elseselect'成绩错误';
end if;
end $$
delimiter ;
call proc_12_if(120)
-- 输入员工的名字,判断工资的情况。/*
sal < 10000 :试用薪资
sal >= 10000 and sal < 20000 :转正薪资
sal >= 20000 :元老薪资
*/
delimiter $$
createprocedure proc_13_if(in in_ename varchar(20))
begindeclare var_sal decimal(7,2);
declareresultvarchar(20);
select sal into var_sal from emp where ename = in_ename;
if var_sal <10000thensetresult='试用薪资';
elseif var_sal <20000thensetresult='转正薪资' ;
elsesetresult='元老薪资' ;
end if;
selectresult;
end $$
delimiter ;
-- 调用call proc_13_if('关羽');
call proc_13_if('程普');
-- 流程控制语句:case/*
支付方式:
1 微信支付
2 支付宝支付
3 银行卡支付
4 其他方式支付
*/-- 格式1
delimiter $$
createprocedure proc14_case(in pay_type int)
begincase pay_type
when1thenselect'微信支付' ;
when2thenselect'支付宝支付' ;
when3thenselect'银行卡支付';
elseselect'其他方式支付';
endcase ;
end $$
delimiter ;
call proc14_case(2);
call proc14_case(4);
-- 格式2
delimiter $$
createprocedure proc_15_case(in score int)
begincasewhen score <60thenselect'不及格';
when score <80thenselect'及格' ;
when score >=80and score <90thenselect'良好';
when score >=90and score <=100thenselect'优秀';
elseselect'成绩错误';
endcase;
end $$
delimiter ;
call proc_15_case(88);
-- 存储过程-循环-while
use mysql7_procedure;
-- 创建测试表createtableuser (
uid intprimary key,
username varchar(50),
password varchar(50)
);
/*
【标签:】while 循环条件 do
循环体;
end while【 标签】;
*/-- 需求:向表中添加指定条数的数据-- -------存储过程-循环-while
delimiter $$
createprocedure proc16_while(in insertCount int)
begindeclare i intdefault1;
label:while i <= insertCount do
insertintouser(uid, username, password) values(i,concat('user-',i),'123456');
set i = i +1;
end while label;
end $$
delimiter ;
call proc16_while(10);
-- -------存储过程-循环控制-while + leave-- leave:直接跳出while循环truncatetableuser;
delimiter $$
createprocedure proc17_while_leave(in insertCount int) -- 10begindeclare i intdefault1;
label:while i <= insertCount do -- 10insertintouser(uid, username, password) values(i,concat('user-',i),'123456');
if i =5then
leave label;
end if;
set i = i +1;
end while label;
select'循环结束';
end $$
delimiter ;
call proc17_while_leave(10);
-- -------存储过程-while+iterate-- iterate:跳过本次循环的剩余代码,进入下一次循环createtable user2 (
uid int ,
username varchar(50),
password varchar(50)
);
use mysql7_procedure;
truncatetable user2;
delimiter $$
createprocedure proc17_while_iterate(in insertCount int) -- 10begindeclare i intdefault0;
label:while i < insertCount do -- 10set i = i +1;
if i =5then
iterate label;
end if;
insertinto user2(uid, username, password) values(i,concat('user-',i),'123456');
end while label;
select'循环结束';
end $$
delimiter ;
call proc17_while_iterate(10); -- 1 2 3 4 6 7 8 9 10-- -------存储过程-循环控制-repeat
use mysql7_procedure;
truncatetableuser;
delimiter $$
createprocedure proc18_repeat(in insertCount int)
begindeclare i intdefault1;
label:repeat
insertintouser(uid, username, password) values(i,concat('user-',i),'123456');
set i = i +1;
until i > insertCount
end repeat label;
select'循环结束';
end $$
delimiter ;
call proc18_repeat(100);
-- 操作游标(cursor)-- 声明游标-- 打开游标-- 通过游标获取值、-- 关闭游标-- -------存储过程-循环控制-loop/*
[标签:] loop
循环体;
if 条件表达式 then
leave [标签];
end if;
end loop;
*/
use mysql7_procedure;
truncatetableuser;
delimiter $$
createprocedure proc19_loop(in insertCount int)
begindeclare i intdefault1;
label: loop
insertintouser(uid, username, password) values(i,concat('user-',i),'123456');
set i = i +1 ;
if i > insertCount
then
leave label;
end if ;
end loop label;
end $$
delimiter ;
call proc19_loop(100);
-- 操作游标(cursor)-- 声明游标-- 打开游标-- 通过游标获取值、-- 关闭游标
use mysql7_procedure;
dropprocedure if exists proc19_cursor;
-- 需求:输入一个部门名,查询该部门员工的编号、名字、薪资 ,将查询的结果集添加游标
delimiter $$
createprocedure proc19_cursor(in in_dname varchar(50))
begin-- 定义局部变量declare var_empno int;
declare var_ename varchar(50);
declare var_sal decimal(7,2);
-- 声明游标declare my_cursor cursorforselect empno,ename,sal
from dept a, emp b
where a.deptno = b.deptno and a.dname = in_dname;
-- 打开游标open my_cursor;
-- 通过游标获取值
label:loop
fetch my_cursor into var_empno, var_ename,var_sal;
select var_empno, var_ename,var_sal;
end loop label;
-- xxxxx-- 关闭游标close my_cursor;
end $$;
delimiter ;
call proc19_cursor('销售部');
-- 游标 + 句柄/*
DECLARE handler_action HANDLER
FOR condition_value [, condition_value] ...
statement
handler_action: {
CONTINUE
| EXIT
| UNDO
}
condition_value: {
mysql_error_code
| condition_name
| SQLWARNING
| NOT FOUND
特别注意:
在语法中,变量声明、游标声明、handler声明是必须按照先后顺序书写的,否则创建存储过程出错。
*/
use mysql7_procedure;
dropprocedure if exists proc21_cursor_handler;
-- 需求:输入一个部门名,查询该部门员工的编号、名字、薪资 ,将查询的结果集添加游标
delimiter $$
createprocedure proc21_cursor_handler(in in_dname varchar(50))
begin-- 定义局部变量declare var_empno int;
declare var_ename varchar(50);
declare var_sal decimal(7,2);
-- 定义标记值declare flag intdefault1;
-- 声明游标declare my_cursor cursorforselect empno,ename,sal
from dept a, emp b
where a.deptno = b.deptno and a.dname = in_dname;
-- 定义句柄:定义异常的处理方式/*
1:异常处理完之后程序该怎么执行
continue :继续执行剩余代码
exit : 直接终止程序
undo: 不支持
2: 触发条件
条件码:
1329
条件名:
SQLWARNING
NOT FOUND
SQLEXCEPTION
3:异常触发之后执行什么代码
设置flag的值 ---》 0
*/declare continue handler for1329set flag =0;
-- 打开游标open my_cursor;
-- 通过游标获取值
label:loop
fetch my_cursor into var_empno, var_ename,var_sal;
-- 判断flag,如果flag的值为1,则执行,否则不执行
if flag =1thenselect var_empno, var_ename,var_sal;
else
leave label;
end if;
end loop label;
-- xxxxx-- 关闭游标close my_cursor;
end $$;
delimiter ;
call proc21_cursor_handler('教研部');
droptable user_2021_11_03;
-- ------------------------------------------- 练习/*
创建下个月的每天对应的表user_2021_12_01、user_2022_12_02、...
需求描述:
我们需要用某个表记录很多数据,比如记录某某用户的搜索、购买行为(注意,此处是假设用数据库保存),当每天记录较多时,如果把所有数据都记录到一张表中太庞大,需要分表,我们的要求是,每天一张表,存当天的统计数据,就要求提前生产这些表——每月月底创建下一个月每天的表!
*/-- 思路:循环构建表名 user_2021_11_01 到 user_2020_11_30;并执行create语句。create database mydb18_proc_demo;
use mydb18_proc_demo;
dropprocedure if exists proc22_demo;
delimiter $$
createprocedure proc22_demo()
begindeclare next_year int; -- 下一个月的年份declare next_month int; -- 下一个月的月份declare next_month_day int;-- 下一个月最后一天的日期declare next_month_str varchar(2); -- 下一个月的月份字符串declare next_month_day_str varchar(2);-- 下一个月的日字符串-- 处理每天的表名declare table_name_str varchar(10);
declare t_index intdefault1;
-- declare create_table_sql varchar(200);-- 获取下个月的年份set next_year =year(date_add(now(),INTERVAL1month)); -- 2021-- 获取下个月是几月set next_month =month(date_add(now(),INTERVAL1month)); -- 11-- 下个月最后一天是几号set next_month_day = dayofmonth(LAST_DAY(date_add(now(),INTERVAL1month))); -- 30
if next_month <10thenset next_month_str = concat('0',next_month); -- 1 ---》 01elseset next_month_str = concat('',next_month); -- 12end if;
while t_index <= next_month_day do
if (t_index <10)
thenset next_month_day_str = concat('0',t_index);
elseset next_month_day_str = concat('',t_index);
end if;
-- 2021_11_01set table_name_str = concat(next_year,'_',next_month_str,'_',next_month_day_str);
-- 拼接create sql语句set@create_table_sql = concat(
'create table user_',
table_name_str,
'(`uid` INT ,`uname` varchar(50) ,`information` varchar(50)) COLLATE=\'utf8_general_ci\' ENGINE=InnoDB');
-- FROM后面不能使用局部变量!prepare create_table_stmt FROM@create_table_sql;
execute create_table_stmt;
DEALLOCATEprepare create_table_stmt;
set t_index = t_index +1;
end while;
end $$
delimiter ;
call proc22_demo();
selectyear(date_add(now(),INTERVAL1month))
select dayofmonth(LAST_DAY(date_add(now(),INTERVAL1month)));
事务SQL
create database if notexists mydb12_transcation;
use mydb12_transcation;
-- 创建账户表createtable account(
id intprimary key, -- 账户id
name varchar(20), -- 账户名
money double-- 金额
);
-- 插入数据insertinto account values(1,'zhangsan',1000);
insertinto account values(2,'lisi',1000);
-- 设置MySQL的事务为手动提交(关闭自动提交)select @@autocommit;
set autocommit =0;
-- 模拟账户转账-- 开启事务begin;
update account set money = money -200where name ='zhangsan';
update account set money = money +200where name ='lisi';
-- 提交事务commit;
-- 回滚事务rollback;
select*from account;
-- 查看隔离级别show variables like'%isolation%';
-- 设置隔离级别/*
set session transaction isolation level 级别字符串
级别字符串:read uncommitted、read committed、repeatable read、serializable
*/-- 设置read uncommittedset session transaction isolation level read uncommitted;
-- 这种隔离级别会引起脏读,A事务读取到B事务没有提交的数据-- 设置read committedset session transaction isolation level read committed;
-- 这种隔离级别会引起不可重复读,A事务在没有提交事务之前,可看到数据不一致-- 设置repeatable read (MySQ默认的)set session transaction isolation level repeatable read;
-- 这种隔离级别会引起幻读,A事务在提交之前和提交之后看到的数据不一致-- 设置serializableset session transaction isolation level serializable;
-- 这种隔离级别比较安全,但是效率低,A事务操作表时,表会被锁起,B事务不能操作。-- SQL的优化insertinto account values(3,'wangwu',1000);
-- 查看当前会话SQL执行类型的统计信息show session status like'Com_______';
-- 查看全局(自从上次MySQL服务器启动至今)执行类型的统计信息showglobal status like'Com_______';
-- 查看针对InnoDB引擎的统计信息show status like'Innodb_rows_%';
-- 查看慢日志配置信息show variables like'%slow_query_log%';
-- 开启慢日志查询setglobal slow_query_log =1;
-- 查看慢日志记录SQL的最低阈值时间,默认如果SQL的执行时间>=10秒,则算慢查询,则会将该操作记录到慢日志中去show variables like'%long_query_time%';
select sleep(12);
select sleep(10);
-- 修改慢日志记录SQL的最低阈值时间setglobal long_query_time =5;
-- 通过show processlist查看当前客户端连接服务器的线程执行状态信息show processlist;
select sleep(50);
-- ----------------explain执行计划-------------------------create database mydb13_optimize;
use mydb13_optimize;
-- 1、查询执行计划
explain select*fromuserwhere uid =1;
-- 2、查询执行计划
explain select*fromuserwhere uname ='张飞';
-- 2.1、id 相同表示加载表的顺序是从上到下
explain select*fromuser u, user_role ur, role r where u.uid = ur.uid and ur.rid = r.rid ;
-- 2.2、 id 不同id值越大,优先级越高,越先被执行。
explain select*from role where rid = (select rid from user_role where uid = (select uid fromuserwhere uname ='张飞'))
-- 2.3/
explain select*from role r ,
(select*from user_role ur where ur.uid = (select uid fromuserwhere uname ='张飞')) t where r.rid = t.rid ;
索引SQL
-- 分布函数- CUME_DIST/*
用途:分组内小于、等于当前rank值的行数 / 分组内总行数
应用场景:查询小于等于当前薪资(salary)的比例
*/
use mydb4;
select
dname,
ename,
salary,
cume_dist() over(orderby salary) as rn1,
cume_dist() over(partitionby dname orderby salary) as rn2
from employee;
/*
rn1:
3 / 12 = 1/4 = 0.25
5 / 12 = 0.4166666666666667
rn2:
1 / 6 = 0.1666666666666667
3 / 6 = 0.5
*/-- percent_rank/*
用途:每行按照公式(rank-1) / (rows-1)进行计算。其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数
应用场景:不常用
*/select
dname,
ename,
salary,
rank() over(partitionby dname orderby salary desc) as rn,
percent_rank() over(partitionby dname orderby salary desc) as rn2
from employee;
/*
rn2:
第一行: (1 - 1) / (6 - 1) = 0
第二行: (1 - 1) / (6 - 1) = 0
第三行: (3 - 1) / (6 - 1) = 0.4
*/-- 前后函数-LAG和LEAD/*
用途:返回位于当前行的前n行(LAG(expr,n))或后n行(LEAD(expr,n))的expr的值
应用场景:查询前1名同学的成绩和当前同学成绩的差值
*/select
dname,
ename,
salary,
hiredate,
lag(hiredate, 1, '2000-01-01') over(partitionby dname orderby hiredate ) as time1,
lag(hiredate, 2) over(partitionby dname orderby hiredate ) as time2
from employee;
select
dname,
ename,
salary,
hiredate,
lead(hiredate, 1, '2000-01-01') over(partitionby dname orderby hiredate ) as time1,
lead(hiredate, 2) over(partitionby dname orderby hiredate ) as time2
from employee;
-- 头尾函数-FIRST_VALUE和LAST_VALUE/*
用途:返回第一个(FIRST_VALUE(expr))或最后一个(LAST_VALUE(expr))expr的值
应用场景:截止到当前,按照日期排序查询第1个入职和最后1个入职员工的薪资
*/select
dname,
ename,
salary,
hiredate,
first_value(salary) over(partitionby dname orderby hiredate ) asfirst,
last_value(salary) over(partitionby dname orderby hiredate ) aslastfrom employee;
-- 其他函数-NTH_VALUE(expr, n)、NTILE(n)/*
NTH_VALUE(expr,n)
用途:返回窗口中第n个expr的值。expr可以是表达式,也可以是列名
应用场景:截止到当前薪资,显示每个员工的薪资中排名第2或者第3的薪资
*/select
dname,
ename,
salary,
hiredate,
nth_value(salary,2) over(partitionby dname orderby hiredate ) as second_salary,
nth_value(salary,3) over(partitionby dname orderby hiredate ) as third_salary
from employee;
-- NTILE/*
用途:将分区中的有序数据分为n个等级,记录等级数
应用场景:将每个部门员工按照入职日期分成3组
*/select
dname,
ename,
salary,
hiredate,
ntile(3) over(partitionby dname orderby hiredate ) as nt
from employee;
-- 取出每一个部门的第一组员工select*from (
select
dname,
ename,
salary,
hiredate,
ntile(3) over(partitionby dname orderby hiredate ) as nt
from employee
)t
where t.nt =1;
create database mydb5;
use mydb5;
-- 方式1-创建表的时候直接指定createtable student(
sid intprimary key,
card_id varchar(20),
name varchar(20),
gender varchar(20),
age int,
birth date,
phone_num varchar(20),
score double,
index index_name(name) -- 给name列创建索引
);
select*from student where name ='张三';
-- 方式2-直接创建-- create index indexname on tablename(columnname);create index index_gender on student(gender);
-- 方式3-修改表结构(添加索引)-- alter table tablename add index indexname(columnname)altertable student add index index_age(age);
-- 1、查看数据库所有索引-- select * from mysql.`innodb_index_stats` a where a.`database_name` = '数据库名’;select*from mysql.`innodb_index_stats` a where a.`database_name` ='mydb5';
-- 2、查看表中所有索引-- select * from mysql.`innodb_index_stats` a where a.`database_name` = '数据库名' and a.table_name like '%表名%’;select*from mysql.`innodb_index_stats` a where a.`database_name` ='mydb5'and a.table_name like'%student%';
-- 3、查看表中所有索引-- show index from table_name;show index from student;
-- 删除索引/*
drop index 索引名 on 表名
-- 或
alter table 表名 drop index 索引名
*/drop index index_gender on student;
altertable student drop index index_age;
-- 索引的操作-创建索引-单列索引-唯一索引/*
唯一索引与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
*/-- 方式1-创建表的时候直接指定createtable student2(
sid intprimary key,
card_id varchar(20),
name varchar(20),
gender varchar(20),
age int,
birth date,
phone_num varchar(20),
score double,
unique index_card_id(card_id) -- 给card_id列创建索引
);
-- 方式2-直接创建-- create unique index 索引名 on 表名(列名)createtable student2(
sid intprimary key,
card_id varchar(20),
name varchar(20),
gender varchar(20),
age int,
birth date,
phone_num varchar(20),
score double
);
createunique index index_card_id on student2(card_id);
-- 方式3-修改表结构(添加索引)-- alter table 表名 add unique [索引名] (列名)altertable student2 addunique index_phone_num(phone_num);
-- 操作-删除索引drop index index_card_id on student2;
altertable student2 drop index index_phone_num;
-- 主键索引show index from student2;
-- 组合索引
use mydb5;
-- 创建索引的基本语法-- 普通索引-- create index indexname on table_name(column1(length),column2(length));create index index_phone_name on student(phone_num,name);
-- 操作-删除索引drop index index_phone_name on student;
-- 创建索引的基本语法-- 唯一索引createunique index index_phone_name on student(phone_num,name);
/*
1 a
1 b
2 a
1 a 不行
*/select*from student where name ='张三';
select*from student where phone_num ='15100046637';
select*from student where phone_num ='15100046637'and name ='张三';
select*from student where name ='张三'and phone_num ='15100046637';
/*
三条sql只有 2 、 3、4能使用的到索引idx_phone_name,因为条件里面必须包含索引前面的字段 才能够进行匹配。
而3和4相比where条件的顺序不一样,为什么4可以用到索引呢?是因为mysql本身就有一层sql优化,他会根据sql来识别出来该用哪个索引,我们可以理解为3和4在mysql眼中是等价的。
*/*/show variables like'%ft%';
use mydb5;
-- 创建表的适合添加全文索引createtable t_article (
id intprimary key auto_increment ,
title varchar(255) ,
content varchar(1000) ,
writing_date date-- ,-- fulltext (content) -- 创建全文检索
);
insertinto t_article values(null,"Yesterday Once More","When I was young I listen to the radio",'2021-10-01');
insertinto t_article values(null,"Right Here Waiting","Oceans apart, day after day,and I slowly go insane",'2021-10-02');
insertinto t_article values(null,"My Heart Will Go On","every night in my dreams,i see you, i feel you",'2021-10-03');
insertinto t_article values(null,"Everything I Do","eLook into my eyes,You will see what you mean to me",'2021-10-04');
insertinto t_article values(null,"Called To Say I Love You","say love you no new year's day, to celebrate",'2021-10-05');
insertinto t_article values(null,"Nothing's Gonna Change My Love For You","if i had to live my life without you near me",'2021-10-06');
insertinto t_article values(null,"Everybody","We're gonna bring the flavor show U how.",'2021-10-07');
-- 修改表结构添加全文索引altertable t_article add fulltext index_content(content)
-- 添加全文索引create fulltext index index_content on t_article(content);
-- 使用全文索引select*from t_article wherematch(content) against('yo'); -- 没有结果select*from t_article wherematch(content) against('you'); -- 有结果select*from t_article where content like'%you%';
createtable shop_info (
id intprimary key auto_increment comment 'id',
shop_name varchar(64) notnull comment '门店名称',
geom_point geometry notnull comment '经纬度',
spatial key geom_index(geom_point)
);
约束SQL
-- 1:通过修改表结构添加主键/*
create table 表名(
...
);
alter table <表名> add primary key(字段列表);
*/
use mydb1;
-- 添加单列主键createtable emp4(
eid int,
name varchar(20),
deptId int,
salary double
);
altertable emp4 addprimary key(eid);
-- 添加多列主键createtable emp5(
eid int,
name varchar(20),
deptId int,
salary double
);
altertable emp5 addprimary key(name, deptId);
-- 删除主键-- 1.删除单列主键altertable emp1 dropprimary key;
-- 2.删除多列主键altertable emp5 dropprimary key;
use mydb1;
-- 自增正约束createtable t_user1 (
id intprimary key auto_increment,
name varchar(20)
);
insertinto t_user1 values(NULL,'张三');
insertinto t_user1(name) values('李四');
deletefrom t_user1; -- delete删除数据之后,自增长还是在最后一个值基础上加1insertinto t_user1 values(NULL,'张三');
insertinto t_user1(name) values('李四');
truncate t_user1; -- truncate删除之后,自增长从1开始insertinto t_user1 values(NULL,'张三');
insertinto t_user1(name) values('李四');
-- 指定自增长的初始值-- 方式一:创建表时指定createtable t_user2 (
id intprimary key auto_increment,
name varchar(20)
)auto_increment =100;
insertinto t_user2 values(NULL,'张三');
insertinto t_user2 values(NULL,'张三');
deletefrom t_user2;
insertinto t_user2 values(NULL,'张三');
insertinto t_user2 values(NULL,'张三');
truncate t_user2; -- truncate删除之后,自增长从1开始insertinto t_user2 values(NULL,'张三');
insertinto t_user2 values(NULL,'张三');
-- 方式二:创建表之后指定createtable t_user3 (
id intprimary key auto_increment,
name varchar(20)
);
altertable t_user3 auto_increment =200;
insertinto t_user3 values(NULL,'张三');
insertinto t_user3 values(NULL,'张三');
-- 非空约束/*
MySQL 非空约束(NOT NULL)指字段的值不能为空。对于使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统就会报错。
*/-- 格式/*
方式1:<字段名><数据类型> not null;
方式2:alter table 表名 modify 字段 类型 not null;
*/
use mydb1;
-- 1. 创建非空约束-方式1,创建表时指定createtable mydb1.t_user6 (
id int ,
name varchar(20) notnull, -- 指定非空约束
address varchar(20) notnull-- 指定非空约束
);
insertinto t_user6(id) values(1001); -- 不可以insertinto t_user6(id,name,address) values(1001,NULL,NULL); -- 不可以insertinto t_user6(id,name,address) values(1001,'NULL','NULL'); -- 可以(字符串:NULL)insertinto t_user6(id,name,address) values(1001,'',''); -- 可以(空串)-- 2.创建非空约束-方式2,创建表之后指定createtable t_user7 (
id int ,
name varchar(20) , -- 指定非空约束
address varchar(20) -- 指定非空约束
);
altertable t_user7 modify name varchar(20) notnull;
altertable t_user7 modify address varchar(20) notnull;
desc t_user7;
-- 3.删除非空约束-- alter table 表名 modify 字段 类型altertable t_user7 modify name varchar(20) ;
altertable t_user7 modify address varchar(20) ;
-- 唯一约束/*
唯一约束(Unique Key)是指所有记录中字段的值不能重复出现。例如,为 id 字段加上唯一性约束后,每条记录的 id 值都是唯一的,不能出现重复的情况。
*/-- 语法:/*
方式1:<字段名> <数据类型> unique
方式2:alter table 表名 modify 字段 类型 not null;
*/
use mydb1;
-- 1. 添加唯一约束-方式1-创建表时指定createtable t_user8 (
id int ,
name varchar(20) ,
phone_number varchar(20) unique-- 指定唯一约束
);
insertinto t_user8 values(1001,'张三',138);
insertinto t_user8 values(1002,'张三2',139);
insertinto t_user8 values(1003,'张三3',NULL);
insertinto t_user8 values(1004,'张三4',NULL); -- 在MySQL中NULL和任何值都不相同 甚至和自己都不相同-- 2. 添加唯一约束-方式1-创建表之后指定-- 格式:alter table 表名 add constraint 约束名 unique(列);createtable t_user9 (
id int ,
name varchar(20) ,
phone_number varchar(20) -- 指定唯一约束
);
altertable t_user9 addconstraint unique_pn unique(phone_number);
insertinto t_user9 values(1001,'张三',138);
insertinto t_user9 values(1002,'张三2',138);
-- 3. 删除唯一约束-- 格式:alter table <表名> drop index <唯一约束名>;altertable t_user9 drop index unique_pn;
-- 默认约束-- 1.创建默认约束/*
方式1: <字段名> <数据类型> default <默认值>;
方式2: alter table 表名 modify 列名 类型 default 默认值;
*/
use mydb1;
-- 方式1-创建表时指定createtable t_user10 (
id int ,
name varchar(20) ,
address varchar(20) default'北京'-- 指定默认约束
);
insertinto t_user10(id,name,address) values(1001,'张三','上海');
insertinto t_user10 values(1002,'李四',NULL);
-- 方式2-创建表之后指定-- alter table 表名 modify 列名 类型 default 默认值;createtable t_user11 (
id int ,
name varchar(20) ,
address varchar(20)
);
altertable t_user11 modify address varchar(20) default'深圳';
insertinto t_user11(id,name) values(1001,'张三');
-- 2.删除默认约束-- alter table <表名> change column <字段名> <类型> default null;altertable t_user11 modify address varchar(20) defaultnull;
insertinto t_user11(id,name) values(1002,'李四');
-- 零填充约束(zerofill)-- 1. 添加约束createtable t_user12 (
id int zerofill , -- 零填充约束
name varchar(20)
);
insertinto t_user12 values(123, '张三');
insertinto t_user12 values(1, '李四');
insertinto t_user12 values(2, '王五');
-- 2.删除约束altertable t_user12 modify id int;
-- 总结-- 1:通过修改表结构添加主键约束createtable emp4(
eid intprimary key,
name varchar(20),
deptId int,
salary double
);
-- 2:添加自增正约束createtable t_user1 (
id intprimary key auto_increment,
name varchar(20)
);
-- 3:创建非空约束createtable mydb1.t_user6 (
id int ,
name varchar(20) notnull, -- 指定非空约束
address varchar(20) notnull-- 指定非空约束
);
-- 4:创建唯一约束createtable t_user8 (
id int ,
name varchar(20) ,
phone_number varchar(20) unique-- 指定唯一约束
);
-- 5:创建默认约束createtable t_user10 (
id int ,
name varchar(20) ,
address varchar(20) default'北京'-- 指定默认约束
);
JDBC操作
drop database if exists mydb16_jdbc;
create database if notexists mydb16_jdbc;
use mydb16_jdbc;
createtable if notexists student(
sid intprimary key auto_increment,
sname varchar(20),
age int
);
insertinto student values(NULL,'宋江',30),(NULL,'武松',28),(NULL,'林冲',26);
select*from student;
-- 防止SQL注入createtable if notexistsuser(
uid intprimary key auto_increment,
username varchar(20),
password varchar(20)
);
insertintouservalues(NULL,'zhangsan','123456'),(NULL,'lisi','888888');
-- SQL注入droptable if existsuser;
createtableuser(
uid intprimary key auto_increment,
username varchar(20),
password varchar(20)
);
insertintouservalues(NULL, 'zhangsan','123456'),(NULL,'lisi','888888');
SQL优化
use mydb13_optimize;
CREATETABLE tb_user
(
id int(11) NOTNULL AUTO_INCREMENT,
username varchar(45) NOTNULL,
password varchar(96) NOTNULL,
name varchar(45) NOTNULL,
birthday datetime DEFAULTNULL,
sex char(1) DEFAULTNULL,
email varchar(45) DEFAULTNULL,
phone varchar(45) DEFAULTNULL,
qq varchar(32) DEFAULTNULL,
status varchar(32) NOTNULL COMMENT '用户状态',
create_time datetime NOTNULL,
update_time datetime DEFAULTNULL,
PRIMARY KEY (id),
UNIQUE KEY unique_user_username (username)
) ;
-- 1、首先,检查一个全局系统变量 'local_infile' 的状态, 如果得到如下显示 Value=OFF,则说明这是不可用的showglobal variables like'local_infile';
-- 2、修改local_infile值为on,开启local_infilesetglobal local_infile=1;
-- 3、加载数据-- 结论:当通过load向表加载数据时,尽量保证文件中的主键有序,这样可以提高执行效率/*
脚本文件介绍 :
sql1.log ----> 主键有序
sql2.log ----> 主键无序
*/-- 主键有序 -22.617s
load data local infile 'D:\\sql_data\\sql1.log'intotable tb_user fields terminated by',' lines terminated by'\n';
truncatetable tb_user;
-- 主键无序-81.739s
load data local infile 'D:\\sql_data\\sql2.log'intotable tb_user fields terminated by',' lines terminated by'\n';
-- 关闭唯一性校验SET UNIQUE_CHECKS=0;
truncatetable tb_user;
load data local infile 'D:\\sql_data\\sql1.log'intotable tb_user fields terminated by',' lines terminated by'\n';
SET UNIQUE_CHECKS=1;
select*from tb_user
-- 优化order by语句CREATETABLE `emp` (
`id` int(11) NOTNULL AUTO_INCREMENT,
`name` varchar(100) NOTNULL,
`age` int(3) NOTNULL,
`salary` int(11) DEFAULTNULL,
PRIMARY KEY (`id`)
) ;
insertinto `emp` (`id`, `name`, `age`, `salary`) values('1','Tom','25','2300');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('2','Jerry','30','3500');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('3','Luci','25','2800');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('4','Jay','36','3500');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('5','Tom2','21','2200');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('6','Jerry2','31','3300');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('7','Luci2','26','2700');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('8','Jay2','33','3500');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('9','Tom3','23','2400');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('10','Jerry3','32','3100');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('11','Luci3','26','2900');
insertinto `emp` (`id`, `name`, `age`, `salary`) values('12','Jay3','37','4500');
-- 创建组合索引create index idx_emp_age_salary on emp(age,salary);
-- 排序,order by
explain select*from emp orderby age; -- Using filesort
explain select*from emp orderby age,salary; -- Using filesort
explain select id from emp orderby age; -- Using index
explain select id,age from emp orderby age; -- Using index
explain select id,age,salary,name from emp orderby age; -- Using filesort-- order by后边的多个排序字段要求尽量排序方式相同
explain select id,age from emp orderby age asc, salary desc; -- Using index; Using filesort
explain select id,age from emp orderby age desc, salary desc; -- Backward index scan; Using index-- order by后边的多个排序字段顺序尽量和组合索引字段顺序一致
explain select id,age from emp orderby salary,age; -- Using index; Using filesortshow variables like'max_length_for_sort_data'; -- 4096show variables like'sort_buffer_size';
-- 优化limitselectcount(*) from tb_user;
select*from tb_user limit 0,10;
explain select*from tb_user limit 900000,10; -- 0.684
explain select*from tb_user a, (select id from tb_user orderby id limit 900000,10) b where a.id = b.id; -- 0.486
explain select*from tb_user where id >900000 limit 10;
drop index idx_emp_age_salary on emp;
explain select age,count(*) from emp groupby age;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了