mysql基础

概念

存储引擎

MYISAM

它不支持事务,访问速度非常快,对事务完整性没有要求或者以select,insert为主的应用基本都可以使用这个引擎来创建表

每个MyISAM在磁盘上存储成三个文件,其中文件名和表名都相同,但是扩展名分别为

  • .frm()存储表定义
  • MYD(MYData,存储数据)
  • MYI(MYIndex,存储索引)

INNODB

innoDB存储引擎提供了具有提交,回滚和崩溃回复能力的事物安全.但是对比MyISAM的存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引

MEMORY

memory使用存在内存中的内容来创建表.每个MEMORY表实际对应一个磁盘文件,格式是.frm

MEMORY类型的表访问非常快,因为它的数据是放在内存中的,并且默认使用HASH索引,但是一旦服务关闭,表中的数据就会丢失,但表还会继续存在

sql

SQL是结Structured Query Language构化查询语言的缩写

sql是专为数据库建立的操作命令集,是一种概念齐全的数据库语言

  • DDL:数据定义语言-用来定义数据库对象:创建库,表,列等
  • DML:数据操作语言-用来操作数据库表中的记录
  • DQL:数据查询语言-用来定义数据
  • DCL:数据控制语言-用来定义访问权限和安全级别

sql数据类型

mysql支持多种类型,大致可分为三类,数值类型,字符串类型,日期和时间类型

常用数据类型

  • double:浮点型,例如double(5,2)最多表示5位,其中必须有俩位小数,及最大值为999.99
  • cahr:固定长度字符串类型:char(4) 'abc '即使没有占用到指定位数多余的也会空出来
  • varchar:可变长度字符串类型varchar(4)'abc'
  • text:字符串类型
  • blob:二进制类型
  • date:日期类型,格式为YYY-MM-dd
  • time时间类型,格式为hh:mm:ss
  • datetime:日期时间类型yyy-MM-dd hh:mm:ss

在mysql中字符串类型和日期类型都要用单引号括起来

sql

连接数据库mysql -uroot -p123456,

DDL

数据定义语言-用来定义数据库对象:创建库,表,列等

建立表

create table 表名(
    列名 列的类型 [约束],
    列名2 列的类型 [约束]
);
create table student(
    id BIGINT,
    stu_name VARCHAR(50),
    stu_age int
);

添加一列

alter table 表名 add 列名 列的类型
alter table student add stu_gender TINYINT

修改一列

alter table 表名 modify 字段名 数据类型
alter table student modify stu_name varchar (30)

修改表名

rename table 原始表名 to 要修改的表名
rename table student to newstu

修改表的字符集

alert table 表名 character set 字符集名称
alter table student character set utf8

修改表的列名

alter table 表名 change 原始列名 新列名 数据类型
alter table student change stu_name s_name VARCHAR(30)

查看表的信息

desc表名
desc student

查看表创建的细节(完整语句)

show create table 表名
show create table student 

删除一列

alter table 表名 drop 字段名
alter table student drop stu_gender

删除表

drop table 表名
drop table student

DML

DML是对表中的数据进行增删改的操作

插入

inset into 表名 (列名1,列名2)value(列值1,列值2)

注意事项

  • 列名与列值的类型个数顺序要一一对应.
  • 值不要超出列定义的长度
  • 插入的日期和字符都一样,都使用括号引起来
-- insert into student (id,stu_name,stu_age) value (3,'wc',2) -- 插入一条
-- insert into student (id,stu_name,stu_age)values(2,'qwq',20),(34,'请问',213) -- 插入多条.
insert into student value(1,'qq',10) -- 可以不写,但必须写齐全

更新

update 表名 set 列名1=列值1,列名2=列值2 where 列名=值

-- update student set stu_score =90 -- 修改全部的内容(没有指定where)
-- update student set stu_score = 0 where id=1; -- 修改id为1全部内容
update student set stu_age =stu_age+1 where id=1

修改数据库密码

mysql8之前

use mysql;
-- 修改mysql中的用户表,name=root host=localhost的记录
update mysql.user set authentication_string=password('123456')where user='root' and Host='localhost';
-- 刷新mysql相关的权限表
flush privileges; 

mysql8

alter user 'root'@'localhost' identified by '新密码' -- sql修改
mysqladmin -u root -p password 1234 -- mysqladmin命令修改

删除

-- delete from student where id=1 -- 删除一条记录
-- delete from student -- 删除整张表
truncate table student -- 删除整张表,并且不能指定条件

delete删除表中的数据,表结构还在

truncate删除是把表直接drop掉,然后创建一个同样的新表,执行速度比delete快

比较明显的区别是delete之后表中的主键自增是从之前一个开始的,而truncate是重新从0开始的

DQL

数据查询语言

select * from student; -- 查询表的全部数据

数据执行dql语句不会对数据进行改变而是让数据库发送结果集给客户端

结果集:ton过查询语句查询出来的数据以表的形式展示给我们成这个表为虚拟结果集.存放在内存中.查询返回的结果集是一张虚拟表

select id,stu_age from student -- 查询指定的结果

条件查询

条件查询就是在查询给时给出where字句,在where字句中科院使用一些运算符以及关键字

关键字

  • = (等于) !=(不等于) <>(不等于) <(小于) <=(小于等于) >(大于) >=(大于等于)
  • between...and 值在什么范围内
  • in(set)
  • is null (为空) is not null(不为空)
  • and 与
  • or 或
  • not 非
-- select id,stu_age from student where id=2 and stu_name='qwq' -- 用and连接必须要都满足才可以
-- select id,stu_age from student where id=1 or id=2 -- 用or连接满足一个即可
-- select * from student where stu_name is null -- 查询全部stu_name为空的记录
-- select * from student where stu_name is not null -- 查询stu_name不为空的记录
-- select * from student where stu_score != 90 -- 查询stu_score不等于90的记录
-- select * from student where stu_age >=1 and stu_age <=100 -- 查询年龄1-100之间的记录
select * from student where stu_age between 1 and 100  -- 查询年龄1-100之间的记录

模糊查询

根据指定的关键字进行查询,使用like关键字后跟通配符

通配符

  • _ :任意一个字符
  • %:任意多个字符
-- 查询姓名由3个字符构成的学生记录
-- select * from student where stu_name like '___';
-- 查询姓名3个字母构成,并且第2个位w的学生记录
-- select * from student where stu_name like '_w_'
-- 查询姓名以q开头的学生记录
-- select * from student where stu_name like 'q%'
-- 查询姓名包含q的学生
-- select * from student where stu_name like '%q%'
-- 查询姓名中第二个字母为w的学生记录
select * from student where stu_name like '_w%'

字段控制查询

-- select distinct id,stu_name from student -- 查询姓名并去重
-- select *,stu_age+stu_score from student -- 对俩个字段进行相加并新增一列返回结果
 -- 相加,如果值为null就把值设置为0,并把新返回的一列别名为sum
 select *,IFNULL(stu_age,0)+IFNULL(stu_score,0) as sum from student

排序

对查询的结果进行排序

关键字order by 排序类型:

  • 升序ASC:从小到大(默认)
  • 降序DESC:从大到小
-- select * from student stu_age order by stu_age desc -- 查询数据根据age降序排列
-- select * from student stu_age order by stu_age  -- 查询数据根据age升序排列
-- 先根据年龄降序排列,在根据成绩升序排列
select * from student stu_age order by stu_age desc,stu_score 

聚合函数

创建一个表

/*
Navicat MySQL Data Transfer

Source Server         : itlike
Source Server Version : 50720
Source Host           : localhost:3306
Source Database       : itlike

Target Server Type    : MYSQL
Target Server Version : 50720
File Encoding         : 65001

Date: 2019-04-12 09:58:35
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `dep_id` int(11) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `salary` decimal(10,2) DEFAULT NULL,
  `cus_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of employee
-- ----------------------------
INSERT INTO `employee` VALUES ('1', '鲁班', '1', '10', '1000.00', '1');
INSERT INTO `employee` VALUES ('2', '后裔', '1', '20', '2000.00', '1');
INSERT INTO `employee` VALUES ('3', '孙尚香', '1', '20', '2500.00', '1');
INSERT INTO `employee` VALUES ('4', '凯', '4', '20', '3000.00', '1');
INSERT INTO `employee` VALUES ('5', '典韦', '4', '40', '3500.00', '2');
INSERT INTO `employee` VALUES ('6', '貂蝉', '6', '20', '5000.00', '1');
INSERT INTO `employee` VALUES ('7', '孙膑', '6', '50', '5000.00', '1');
INSERT INTO `employee` VALUES ('8', '蔡文姬', '30', '35', '4000.00', '1');

对查询的结果进行统计算

  • count():统计指定列不为null的记录行数
  • max():计算指定列的最大值,如果指定的是字符串列,那么使用字符串排序运算
  • min():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算
  • sum():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0
  • avg计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0

count

-- select count(dep_id) from employee -- 查询数据条数 不会有为null的记录被统计进去
-- select count(*) from employee where age >20 -- 查询年龄大于20的总人数
-- select count(*)from employee where age+salary>2000 -- 查询年龄和工资大于2000的人数
select count(age),count(name)employee from employee -- 统计姓名和年龄有效的数据量,会返回俩组数据
-- select sum(salary),sum(age) from employee -- 查询全部人的年龄和工资总和
-- select sum(salary+age)FROM employee -- 查询全部人的年龄加上工资的总和
-- select avg(salary) from employee -- 求收入的平均值
-- select max(salary) from employee -- 求最高收入
select min(salary) from employee -- 求最低收入

分组查询

select age from employee GROUP BY age

根据age字段来分组,当group by单独使用时,只显示出每一组第一条记录

所以group by 单独使用时的意义不大

-- 根据年龄进行分组,查出分组下的对于name
select age,group_concat(name) from employee GROUP BY age

在使用分组的时候,select直接跟的字段一般都出现在group by之后

group by+group_concat()

group_concat(字段名)可以作为一个输出字段来使用

表示分组后,根据分组结果,使用group_concat()来放置每一组的某字段值的集合

配合聚合函数使用

-- 查出全部分组的各个薪资,并且算薪资的总和
select age,group_concat(salary),sum(salary) from employee GROUP BY age

having

用来分组查询后制定一些条件来输出查询结果

having作用和where一样,但having只能用于group by

-- 查出全部分组的各个薪资,并且算薪资的总和,显示过滤掉总和大于4000的数据
select age,group_concat(salary),sum(salary) from employee GROUP BY age
having sum(salary)>4000

having与where的区别

  • having是在分组之后对数据进行过滤
  • where是在分组前对数据进行过滤
  • having后面可以使用分组函数(统计函数)where不能
  • where是对分组前记录的条件,如果某行记录没有满足where子句的条件,那么这行记录不会参与分组;而having是对分组后数据的约束

limit分页

从哪一行开始查,查到哪一条

-- select * from employee limit 5; -- 从第一条开始取五条

select * from employee limit 3,5 -- 从第3条开始取五条(角标为0)

sql语句编写顺序是

select->from-?where->group by->having->orderby->limit

数据完整性

什么是数据完整性:保证用户输入的数据保存到数据库中是正确的.

如何添加数据完整性:在创建表的时候给表添加约束

完整性分类:实体完整性,与完整性,引用完整性

实体完整性

什么是实体完整性:表中的每一行代表一个实体

作用:表示每一行数据不重复.行级约束

约束类型:主键约束(primary key),唯一约束(unique),自动增长列(auto_increment)

主键约束:

每个表中药有一个主键,数据唯一不能为null,

create table 表名(字段1 数据类型 primary key,字段2 数据类型);
create table 表名(字段1 数据类型,字段2 数据类型,primary key(要设置主键的字段));
create table 表名(字段1 数据类型,字段2 数据类型,primary key(主键1,主键2)) -- 设置联合主键


create table person( 
    ID BIGINT primary key,
    name varchar (50)
)

联合主键:俩个字段数据相同时,才违反联合主键约束

先创建表,再去修改表,添加主键

alter table person add constraint primary key(id)

唯一约束

特点:指定的列数据不能重复可以为空值

create table 表名(字段名1 数据类型,字段名2 数据类型 unique)

自动增长列

特点:指定的数据自动增长,即使数据删除还是从删除的序号继续往下

格式:create table 表名(字段名 数据类型 primary key auto_increment,字段 数据类型 unique)

create table person(
    id int primary key auto_increment,
    name varchar(20) unique
)

域完整性

使用:限制词单元格的数据正确,不对找刺裂的其他单元格比较,域代表的是当前单元格

域完整性约束

  • 数据类型约束:数值类型,日期类型,字符串类型
  • 非空约束(not null):不能为空
  • 默认值约束(default):字段不填写时的默认值

非空约束与默认值

create table 表名(字段名 数据类型 primary key auto_increment,字段2 数据类型 unique not null)

create table person(
    id int primary key auto_increment,
    name varchar (20) unique not null, # 设置唯一索引不能为空
    gender char(1) default '男' #默认值
)

参照完整性

是指标之间的一种对应关系,通常情况下,可以通过设置俩张表之间的主键外键,或者编写俩表的触发器来实现

由对应参照完整性的俩张表格,在对他们进行数据插入,更新删除的过程中,系统都会讲被修改表格与另一张表格进行对照,从而阻止一些不正确的数据操作

数据库的主键和外检类型一定要一致

俩个表必须要是innodb类型

设置参照完整性之后,外键当中的内值,必须得是主键当中的内容

一个表设置当中的字段设置为主键,设置主键的为主表

create table 表名(
    字段名 类型,
    字段名2 类型2
    constraint 外检名 foreign key (当前表的外键) references 管理的主表(主表关联的字段)
)


create table task (
    id int primary key auto_increment,
    user_id int, 
    data varchar(30),
    constraint u_id foreign key (user_id) references user(id)
)

以上方法创建的外检 在主表更新的时候或主表被修改的时候,默认值是restric

一共四种分别为

  • CASCADE:主表数据被删除后,对应从表的关联数据也被删除
  • RESTRICT:如果从表有关联数据,主表记录不允许被删除,必须先删除总表中的关联数据之后,才能删除主表数据(默认)
  • set null :主表删除数据之后,对应从表中的关联数据外检自动设置为null,前提是该字段允许为null

no action 在mysql中no action与RESTRICT相同添加外键约束

alter table 表名 add constraint 约束名 foregin key(从表列名) references 主表(主表列名)
ON DELETE RESTRICT ON UPDATE RESTRICT; -- 这行的意思是设置在删除的时候,也一起删除
alter table task add constraint u_id foreign key(user_id) references user(id);

查询

多表查询

合并结果集查询

union与union all

union:合并时去除重复记录,union:合并时不去除重复记录

select * from 表1 union select * from 表2
select * from 表1 union all select * from 表2

注意:被合并的俩个结果列数,列类型必须相同

笛卡尔集

笛卡尔集这词经常出现于数据库多表查询中。

例 A={1,2},B={0,1}

A×B={(1,0),(1,1),(2,0),(2,1)},

B×A={(0,1),(0,2),(1,1),(1,2)},

这样的查询就会产生笛卡尔集

select * from 表名1,表名2

用这样的方式可以避免笛卡尔集

select * from user,task  where user.id=task.user_id

别名的方式

select * from user u,task t  where u.id=t.user_id
#效果相同,相同的方法也可以给查询的列明来进行重命名
select * from user as u,task as t  where u.id=t.user_id 

连接查询

内连接

俩个表同时满足的值才显示

select * from 表名1 inner join 表名2 on 表名1.字段名=表名2.字段名

select * FROM user inner JOIN task on user.id=task.user_id

查询不强制要求表与表之间建立主外检的关系,外检约束只能约束增删改

在连接查询后面还有更多的条件可以在后面写where,和and

左连接

俩表满足条件相同的数据查出来,如果左边表当中有不相同的数据,也把左边表当中的数据查出来

select * from 表名1 left join 表名2 on 表名1.字段名=表名2.字段名

select * FROM user left JOIN task on user.id=task.user_id
右连接

俩表满足条件相同的数据查出来,如果右边表当中有不相同的数据,也把右边表当中的数据查出来

select * from 表名1 right join 表名2 on 表名1.字段名=表名2.字段名

select * FROM user right JOIN task on user.id=task.user_id
多表连接查询
select * from 关联表1
inner join 表1 on 表1.字段=关联表.字段  
inner join 表2 on 表2.字段=关联表.字段;
或
select * from 表1
inner join 关联表 on 表1.字段=关联表.字段  
inner join 表2 on 表2.字段=关联表.字段;
自然连接

连接查询会产生无用的笛卡尔集,我们通常使用主外键关系等式来去除它,然而自然连接无需你去给出主外键等式,他会自动找到这一等式,也就说不用写条件

select * from user natural join task;

子查询

一个select语句中包含一个完整的select语句或俩个以上select,那么就是子查询了

子查询出现的位置:where后,把select查询出的结果当做另一个select的条件值,from后把查询出的结果当做一个新表

放在where之后

select * from 表1 where 字段=(另一个查询语句,需要返回单个结果)
select * from user where id=(select user_id from task where id=1) 

放在from之后

select * from (查询语句) 别名 条件字句

select * from (select * from user) t where id=1

函数

事先提供好的一些功能可以直接使用,函数可以在select语句及其字句也可以用在update和delete语句当中

字符串

  • concat(s1,s2...sn):将传入的字符连接成一个字符串,任何字符串与null进行连接的结果都是null
  • insert(str,x,y,inetr):将字符串str从x位置开始,y个字符张的子串替换为指定的字符
  • lower(str)和right(str)字符串转成小写或者大写
  • left(str,x)和right(str,x),分别返回字符串最左边的x个字符和最右边的x个字符,如果第二个参数为null,那么不返回任何字符
  • lpad(str,n,pad)和rpad(str,n,pad)用字符串pad对str最左边或最右边进行填充,直接到长度为n个字符的长度
  • ltrim(str)和rtrim(str)去掉字符串中最左边和最右边的空格
  • trim(str)去掉字符串左右的空格
  • repeat(str,x)返回str重复x次的结果
  • replace(str,a,b):用字符串b替换字符串str中出现的字符串a
  • substring(str,x,y)返回字符串stx中第x位置起y个字符长度的字符

数值

  • abs(x)绝对值
  • ceil(x):向上取整,如1.1会变成2
  • floor(x)向下取整,如1.8会变成1
  • mod(x,y)返回x/y的余数
  • rand():返回0-1内容的随机值(可以用乘法)

时间和日期

  • curdate():返回当前日期,只包含时分秒
  • curtime();返回当前时间,只包含时分秒
  • now()返回当前日期和时间,年月日时分秒都包含
  • unix_timestamp();返回当前日期的时间戳,从1970往后的毫秒数
  • from_unixtime(unixtime)将一个时间戳转换成日期类型
  • week(date)返回当前是一年中的第几周
  • year(date)返回所给的日期是哪一年
  • hour(time)返回当前时间的小时
  • minute(time)返回当前时间的分钟
  • date_format(date,fmt)按字符串格式化日期date值
  • date_add(date,interval expr type)计算日期间隔
  • datediff(date1,date2)计算俩个日期相差的天数

流程控制

if(value,t,f)如果value是真,返回去t,否则返回f

select if (2>3,'true','false') 返回false0

ifnull(value,value2):如果value不为空,返回value1,否则返回value2

case when then end

其他常用

  • database()返回当前数据库名
  • version()返回当前数据库版本
  • user()返回当前登录用户
  • password(str)对str进行加密
  • md5返回str的md5值

存储过程

存储过程是一组可编程的函数,是为了完成特定的功能的sql语句,存储过程就是具有名字的一段代码,用来完成特定的给你,创建的存储过程保存在数据库的数据字典中

将重复性很高的一些操作,封装到一个存储过程中,简化了对这些sql的调用

能做批量处理,统一接口确保数据的安全

相对于oracle数据库来说,mysql的存储过程相对功能较弱,使用较少

delimiter

它与存储过程语法无关,delimtter语句将标准风格付 分号(;)改为$$,因为我们想将存储过程作为整体传递给服务器,而不是让mysql工具依次解释每个语句

告诉mysql解释器,该段命令语句结束了,mysql是否可以执行了.默认情况下 delimiter是分号,在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该,命令.但有时候,不希望mysql这么做,在为可能输入较多的语句且语句中包含有分号.使用delimiter $$,这样只有当$$出现之后,mysql解释器才会执行这段语句

操作

创建

creeate procedure 名称()
begin
语句
end$$

call 名称();调用存储过程


delimiter $$ 
CREATE PROCEDURE show_user() #设置存储过程的名称
BEGIN
select * from user; 
END$$ #存储过程结束
delimiter;
call show_user();
  • 查看所有存储过程show procedure status;
  • 查看指定数据库中的存储过程 show procedure status where db ='数据库名'
  • 查看存储过程源码show create procedure 名称
  • drop procedure 存储过程名称删除存储过程

变量

  • 在存储过程中声明变量declare 变量名 数据类型(大小) default 默认值
  • 同时声明多个的方法 declare x,y int default 0;
  • 设置变量 set x=3;set y=4;
  • 使用select into将查询的结果分配给一个变量 select count(*)into变量名 from 表名
  • 范围:如果存储过程中声明一个变量,那么当达到存储过程的end语句时,它将超出范围,因此在其他代码块中无法访问

参数

定义参数 create procedure 函数名(in 字段名 类型,out 字段名2 类型)out代表输出的参数,类似返回值

使用根据传入的值搜索task.data为传入的值的结果

delimiter $$
create procedure getName(in name varchar(255))
begin
select * from task where datas=name;

end$$
delimiter;
call getName('1qq1')

有返回值的根据传入的值搜索task.data为传入的值的结果的id

delimiter $$
create procedure tid(in name varchar(255),out ret int)
begin
select id into ret from task where datas=name;

end$$
delimiter ;

call tid('1qq1',@d);
select @d

inout可以传入参数,也可以作为返回值

delimiter $$
create procedure tid(in name varchar(255),inout ret int)
begin
select id into ret from task where datas=name;

end$$
delimiter ;

set @d=20;
call tid('1qq1',@d);
select @d 

自定义函数:create function rand_str(n int)returns varchar(255)

索引

索引用于快速找出在某个列中特有的一行,不使用索引,mysql必须从第一条记录开始读完整个表,知道找出相关行,表越大,查询数据所花费的时间就越多,如果表中有一个索引,mysql能够快速达到一个位置去搜索数据文件.而不必查看所有数据,那么将会节省很大一部分空间

mysql索引的5种类型:主键索引唯一索引普通索引,空间索引全文索引

  • 主键索引:primary key
  • 唯一索引:unique
  • 普通索引:index或normal
  • 全文索引:fulltext
  • 空间索引:spatial

索引方法

普通查询会逐条遍历数据,而索引会对数据进行排序

索引方法有俩种btree和hash innomardb只能使用btree

b+数索引

b+数是一个多平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且统计的节点之间有指针互相连接

hash索引

hash索引就是采用一定的哈希算法,兼职换算成新的哈希值,检索时不需要类似b+数那样从根节点到叶子节点逐一查找,只需要一次哈希算法即可定位到响应的位置,速度非常快

hash索引的结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不想b-tree索引需要从根节点刀子节点,最后才能访问到叶子节点这样多次的io访问,所以hash索引的查询效率要远高于b-tree索引,但只有MEMORY引擎才能使用hash索引,所以一般用的比较少

Last modification:November 17, 2023
如果觉得我的文章对你有用,请随意赞赏