mysql

313 阅读16分钟

SQL语言(关键字是不区分大小写的,建议大写)

SQL结构化查询语言 Structured Query Language

1. DDL(Data Definition Language) 数据定义语言

用来创建、删除、修改数据库中的对象(表格、用户、索引、视图、存储过程、触发器)

create创建、drop删除、alter修改

2. DML(Data Manipulation Language)数据操作语言

用来操作数据库表格中的具体数据(信息)(CURD)

写数据:insert新增、delete删除、update修改

读数据:select查询

由于读数据的操作很多、很重要,所以有人给他单独起了一个名字DQL(Data Query language)数据查询语言

select、where条件、group by分组、having条件、order by排序

3. DCL(Data Control Language)数据控制语言

用来控制用户权限

赋予:grant 权限 to 用户

回收:revoke 权限,权限 from 用户

4. TPL(Transcation Process Language)事务处理语言

可以理解为多线程并发访问同一个文件资源 带来的安全问题

begin Transcation

commit提交、rollback回滚、save point A 保存还原点


DDL 数据定义语言

  1. 创建database
// 默认创建数据库,字符集有默认值,为latin1
// 当前数据库中的所有表格都按照这个字符集进行处理,不能存储中文
create database name; 

// 创建数据库的时候可以修改默认字符集,通常设置为utf8,注意中间没有杠
create database 数据库名 default character set = 'utf8';

// 查看数据库的默认字符集,默认为latin1,所以处理不了中文
select schema_name, default_character_set_name from information_schema.schemata where schema_name = "数据库名";

// 可以查看到数据库当中某个表的字符集
show table status from 数据库名 like '表名';

// 如果不想让数据库中所有的表格存储中文,只单纯的某一张表格需要中文,可以在创建表格的时候设置字符集
  1. 创建table
create table 表名(
    列名  数据类型(长度),
    列名  数据类型(长度),
    列名  数据类型(长度)
);

// 创建表格的时候设置字符集
create table 表名(
    列名  数据类型(长度),
    列名  数据类型(长度),
    列名  数据类型(长度)
) character set utf8 [collate utf8_general_ci];
// collate utf8_general_ci设置的是排序规则,

// utf8_general_ci是默认值,性能比较高,可能不太精确
// utf8_unicode_ci,性能表较低,扩展性好

// 查看表格的描述(即列名、列类型等,不显示表格的内容)
desc 表名;
  1. 数据库中的数据类型

按照存储数据的方式来分类:

  • 数值型

    • 整数:tinyint、smallint、mediumint、int(4字节、32bit)/integer、bigint
    • 小数:float(4字节)、double(8字节)、decimal、numeric

    float(m, n) 总共可以存储m位,小数点之后有n位
    m取值范围为1-65,n取值范围是0-30
    如果不写的话,默认情况下m是10,n是0

  • 字符串

    • char、varchar(可变字符串,variable)数据库里面所有的字符串类型用单引号
    • binary(二进制)、varbinary(可变二进制)
    • blob(二进制大文本)、text(正常字符大文本)
  • 日期/时间

    • date(日期)、time(时间)、datetime(日期&时间)、timestamp(时间戳)
  1. 修改表格结构
    1. 修改表格名字
    alter table 原表名 rename [to] 新表名;
    
    1. 修改原有的列(列名错了、列类型不对、列长度不够)
    alter table 表名 change 原列名 新列名 新类型 新长度;
    // 新列名、新类型、新长度都可以和原来的一样
    
    1. 新增一个列
    alter table 表名 add 新列名 新类型 新长度;
    
    1. 删除一个原有的列
    alter table 表名 drop 列名;
    
    1. 删除table、删除database
    drop table 表格名字;
    drop database 数据库名字;
    

DML 数据操作语言

操作的是表格中的数据信息

分类:写入信息、读取信息

1. 写入信息(数据库中的信息发生了真实的改变)

insert新增、delete删除、update修改

2. 读取信息(数据库中的信息没有发生改变 读取信息展示出来)DQL

select 查询

新增记录

insert into 表名(列名, 列名, 列名) values(值, 值, 值);
// 没写的列名默认为null

// 如果新增加全部表格的列,就不用写列了,省略表名后面的括号内容
// 但是要求值的顺序、类型、个数必须与表格中的列一致
insert into 表明 values(值,值,值,值);

// 也可以一条insert语句,新增多个记录
insert into 表名(列, 列) values(值, 值), (值, 值), (值, 值);

删除记录

delete from 表名 [where ...];

修改记录

update 表名 set 列=值 [, 列=值] [where ...];

查询记录

select 列, 列 from 表名 [where ...];

select * from 表名

// 可以修改查出的结果的列名,
select 列名 as 列名 from 表名

条件筛选

  1. 除了insert以外的其他三个语句都可以做筛选。where是一个关键字,拼接在除了insert语句以外的其他语句基本结构之后
    delete from 表 where
    update 表 set 列=值 where...
    select 列 form 表 where...;
  2. 筛选用来筛出符合条件的记录行数,并不是控制显示的列
  3. where后面按照某一个列或者是某一写条件进行筛选
  4. where后面具体怎么使用、连接什么东西?
  • 比较运算符:>、>=、<、<=、!=、=
  • 算数运算符:+、-、*、/
  • 逻辑运算符:and、or、not
    如果and和or同时出现的话,and的级别更高
  • [not] between and
    两边都是闭区间,只需要循环一次
  • [not] in (条件, 条件)
    满足其中一个条件
  • [not] like
    模糊查询:%代表0-n个字符,_代表1个字符(有且只有一个)
select * from student where chinese>=95 and english >=95;
// 数据库底层做的事情:
// 1. 解析SQL
// 2. 从表格中将全部数据都读取出来,放在数据库缓存,集合list
// 3. 将list集合做一个循环遍历,每一次拿到一个元素(一行记录)条件
        假设我们的表格有7行记录
        如果只写一个where条件
        执行7次循环就可以比较出来了
        
        如果有and连接不止一个条件
        先按照第一个条件先进性筛选
        在按照第二个条件再筛选
// 4. 如果以后再语句中使用了and,尽量将条件苛刻的写在前面,这样可以提高代码效率

排序

  1. 连接在查询语句之后的,先查出来,再排序
  2. 按照某一个列进行排序的
    order by 列
  3. 排序有两种方式:
    升序 asc 默认
    降序 desc
  4. 可以联合排序
    order by 列名 [升序/降序],[列名 升序/降序]

函数

mysql里面的返回值都是由返回值的

  1. 函数可以放置的位置?
  • 查询中用来显示的部分
select 函数(列) from 表格
  • 条件筛选后面
select 列 from 表格 where sal > 函数(值)
  1. 常用函数:按照功能来进行划分
  • 比较函数
    • ifnull(值) 是空值返回1,不是返回0
  • 数学函数(数值函数)
    • abs绝对值
    • floor向下取整
    • mod(5, 2)取余数
    • pow求次方
    • round()
  • 日期和时间
    • now()
    • yaer() month() day() week()
  • 控制流程函数(转换函数)
    • if(条件, 值1, 值2)
    • ifnull(值, val) 如果值为空,就显示val,否则正常显示值
  • 字符串函数
    • length()
    • concat()
    • substr()
    • instr()
    • replace()
    • upper()
    • lower()
    • ltrim() rtrim()
    • lpad() rpad()
    • reverse()
  • 分组函数(聚合函数)+ 分组条件
    • 去重复 distinct
      • distinct 列 如果有一样的列信息,将一样的信息合并。行数会减少,查询的每一个列。行数个数需要一致
      • distanct 列, 列 如果有两个以上的列,将两个以上或多个列的组合当作整体。如果整体有一样的信息,则才会去重复,否则就全部显示
    • count()
    • max()
    • min()
    • avg()
    • sum()
select count(列) from student group by classid;

查询student表个人中所有的18岁同学,都在哪个班级 先进行条件筛选,后分组 查询student表格中语文平均成绩高于90分的班级 先进性分组,然后再进行筛选(having) having 关键字的使用与where类似 优先级:where、 group by、having、order by

分组条件+分组函数查询

  1. 在查询之前需要先考虑,到底是先分组,还是先筛选条件 先筛选 后分组:where group 先分组 后筛选:group having
  2. 在查询的时候一旦分组了,行数会减少 想要展示的信息,个数需要与分组条件的个数一致

嵌套

一个完整的SQL语句中,嵌套了另一个完整的SQL语句

  1. 嵌套可以将查询的结果当作条件再次查询
  2. 可以将查询的最终结果当作一张表格,在表格的基础上再次查询 注意:再将结果当作表格的时候,需要将表格起别名
  3. 嵌套将某一个查询的结果当作条件的时候,表格可以不是一张,我们可以将另一张表格查询的信息,当作当前表格的条件

几个比较重要的关键字的使用

  • in 满足查询子集中的某一个即可 in后面的自己括号内,可以是常量固定值、也可以是通过另一条sql语句查询出来的结果 如下的三个使用起来与in类似,查询是否满足后面的子集中的条件 但是一下三个关键字的后面不允许写固定值,只允许写sql语句(只能通过嵌套来获取子集)
  • any 满足查询子集中的某一个即可
  • some 与any完全一致
  • all 满足查询自己种的全部才可以

集合操作:

union 并集 (oracle数据库有----> intersect交集 minus差集)

select tid, tname, tsex from teacher union select sid, sname, ssex from student;

  1. 要求是前后两个查询子集的列数必须是一致的
  2. 类型没有要求
  3. 拼接后显示的列名是前一个自己默认的列名
  4. 注意:union和union all的区别:
    • union合并后做去重的处理,性能表较慢。如果产生重复元素,记录的是第一次出现的那一行。
    • union all 将两个查询的字节直接做合并,不做任何处理,性能比较快。建议以后使用union all来进行合并处理

列的约束

  1. 主键约束(Primary Key) 主键约束要求当前的列不能为null 主键约束要求当前的列 值是唯一的,不能存在
alter table 表名 add constraint 约束名字 约束类型(列);
// 可以简写为:
alter table 表名 add primary key (classid);

// 添加了主键值之后若想要让主键自增,可以做相应的设计:
alter table 表名 modify classid int(4) auto_increment;
// 如果没有做起始值的说明,会从1开始
alter table 表名 auto_increment = 10;
// 删除主键约束
alter table 表名 drop primary key;
注意:删除主键约束以后,不重复的特性取消了,非空特想还在
alter table 表名 modify 列 int(4) null;
  1. 唯一约束 可以为表格中的某一个列添加唯一约束,唯一与主键类似 唯一约束表示的是列的值,不能重复,可以为空 唯一约束在表格中可以存在多个列
alter table 表名 add constraint 约束名 约束类型(列);
alter table myclass add constraint uk_myclass unique [key] (loc);
可以简写为:
alter table myclass add unique key(loc);    // 约束名默认为列名

// 删除唯一约束:
alter table myclass drop index 约束名;
  1. 非空约束 可以给表格中的某一列上添加非空约束 当前列的值不能为null
alter table 表名 modify 原列名 原类型 原长度 [not] null;
alter table myclass modify cname barchar(20) null;
  1. 外键约束(Foreign Key) 表格中可以有多个列被设置为外键约束,当前列的值可以为空,可以重复 但是当前列的值不能随便的填写,值取另外一张表格内寻找 外键是当前列的值受到另外一张表格某一列的影响。 另外一张表格的列,必须是唯一约束
alter table 表名字 add constraint fk_当前表_关联表 约束类型(列) references 另一个表(列);
alter table student add cosntraint fk_student_myclass foreign key(classid) references myclass(classid);

// 查看
show keys from 表;
desc 表;

// 删除外键约束
alter table 表名字 drop foreign key 外键名;
// 注意:通过上面的语句其实已经将外键约束删掉了;自动在当前表格内添加一个新的key;
// 需要再次手动将这个生成的key删掉,外键约束才真的删除干净。
alter table 表名 drop key 约束名字;

// 简写:
alter table student add foreign key(列) references 另一个表(列);
注意:按照默认的方式添加外键,外键的名字不是默认类名
alter table student drop foreign key student_ibfk_1;
alter table student drop key classid;
  1. 检查约束

列在存值的时候做一个细致的检查,范围是否合理等

alter table student add constraint ck_sage check(sage>15 and sage< 30);

在mysql里面不好用

表格之间的关系

  1. 一对多

    班级(一端)和学生(多端)的关系,班级表的主键id作为学生表的外键

  2. 多对多

    老师和学生的关系,需要一个中间表,把老师和学生的编号当作组件,老师编号和学生编号都是外键

  3. 一对一

    人和身份证的关系, 给人的身份证那一列添加外键和唯一约束

表格之间的联合查询

  1. 等值连接

    select * from table1, table2; // 这样得到的是一个笛卡尔积,即将两张表格或多张表格进行无条件的拼接

    select * from table1, table2 where table1.no = table2.no; // 等值连接,等值连接的意思就是在笛卡尔的基础上进行筛选,筛选条件不一定是等号(通常是等号);

  2. 外连接

    select * from A left/right [ outer] join B on 条件

    两张表格A和B,查询的时候谁放在左边显示,谁就写在前面,谁在右边显示,谁就写在后面

    left和right来控制以哪一个表格的数据作为基准,作为基准的表格数据必须全部显示出来,非基准的表格按照on条件与之拼接,若找到条件拼接,则正常显示,若找不到满足条件的则null

    外连接查询结果有可能比等值连接的最终结果多一部分数据

    外连接不写on关键字是不能进行拼接的

  3. 内连接(自连接)

    select * from A inner join B on 条件; 在当前表格中再次查询当前表格的信息

    A和B可以是不同的两张表格,也可以是相同的两张表格

行列互换

    select wname as '仓库名',
    max( if(wmonth='一月份', winvenroty, 0)) as '一月份',
    max( if(wmonth='二月份', winventory, 0)) as '二月份',
    max( if(wmonth='三月份', winventory, 0)) as '三月份',
    from warehouse
    group by wname;

分页

limit a, b; a代表想要显示的起始行索引,包括此行(索引从0开始),也叫做偏移量。b代表想要显示的行数

DCL 数据控制语言(Data Control Language)

控制用户的权限、grant赋予、remove回收

  1. 我们现在的身份是一个SYSDBA管理员

    管理员可以操作其他普通用户的权限

    通过root账号查看mysql数据库中的user表格

    记录着所有的用户信息:一般只查询下面吉列:(一共有两百多列)

    user列、host列、password列、authentication_string列

  2. 创建一个新的用户

    create user '用户名'@'IP地址' identified by '密码';

    用户被创建成功之后值只有一个默认的权限 Usage只允许登录,不允许做其他事情

    show frants for '用户名'@'IP';

  3. 给新的用户赋予权限

    grant 权限 on 数据库名.表 to '用户名'@'IP';

    赋予权限之后,最好做一个刷新:flush privileges

  4. 退出当前用户,登录刚刚创建的新用户

    退出用户:exit;

    登录新用户:mysql -u zzt -p

  5. 回收用户的权限

    Usage权限是无法回收的,因为创建用户的时候他就默认有了

    revoke 权限 on 数据库名.表名 from '用户名'@'IP';

  6. 修改用户的密码

    update user set authentication_string = password(值) where user = 'gyq';

  7. 删除用户

    drop user '用户名'@'IP';

数据库设计的范式--表之间的范式

可以理解为Java当中的设计模式

设计数据库时,遵循的不同规范,这些规范统称为范式。

范式的目的是为了减少数据库中的冗余,管理表格的时候变得容易(修改、删除),查询的时候可能就涉及到表格联合的问题

Normal From(标准话形式-普通范式)

  1. 第一范式

    数据的原子性:数据库中的每一张表格的每一个列都是不可分割的,即行列交叉点的单元格只存储一个数据

    每一个表格必须有主键约束(作用是可以快速查询某一行记录)

  2. 第二范式

    在满足第一范式的前提下,不允许出现部分依赖性(非主键列不能受到主键列或主键的一部分影响)

    当产生了非主键列受到主键或主键的部分影响,将数据拆开存储在两张表格里

  3. 第三范式

    在满足前两个范式的前提下,不允许出现传递依赖性(非主键列不能受到非主键列或非主键列的一部分影响)

    当产生了非主键列受到非主键列的影响时,将没有关系的数据拆开单独存放在表格里

事务及隔离级别

事务Transaction

  1. 事务可以理解为是让数据库做的事情
  2. 有些时候事情之内不止一条sql,存在多个组成单元。比如:张三给李四转100块钱,在数据库中,要给张三金减掉100,李四要加100。这个就是不止一条sql语句
  3. 一件事情中的所有操作应该是统一的,即要么都成功,要么都失败
  4. 事物的本质:可以理解为多线程并发操作同一张表格可能带来的安全问题
  5. 事务的四大特性:(ACID)
  • Atomicity原子性: 一个事务中的所有操作是一个整体,不可再分。事务中的所有操作要么都成功,要么都失败。

  • Consistency一致性: 一个用户操作了数据提交了以后,另一个用户看到的数据与之前用户看到的效果是一致的。

  • Isolation隔离性: 指的是多个用户并发访问数据库时,一个用户操作数据库,另一个用户不能有所干扰,多个用户之间的数据操作事务要相互隔离。

    事务的隔离级别:级别越高越安全,性能慢

  • Durability持久性: 指的是一个用户操作数据的事务一旦被提交(缓存-->文件),他对数据库底层真实的改变时永久性的,不可返回。