Mysql数据库

MySQL数据库

1.常见命令

cmd:

mysql -u root - p

net start mysql

net stop mysql

2.数据类型

数字:int double(7,2)整数和小数最大位数,小数位数

字符:

char(10) 长度固定

varchar(10)长度可变 10为最长长度

日期 :

date(yyyy-MM-dd)

datetime(yyyy-MM-dd HH:mm:ss)

timestamp(yyyyMMddHHmmss)

3.创建表/约束

列级约束、表级约束

create table student(
    -- 主键约束
    sid int(4) primary key auto_increment,
    -- 非空且唯一
    sname varchar(40) not null unique ,
    -- 检查约束
    sex char(1) check (sex in('男','女')),
    birthday date,
    -- 外键约束
    -- 引用的列必须是主键或具有唯一约束
    cid int references classes(classid)
);

4.增删改

show tables;
select * from student;
--添加
insert into student values(9,'刘一水','男','1976-09-11',6);
--给部分列添加
insert into student (sname,sex,cid) values('谢梅','女',5)
--修改
update student set birthday = '1978-01-23' where sid=10;
--删除
delete from student where sid = 10;

5.查询

-- 查询基础
    select ename,jo,sal,deptno from emp;
    select ename,jo,sal,deptno where sal>2000;

SQl操作符

算数运算符
select sal*12 from emp;
select 2+3;
select 11%4 from dual; -- dual是一张虚拟表(可写可不写)
-- div取整数部分 
select 10/3;-- 3.3333
select 10 div 4;-- 3
-- mod和%结果一致
关系运算符
-- !=和<>表示不等于
select * from emp where deptno<>30;
select * from emp where deptno!=30;
逻辑运算符
-- and or not && || not
-- 查询薪资大于2000或工作为CLERK的员工信息
select * from emp where sal>2000 or job='CLERK';
-- XOR 逻辑异或
-- 规则: 有一个为null,结果则为null 
-- 两边值不同,结果为1,两边值相同,结果为0
select 5>3 xor 8<10; -- 结果0
select 5>3 xor null; -- 结果null

基本查询

去重
-- 去除重复行 distinct
-- 查询emp表中工种
select distinct job from emp;
select distinct deptno,job from emp;
别名
select sal*12 年薪 from emp;
-- 查询没有提成的员工信息
-- is null/is not null
select * from emp where comm is null;
-- 计算年薪
-- ifnull(column,0) 如果column不为null,结果就是该值,如果是null,结果为0
select ename 员工姓名,(sal+ifnull(comm,0))*12 年薪 from emp;
模糊查询
-- _ 匹配一个字符
-- % 匹配任意个字符
select * from emp where ename like 'S%';
-- 查询名字第三位为M的员工信息
select * from emp where ename like '__M%';
--查询名字中有M的员工信息
select * from emp where ename like '%M%';

正则匹配

regexp或rlike

-- 查询名字为4个字母的员工
select * from emp where ename regexp '^[A-Z]{4}$';
-- 查询名字以M开头的员工
select * from emp where ename rlike '^M';

in

select * from where ename in('ename1','ename2','ename3','ename4');

区别between A and B

-- 两头都包含
select * from emp where al between 1100 and 3000;
排序

使用order by子句进行排序,升序asc、降序desc。

-- 单列排序
-- 按照薪资升序排列
select * from emp order by sal;
select * from emp order by sal asc;
-- 按照薪资降序排列
select * from emp order by sal desc;
-- 多列排序
-- 按照第一个列进行排序,如果第一个列内容相同,则按第二个列进行排序
-- 每一个列可以单独指定排序方式
select * from emp order by sal desc,ename;
-- 按照别名排序
select ename 员工姓名,(sal+ifnull(comm,0))*12 年薪 from emp order by 年薪 desc;
复制
--  复制一张表,目标表不存在
creat table emp1 as select * from emp;
select * from emp1;
delete from emp1;
-- delete表还在 drop全删

-- 复制一张表,目标表存在
insert into emp1 select * from emp where sal>2000;
-- 注意:查询数据的列要和原表的列匹配
insert into emp1 select empno,ename,job,sak,deptno from emp where sal>2000;

-- union 对查询结果集的操作
insert into emp1 select * from emp where sal>2000 union
 select * from emp where ename rlike '^M';

常用函数

1.字符函数

lower(char),upper(char)

-- 将字符串转化为小写
select lower('ABC');
select lower(ename) from emp;

length(char)/char_length(char)

-- 返回字符串长度
select ename,length(ename) from emp;

**substr(str,pos,len) **

substring(str,pos,len)

mid(str,pos,len)

下标从1开始,最后一位下标-1

str 源字符串

pos 起始位置

len 截取长度(可省略)

-- 截取字符串
select substr('hello world',3,3);-- llo
select substr('hello world',-4,3);-- orl

**replace(str,old,new) **

-- 字符串的替换
select replace('zcripture clazzicz','z','s');

insert(str,pos,len,new)

-- 用新字符串替换一段旧字符串
select insert('hello oracle数据库',7,6,'MySQL');

concat(str1,str2,str3,…,strn)

-- 拼接字符串
select concat('hello','','world');
select concat('你好',ename) from emp;

space(n)

-- 由n个空格拼成的字符串
select concat('***',space(5),'***');

instr(str,sub,str)

-- 字串在原字符串中第一次出现的位置
select instr('abcdefcdrt','cd'); --3

format(x,d)

x——源数字,一般为double类型

d——小数位数,不能省略

-- 保留d位小数,四舍五入取整
select format(3.14159269793,3);-- 3.142

trim(str)

-- 返回源字符串去掉左右两边空格的副本
select concat ('***',trim('  abc  xyz    '),'**');
-- ***abc  xyz**

综合使用

-- 将姓名首字母大写,其余小写
select concat(substr(ename,1,1),lower(substr,2)) from emp;
2.数学函数

mod(m,n)

-- 求模
select mod(11,4);
select 11%4;

floor(n)

ceil(n)

-- 向上取整
select ceil(-2.567);-- -2

rand(n) 返回0-1间随机整数

-- 获取20-50之间的随机整数
select floor(30*rand()+20);-- 可以取到20 取不到50
-- 随机乱序
select * from emp order by rand();

pow(x,y)

-- 求x的y次幂
select pow(2,10); --1024

round(x[,d])

-- 保留d位小数,四舍五入取整
-- d小数位数,可以省略
select round(3.141592);-- 3

truncate(x[,d])

-- truncate(x[,d]) 保留d位小数,舍掉其余部分,不四舍五入
select truncate(3.1415926,4);
3.时间函数
-- 获取当前时间
select now(),sysdate(),current_timestamp();

-- curdate()、current_date获取年月日
select curdate(),current_date();

-- curtime()、current_time、current_time 获取时分秒
select curtime(),current_time(),current_time;

-- adddate(date,days|interval expr unit) 时间计算
-- date_add(date,interval expr unit)
select adddate(now(),10);-- 10天以后
select adddate(now(),interval 80 hour);-- 80小时以后
select adddate(now(),interval '5 8'day_hour);-- 5天8小时以后


-- datediff(date1,date2) 计算日期的差值
select datediff(now(),'2021-06-11');-- 相差天数

-- date(date) 提取年月日
-- time(date) 提取时分秒
select date(now()),time(sysdate());

-- week(date) 提取date在当年的第几周
select week(sysdate());

-- day(date),dayofmonth(now()) 一个月的第几天
select day(now()),dayofmonth(now());

-- dayofweek(date) 星期几
select dayofweek(now());

-- last_day(date) date所在月份的最后一天
select last_day(now());

综合实例

-- 显示入职时间超过38年的员工
select * from emp where adddate(hiredate,interval 38 year)<now();
4.转换函数

字符串和数字可以自动转换

-- date_format(date,format) 将日期类型转换为一定格式的字符串
select date_format(now(),'%Y/%m/%d %H:%i:%s');
select date_format(now(),'%Y/%m/%d %T');

-- str_to_date(str,format) 将时间字符串转换为datetime类型
-- str 要和format的格式保持一致,否则结果为null
select str_to_date('2021-09-15 12:34:27','%Y-%m-%d %T');
5.条件判断函数
-- if(expr,v1,v2) expr为true,结果为v1,expr为false,结果为v2
select ename,sal,if(sal>2500,'高工资','低工资') from emp;

-- ifnull(v1,v2) 如果v1不为null,结果为v1,如果v1为null,结果为v2
6.信息系统函数
-- version();查看系统版本号

-- connection_id();查看当前用户的连接数

-- user();

-- charset(str);
7.加密函数

md5(str);

sha(str);

高级查询

1.聚合函数

普通列不能和聚合函数一起查询

-- max(column) min(column)
select max(sal)最高薪资,min(sal)最低薪资 from emp;

-- count(*) 查询结果的所有行
-- count(column) 查询结果该列不为null的行数
-- count(distinct column) 查询结果该列相异值的数量
select count(*) from emp where sal>2000;
-- 统计有提成的员工的数量
select count(comm) from emp;
-- 查询有多少工种
select count(distinct job) from emp;

-- sum(column) 求和
-- avg(column) 求平均
select sum(sal) 总薪资,round(avg(sal),2) 平均薪资 from emp;

聚合函数除了count(),其余都忽略null值

2.分组查询
-- 分组查询
select cid ,round(avg(score),1) from stuscore group by cid;

-- 多列分组
select stuid,cid,round(avg(score),1) 平均成绩 from stuscore group by stuid,cid;

having 在分组之后进行条件筛选

where—>group by—>having—>order by

where后不能用别名 having可以

3.多表联结查询

多表联查时需要给表起别名,

如果没有给表起别名,使用别名.列名,

如果给表起了别名,必须使用别名.列名,否则会出错。

内联结
-- 两表联查
-- 方法一:
select s.sname,sc.*from student s
 inner join stuscore sc on s.stuid = sc.stuid;

-- 方法二:
select s.sname,sc.* from student s, stuscore sc 
where s.stuid = sc.stuid;

-- 三表联查
-- 方法一:
select s.sname,c.cname,sc.score from student s
  inner join stuscore sc on s.stuid = sc.stuid
  inner join course c on sc.cid = c.cid;

-- 方法二:
select s.sname,c.cname,sc.score from student s,course c,stuscore sc
  where sc.stuid = s.stuid and sc.cid = c.cid;
4.子查询

1.子查询的结果为一行一列,当作一个数值直接使用。

2.子查询是一列多行,使用关键字in。

3.子查询结果为一行多列,加小括号。

4.子查询结果为多行多列,当作一张新表。

-- 查询薪资比SCOTT低的员工信息
select * from emp where sal<
   (select sal from emp where ename='SCOTT');
5.合并查询

保证多个查询结果集的列必须一致

union: 合并去重

union all: 合并不去重

6.分页查询

limit start,count

satrt 起始行,从0开始,可以省略,默认为0

count 查询的行数

-- 查询6-10行
select * from emp limit 5,5;
7.SQL语句导入,导出
-- 导出数据
select * from emp where sal>2000 into outfile '路径';
-- 文件导入
load data infile '路径'into table emp1;

explain:分析sql语句查询计划。

6.数据库对象

1.索引

创建

-- 查看表索引
show keys from emp1;

-- 1.给job添加普通索引
create index job_index on emp1(job);

-- 2.给ename添加唯一索引
-- 某个列添加了唯一约束,系统会自动创建唯一索引
-- 如果该列没有唯一约束,可以单独添加唯一索引
create unique index ename_index on emp1(ename);
alter table emp1 add unique(ename);

-- 3.主键索引
-- 给列添加主键约束(primary key)时,系统会自动创建主键索引,不必重复设置

-- 4.全文索引(fulltext),只适用于char、vachar,text类型的列
creat fulltext index job_fulltext on emp1(job);

-- 5.组合索引,一次给多个列添加索引

添加索引时,如何选择具体哪一个索引:

1.该列是主键,自动会添加主键索引

2.如果该列值必须唯一,考虑添加唯一索引

3.如果该列是字符类类型,考虑添加全文索引

4.添加普通索引或组合索引

2.视图

视图和表的区别:

  • 表需要占用磁盘空间,视图不需要
  • 视图不能添加索引
  • 使用视图可以简化查询
  • 视图有利于提高安全性,比如不同用户查看不同的视图
-- view(视图)
-- 创建视图,各个部门的平均薪资
creat or replace view view_avgsal as select deptno,round(avg(sal),2)avgsal from emp group by deptno;
-- 可以像普通表一样查询视图
select * from view_avgsal;
-- 修改视图,修改视图对应的sql语句
alter view view_avgsal as select * from emp;
-- 修改视图名
rename table view_avgsal to avgsal;

3.事务

由一组相关的DML(增删改)语句组成,该组的DML语句要么全部执行成功,要么都不执行。

事务四大特性(ACID):

  • 原子性:不可分割
  • 一致性:事务开始时,数据库中数据一致,事务结束,数据也一致。
  • 隔离性:多个并发的事务可以独立运行,而不能互相干扰。
  • 持久性:事务提交后,数据库的变化就会永久的保留下来。
-- 事务(Transaction)
-- 事务执行完之后一定要提交,才能永久保存在数据库中
-- rollback,回退到最近的一次提交之后
update emp1 set sal = 2000 where empno = 7369;
-- 手动提交
commit;
-- 设置手动提交
set autocommit=0;
select @@autocommit;
select * from emp1;


隔离的四个级别:

  • READ UNCOMMITTED:读取未提交,可能产生脏读,不可重复读,幻读
  • READ COMMITTED:读取提交,可能产生不可重复读,幻读
  • REPEATABLE-READ:可重复读,默认的隔离级别,解决了幻读
  • SERIALIZABLE:可串行化 ,对表加锁,不允许多个事务同时操作同一张表,效率较低

read committed 读取提交,可能产生不可重复读

不可重复读:同一个事务中,相同的查询语句查询到的结果不同

锁的分类:

MySQL分为三类:全局锁,表级锁和行级锁

7.MySQL编程基础

变量

1.局部变量

定义在存储过程,函数,触发器begin/end语句块之间

declare v_name varchar(15) default '';
2.用户变量

不需要声明,直接使用

①set @num=1 或 set @num:=1

set @num=8;
set @num:=10;

②select @num:=18 或 select @num:=列 from 表名

注意:select可以直接查询变量的值

set可以使用=或:=,但是select必须用:=赋值

select @num:=100;
select @num:=sal from emp where ename = 'SCOTT';
3.全局变量
show variables like '%autocommit%';
4.会话变量

MySQL会将当前所有全局变量的值复制一份

-- 查看所有会话变量
show session variables;
-- 查看一个会话变量
sekect @@session var_name

语句

1.set

set 变量名 = 表达式;

set 变量名 := 表达式;

set 变量名1 = 表达式1,变量名2=表达式2;

2.select

select 表达式 into 变量 from 表名 --不产生结果集

select 会话变量:=表达式 --产生结果集

3.条件控制语句

游标

-- 用游标提取emp表中7788雇员的名称和职务
creat procedure findempbyempno()
begin
  -- 编码部分
  -- 定义变量
  declare V_name varchar(15);
  declare V_job varchar(10);
  -- 声明游标
  declare cur_emp cursor for select ename,job from emp where empno=7788;
  -- 打开游标
  open cur_emp;
  -- 提取数据
  fetch cur_emp into v_name,v_job;
  select concat('员工姓名:',v_name,'工作:',v_job);
  -- 关闭游标
  close cur_emp;
end;
 -- 调用存储过程
 call findempbyempno();
 
 
 -- 顺序显示emp表中雇员的编号、姓名、薪资、部门编号
 creat procedure pro_emp()
 begin
   -- 定义变量
   declare done int default 0;
   declare eno int;
   declare v_name varchar(15);
   declare v_sal decimal(7,2);
   declare v_deptno int unsigned;
   declare result varchar(2000) default '';
   declare cur_emp cursor for select empno,ename,sal,deptno from emp;
   --指定游标结束的标志
   declare continue handler for not found set done = 1;
   open cur_emp;
   -- 提取数据
   while done!=1 do
      fetch cur_emp into eno,v_name,v_sal,v_deptno;
      if done!=1 then
      set result = concat(result,'\r\n','编号:',eno,',姓名:',v_name,',薪资:',v_sal,',部门编号:',v_id);
   end if;
   end while;
   select result;
   -- 关闭游标
   close cur_emp;
end;
call pro_emp();

8.存储过程、函数和触发器

-- 存储过程 procedure
-- 使用过程输出emp表中的雇员编号为7788的姓名
create procedure pro_7788()
begin
   -- 定义变量
   declare v_name varchar(15);
   -- 将查询的值赋值给v_name
   select ename into v_name from emp where empno=7788;
   -- 输出变量的值
   select concat('编号为7788的雇员姓名:',v_name);
end;
-- 调用存储过程
call pro_7788;


-- 使用过程实现九九乘法表
create procedure pro_99()
begin
    declare i int default 1;
    declare j int default 1;
    declare result varchar(2000) default '';
    n1:loop
        set j=1;
        n2:loop
            if j<i then
                set result=concat(result,j,'x',i,'=',j*i,' ');
            else set result=concat(result,j,'x',i,'=',j*i);
            end if;
            set j=j+1;
            if j>i then leave n2;
            end if;
        end loop;
        if i<9 then
            set result=concat(result,'\r\n');
        end if;
        set i=i+1;
        if i>9 then leave n1;
        end if;
    end loop;
    select result;
end;
call pro_99();
drop procedure pro_99;

带参数的存储过程

存储过程的参数:

1.in 默认参数类型 可以省略

-- 创建一个过程,以雇员号为参数查询雇员的姓名和职位
creat procedure pro_findempbyo(eno int)
begin
   -- 定义变量
   declare v_name varchar(15);
   declare v_job varchar(10);
   select ename,job into v_name,v_job from emp where emp=eno;
   select v_name,v-job;
end;
call procedure pro_findempbyo(7369);

2.out

create procedure pro_findsalbyno(eno int,out vsal decimal(7,2))
begin
    select sal into vsal from emp where empno = eno;
end;
-- 调用
set @sal=0;
call pro_findsalbyno(7788,@sal);
select round(7788,@sal);

3.inout

-- 创建两个变量的值进行交换
create procedure pro_swap(inout num1 int,inout num2 int)
begin
    declare temp int default 0;
    -- 交换
    set temp = num1;
    set num1 = num2;
    set num2 = temp;
end;
set @n1=10;
set @n2=20;
call pro_swap(@n1,@n2);
select @n1,@n2;

自定义函数

-- 函数 function
-- 创建一个函数,以雇员号查询雇员的姓名
create function fun_findnamebyno(eno int)
returns varchar(15)
begin
    declare v_name varchar(15);
    select ename into v_name from emp where empno=eno;
    return v_name;
end;

存储过程和函数区别:

1.函数必须有声明返回值类型,存储过程没有。

2.函数必须返回一个和声明类型一致的值,存储过程无需返回任何值。

3.调用方式不同,函数使用select,存储过程使用call进行调用。

4.存储过程的参数有in,out,inout三种模式,函数一般只有in。

触发器

-- 触发器tigger
-- 在studet表建立触发器,在向student表中添加数据时触发
-- 将时间和学生信息存入logs表中
create tigger tri_student after insert
on student for each row
begin
-- 自动给logs表中添加一条数据
-- new 表示即将要添加的行
insert into logs(msg,createtime) values(new.sname,now());
end;
-- 触发触发器
insert into student values(6,'谢广坤');



-- 限制更改的薪资不能小于原来的薪资
create tigger tri_update_sal before update
on emp1 for each row
begin
-- new、old
-- 即将要修改的薪资 new.sal
-- 原来的薪资 用new.empno查询的薪资
-- declare v_sal decimal(7,2);
-- select sal into v_sal from emp1 where empno=new.empno;
-- 判断即将要要求的薪资是否小于原来的薪资
if new.sal<old.sal then
    -- 发起系统异常
    signal sqlstate '45008' set message_text='黑心老板!不允许降薪';
    end if;
end;

-- 限制每个部门下的员工数量不能超过5位
create tigger tri_deptcount after insert
on emp1 for each row
begin
declare v_count int default 0;
--查询即将要添加数据的部门的人数
select count(*) into v_count from emp1 where deptno=new.deptno;
-- 如果该部门人数大于等于5,发起异常
if v_count>=5 then
    signal sqlstate '450082' set message_text='部门已满员'; 
    end if;
end;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值