Mysql详解

Posted 星辰安安

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql详解相关的知识,希望对你有一定的参考价值。

数据库分类

关系型:以行作为记录,列数相同
非关系型:以列作为记录,行数随便

数据库层级

服务器->数据库->表(行列组成的二维表格)->行

数据类型

1、整数类型,包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别表示1字节、2字节、3字节、4字节、8字节整数
2、实数类型,包括FLOAT、DOUBLE、DECIMAL。
3、字符串类型,包括VARCHAR、CHAR、TEXT、BLOB。字符串使用单引号。
4、枚举类型(ENUM),把不重复的数据存储为一个预定义的集合。
5、日期和时间类型,尽量使用timestamp,空间效率高于datetime,

SQL语句:每个命令执行结束加分号结束

查询所有数据库:show databases;
切换数据库:use 库命名;
创建数据库:create database [IF NOT EXISTS] 库名;
删除数据库:drop database [IF EXISTS] 库名;
查询数据库创建:show 建库语句;
指定数据库采用的字符集:CHARACTER SET
注意:不要修改mysql服务器的编码集,表的编码集默认和库一致

建表

格式:
create table [if exists] 表名(
字段1 数据类型 字段属性,
字段2 数据类型 字段属性,…
字段N 数据类型 字段属性 )engine=引擎 default charset=编码集;

查看当前数据库:select database();
查看建表语句:show create table 表名;
查看表结构:desc 表名;
删除:drop table [if exists] 表名;

字段属性:

not null:字段非空,没给值数据为默认值(varchar默认值为空)
AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1
PRIMARY KEY关键字用于定义列为主键,您可以使用多列来定义主键,列间以逗号分隔
ENGINE 设置存储引擎,
CHARSET 设置编码
default null:没给值数据就是null
default 值:设置字段的默认值
注意:主键是不重复的列

修改表结构

修改表名:alter table 旧表名 rename to 新表名;
添加字段:alter table 表名 add 字段 字段数据类型 属性;
删除字段:alter table 表名 drop 字段
修改字段:alter table 表名 change 旧字段 新字段 数据类型 属性;
修改字段:alter table 表名 modify 字段 数据类型 属性;
注意:
change:修改所有(字段名,数据类型,属性)
modify:修改一部分(数据类型,属性)
修改数据类型时,varchar->int原数据会变为0

增删改查

增:
格式: insert into 表名(字段) values(值),(值)…(值);
例如:
insert into stduent(name) values(‘zs’);
insert into stduent(name)values(‘zs’),(‘ls’);


格式: delete from 表名 where 子句;


格式: update 表名 set 字段1=值1,字段2=值2…字段N=值N where 子句;


格式: select 字段 from 表名 where 子句;
注意: *表示所有字段

as起别名
格式: 字段 as 名称
注意: as 也加可不加

子句:

> < <= >= = <> 大于、小于、大于(小于)等于、不等于
between …and… 显示在某一区间的值(含头含尾)
in(set) 显示在in列表中的值,例:in(100,200)只能匹配100或200
like ‘张_’ 模糊查询 使用% 和 _(%表示匹配所有 _匹配一个)
Is null 判断是否为空
is not null 判断是否不为空
and 多个条件同时成立
or 多个条件任一成立
not 不成立,例:where not(expection>10000);

limit分页

格式:
语句 limit 开始下标,长度;
如果数据量不够,显示全部
例如:从下标为0开始显示10条
select * from stduents limit 0,10;

去重

格式:
DISTINCT 字段1,字段2…字段N
注意:
字段不能在DISTINCT之前,只能在DISTINCT后面
DISTINCT之后有多个字段,按照所有字段进行去重

聚合函数:

count(字段):求多少行数据
sum(字段):求和
avg(字段):平均数
max(字段):最大值
min(字段):最小值
注意:
varchar能比较大小,不能获取avg(没有任何意义)
如果值为Null不参与计算
sum和avg字段的数据不是数值,结果都是0

字段进行算术运算

格式:
(字段 符号 字段)
例如: select (name+age) from students;
注意:
字符串参与运算(字符串为0)

拼接:

格式:
concat(str1,str2…)
例如:把name和age以-拼接显示
select concat(name,’-’,age)from students;
格式:
concat_ws(separator,str1,str2,…)
例如:把name和age以-拼接显示
select concat_ws(’-’,name,age)from students;

日期函数

获取当前日期:
current_timestamp;–所有
current_timestamp();–所有
CURRENT_DATE();-- 年月日
CURRENT_DATE;-- 年月日
CURRENT_TIME();-- 时分秒
CURRENT_TIME;-- 时分秒

时间转str
格式:
date_format(date,format)
str转日期
格式:
str_to_date(str,formaat)

日期相减

格式:
datediff(expr1,expr2);
注意:只能相减年月日,时分秒参与运算结果为null

函数向日期添加指定的时间间隔

格式:
DATE_ADD(date,INTERVAL expr unit);
date:时间
INTERVAL:关键字
expr:间隔的数值
unit:年月日时分秒(…,…,day,…,…,…)

数值计算

round(x,d):四舍五入 x:值 d:保留几位小数点

ceil(x):向上取整
floor(x):向下取整
rand():随机数(0-1之间)

排序

格式:
order by 字段1 asc|desc,字段2 asc|desc…字段n asc|desc;
例如:按照age进行降序排列,age相同按照id进行降序排列
select * from students order by age desc,id desc;
注意: 默认升序asc,降序desc 如果有多个字段,按照先后顺序依次排序

分组

格式:
group by 字段1,字段2…字段n;
注意:
多个字段,按照所有字段进行分组(一起分组)
有多少组显示多少条数据(默认情况下,没有经过条件筛选)
每组显示的数据为每组中默认第一条数据
gruop by通常和聚合函数一起使用

筛选:where having

区别:
1.having可以使用聚合函数where不可以
2.having是在分组后对数据进行过滤,where是在分组前

TopN问题

1.TopN
age最大的前三个
select * from students order by age desc limit 0,3;

2.分组Top1
按sex分组后,求分组中年龄最大的一个
1.select * from students where age in (select max(age) m from students group by sex);
2.select * from students as stu1 where age=(select max(age) from students as stu2 where stu1.sex=stu2.sex);

3.分组TopN
按sex分组后,求分组中年龄最大的三个
select * from students as stu1 where 3>(select count(*) students as stu2 where stu1.sex=stu2.sex and stu1.age<stu2.age);

mysql三大范式

1.原子性:字段不可再分割
2.唯一性:字段依赖于主键
3.冗余性:数据量过大

连表联查

union:结果集进行合并(纵向合并)
格式: 查询语句 union 查询语句
注意:
查询列数必须相同
字段为第一个sql语句的字段
union默认去重
union all不去重

left join(以左表为基准关联右表中的数据)
格式: select * from 左表 left join 右表 on 关联条件;
注意:
左表匹配不到右表,以null不全
右表匹配不到左表,不显示

right join(以右表为基准关联左表中的数据)
格式: select * from 右表 left join 左表 on 关联条件;
注意:
左表匹配不到右表,不显示
右表匹配不到左表,以null不全

inner join(求两张表的交集)
格式: select * from 右表 inner join 左表 on 关联条件;
注意:
关联条件可写可不写
如果不写可以写为select * from 表1,表2 where 子句;

条件判断

if
格式: if(条件,为true的结果,为false的结果)

case when
格式:
case when 条件 then 为true的结果 [when 条件 then 为true的结果] [else 为false的结果] end

从其他表加载数据

格式1:
create table 表名 as 查询语句;
格式2:
insert into 表名 查询语句;
注意:字段属性和数据类型和其他表保持一致

视图:由查询结果得到的一张虚拟表(临时表,虚表),虚拟表和基本表有一对一和一对多的关系

创建:
create view 视图名称 as 查询语句
一对一(数据和基本表一样):增删改查
一对一(数据由基本表聚合):查
一对多(数据由基本表聚合):查
一对多(数据来自于连表联查):查改
注意:
虚拟表不存储任何数据,数据存储在基本表中,基本表当中数据发生改变虚拟表中的数据也能发生改变

创建视图,查询语句中不能出现子查询(不能作为一张表,可以作为结果进行筛选),把子查询作为视图之后再创建视图

错误创建方式

CREATE VIEW v_user_role AS 
SELECT ur.user_id , ur.role_id  ,u.user_name
from t_user_role ur 
left join t_user u on ur.user_id = u.user_id

正确创建方式

CREATE VIEW v_user_role AS 
SELECT ur.user_id , ur.role_id  ,u.user_name
FROM  (t_user_role ur 
LEFT JOIN t_user u ON ur.user_id = u.user_id)

查询视图结构:

desc 视图名称;
show create view/table 视图名称;

删除视图:

drop view 视图名称;

执行计划

在sql语句前加上explain命令可以查看执行计划

from–where–group by–having–select–order by
from:需要从哪个数据表检索数据
where:过滤表中数据的条件
group by:如何将上面过滤出的数据分组
having:对上面已经分组的数据进行过滤的条件
select:查看结果集中的哪个列,或列的计算结果
order by :按照什么样的顺序来查看返回的数据

索引

添加:
alter table 表名 add index 索引名称(字段);
删除: alter table 表名 drop index 索引名称;
注意:
每个字段都可以添加索引 主键默认含有索引
不要每个字段都添加索引(索引也需要消耗资源),只需要给常用字段添加索引

事务:批处理,保证多个sql语句一起执行成功或一起执行失败(回滚撤销当前操作)

开始事务: begin;
回滚事务: rollback;
提交事务: commit;
结束事务: end;

注意:没有commit或end之前,事务中的所有操作都是临时的(在缓存中的)
commit或end之后,把这些临时的(在缓存中的)数据提交到原始数据中进行修改
end默认执行commit;

shell操作mysql

#!/bin/sh
	MYSQL="mysql -hmaster -uroot -p123456"
	sql="select * from shujia.student where sex='0'"
	result="$($MYSQL -e "$sql")"
	echo  "$result"

java操作mysql

导入第三方工具包
		file->project structure->Modules->Dependencies->+->JARs or dir...->选择包->apply

	1.加载第三方工具
		Class.forname("com.mysql.jdbc.Driver");
	2.获取连接
        String url="jdbc:mysql://master:3306/shujia";
        String username="root";
        String password="123456";
        Connection connection = DriverManager.getConnection(url, username, password);
    3.获取执行器 createStatement(会出现sql注入不使用)和prepareStatement
    	PreparedStatement ps = connection.prepareStatement(sql);//给sql的格式(模板)
        ps.setString(1,"1012");
        ps.setString(2,"test");
    4.获取结果(sql语句为增删改查操作,不需要解析结果,使用executeUpdate())
    	ResultSet rs = ps.executeQuery();
        while (rs.next())
            String name = rs.getString("name");
            System.out.println(name);
        
    5.关闭连接(从下向上关闭)
    	rs.close();
    	ps.close();
    	conn.close();

sql注入:参数中有mysql命令,而mysql把这些关键字当做命令去执行

prepareStatement:避免了sql注入,首先发送sql的格式,然后在传递参数(参数中有关键字也作为参数执行)
prepareStatement传参:通过set数据类型(int prepareIndex,数据类型 x)
注意:index从1开始

创建连接和关闭需要写很多次,可以把连接和关闭写入到工具类中,再次使用时,直接调用工具类,避免多次书写创建连接和关闭

public class JDBCUtil 
    private static String driver="com.mysql.jdbc.Driver";
    private static String url="+

    +";
    private static String username="root";
    private static String password="123456";
    static 
        try 
            Class.forName(driver);
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        
    
    //获取连接的方法
    public static Connection getConnection() throws Exception 
        Connection conn = DriverManager.getConnection(url, username, password);
        return conn;
    
    public static void closeAll(PreparedStatement ps,Connection conn)throws Exception
        ps.close();
        conn.close();
    
    public static void closeAll(ResultSet rs,PreparedStatement ps, Connection conn)throws Exception
        rs.close();
        ps.close();
        conn.close();
    

创建资源目录和文件

1.创建普通目录(建议名称为 resource)
2.通过project st…设置为资源目录
3. 创建文件,格式必须后缀为properties

以上是关于Mysql详解的主要内容,如果未能解决你的问题,请参考以下文章

MySQL order by关键字详解,order by排序

MySQL中是不是有只支持时分秒 时间的数据类型

MySQL日期格式化 yyyy-mm-dd 详解 DATE_FORMAT() 函数

MySQL日期格式化 yyyy-mm-dd 详解 DATE_FORMAT() 函数

java像Mysql数据库添加数据Date时间没有时分秒?

mysql中一个字段升序,另一个字段降序