mysql入门与进阶
MySQL入门与进阶
需求:对一张表中的数据进行增删改查操作(CURD)
C:create 创建
U:update 修改
R:read 读|检索 查询
D:delete 删除
涉及技术:数据库
1、数据库认知
1.1、数据库
本质上就是一个文件系统.通过标准的sql对数据进行curd操作
安装数据库管理系统:数据库管理系统就是一个软件,与安装其他软件操作一样,但是需要进行配置,具体步骤略
1.2、常见的关系型数据库
关系型数据库:存放实体与实体之间的关系的数据库(就是二维表)
实体:用户 订单 商品
关系:用户拥有订单 订单包含商品
非关系型数据库:存放的是对象(redis) NO-sql(not only sql)
常见数据库及对应特点
软件名 厂商 特点
mysql oracle 开源mian的数据库
oracle oracle 大型的收费的数据库
DB2 IBM 大型的收费的数据库
sqlserver 微软 中大型的收费的数据库
sybase sybase (powerdesigner)
MYSQL :开源免费的数据库,小型的数据库.已经被Oracle收购了.MySQL6.x版本也开始收费.
Oracle :收费的大型数据库.Oracle公司的产品.Oracle收购SUN公司,收购MYSQL.
DB2 :IBM公司的数据库产品,收费的.银行系统中.
SQLServer:MS公司.收费的中型的数据库.
SyBase :已经淡出历史舞台.提供了一个非常专业数据建模的工具PowerDesigner.
SQLite : 嵌入式的小型数据库,应用在手机端.
Java相关的数据库:MYSQL,Oracle
安装了数据库管理系统的计算机称之为数据库服务器
服务器:给别人提供提供服务器(软件服务器)
我们可以通过标准的sql在服务器创建数据库(database),有了数据库之后,就可以在数据库上创建表了,有了表之后,就可以在里面存放数据了.
SQL:结构化查询语句
作用:管理数据库.
sql的分类:
DDL:数据定义语言
操作对象:数据库和表
关键词:create alter drop
DML:数据操作语言
操作对象:记录
关键词:insert,delete,update
DQL:数据查询语言(非官方)
关键词:select
DCL:数据控制语言
操作对象:用户 事务 权限
关键词:if,grant
2、DDL数据定义语言
2.1 mysql数据库的登录
命令:mysql -u root -p (即:mysql -u 数据库用户名 -p)
2.2 DDL数据定义语言
操作对象:数据库、表
关键词:create alter drop
2.3数据库的CRUD操作
2.3.1创建数据库
语法:
* create database 数据库名;
* create database 数据库名 character set 字符集;
* create database 数据库名 character set 字符集 collate 校对规则;
2.3.2查看数据库
* 查看数据库服务器中的所有的数据库:show databases;
* 查看某个数据库的定义的信息:show create database 数据库名;
2.3.3删除数据库
* drop database 数据库名称;
此前有hejh3这个数据库,对其进行删除,执行结果如下:
2.3.4修改数据库
* alter database 数据库名 character set 字符集 collate 校对规则;
2.3.5其他命令操作数据库
* 切换数据库:use 数据库名;
* 查看正在使用的数据库:select database();
切换到hejh1数据库:
查看当前使用的数据库:
2.4数据库中表的CRUD操作
2.4.1创建表
create table 表名( 字段名 类型(长度) 约束, 字段名 类型(长度) 约束 );
java和mysql类型对比 Java MYSQL int int float float double double char/String char/varchar(char固定长度字符串,varchar可变长度的字符串) Date date,time,datetime,timestamp 文件类型 BLOB、TEXT TEXT指的是文本文件 BLOB二进制文件
* Oracle的文件类型:BLOB CLOB 约束: 单表约束: * 主键约束:primary key * 唯一约束:unique * 非空约束:not null 创建一个分类表: 分类ID int类型 主键 自动增长 分类名称 字符串类型 长度20 create table category( cid int primary key auto_increment, cname varchar(20) ); ***** 注意:建表之前一定先选择数据库.
例如,创建user表,
create table user(
id int primary key auto_increment,
username varchar(20)
);
例如,创建user1表,
create table user1(
id int primary key auto_increment,
username varchar(20)
);
2.4.2查看表
查看数据库中的所有表:show tables;
查看表结构:desc 表名;
基于2.4.1创建的2张表,用show tables命令查看当前数据库hejh1下所有的表,
查看表结构:desc 表名;
2.4.3删除表
drop table 表名;
hejh1数据库中有,user、user1 2张表,删除user1表,drop table user1;
truncate 清空表 ★
格式:
truncate 表名; 干掉表,重新创建一张空表
和delete from 区别:
delete属于DML语句,数据可以回滚 truncate属于DDL语句
delete逐条删除 truncate干掉表,重新创建一张空表
auto_increment 自增
要求:
1.被修饰的字段类型支持自增. 一般int
2.被修饰的字段必须是一个key 一般是primary key
create table ai01(
id varchar(10) auto_increment
);-- 错误 Incorrect column specifier for column 'id'
create table ai01(
id int auto_increment
);-- 错误 Incorrect table definition; there can be only one auto column and it must be defined as a key
2.4.4修改表
格式: alter table 表名 ....
hejh1数据库中,修改user表名为user11,命令如下:
修改表名: alter table 旧表名 rename to 新表名;
例如: alter table user rename to user11;
user表中增加password字段(列)
添加字段: alter table 表名 add [column] 字段描述;
例如: alter table user add password varchar(20);
将字段password名字改为pwd,命令如下:
修改字段名: alter table 表名 change 字段名称 新字段描述; 例如: alter table user change password pwd varchar(22);
将pwd字段的类型从varchar改为int类型,命令如下:
修改字段描述: alter table 表名 modify 字段名称 字段类型 [约束];
例如: alter table user modify pwd int [not null];
删除字段pwd,命令如下:
删除字段: alter table 表名 drop 字段名;
例如:alter table user drop pwd;
2.4.5常用命令
切换或者进入数据库: use 数据库名称;
查看当前数据库下所有表: show tables;
查看表结构:desc 表名;
查看建表语句:show create table 表名;
3.DML数据操作语言
操作对象:记录(行)
关键词:insert update delete
3.1insert插入数据
语法: * insert into 表(列名1,列名2,列名3..) values(值1,值2,值3..); -- 向表中插入某些列 * insert into 表 values(值1,值2,值3..); --向表中插入所有列 注意: * 1.列名数与values后面的值的个数相等 * 2.列的顺序与插入的值得顺序一致 * 3.列名的类型与插入的值要一致. * 4.插入值得时候不能超过最大长度. * 5.值如果是字符串或者日期需要加’’. cmd下插入中文的乱码的解决: * 修改mysql.ini文件. * 将[mysql]下面的字符集改为gbk * 重启mysql服务.services.msc
插入:
格式1: insert into 表名 values(字段值1,字段值2...,字段值n);
注意:
默认插入全部字段,必须保证values后面的内容的类型、顺序和表结构中的一致,若字段类型为数字,可以省略引号
例如:
insert into user values(1,'hejh');
insert into user values('2','swy');
insert into user values('5');-- 错误的
格式2: insert into 表名(字段名,字段名1...) values(字段值,字段值1...);
注意: 插入指定的字段,必须保证values后面的内容的类型、顺序和表名后面的字段的类型和顺序保持一致.
例如:
insert into user (username,id) values('hh',4);
insert into user (username) values('jack',5);-- 错误的
查看数据插入是否成功
3.2 update数据修改
格式: update 表名 set 字段名=字段值,字段名1=字段值1... [where 条件];
例如: update user set username='hejh1' where username='hh';
注意:
* 1.列名的类型与修改的值要一致.
* 2.修改值得时候不能超过最大长度.
* 3.值如果是字符串或者日期需要加’’.
3.3 delete数据修改
格式: delete from 表名 [where 条件];
例如: delete from user where id = '4';
面试:删除表中所有记录使用delete from 表名; 还是用truncate table 表名?
* 删除方式:delete 一条一条删除. 而truncate 直接将表删除,重新建表.
* 事务控制DML。delete属于DML,如果在一个事务中,delete数据,这些数据可以找回;truncate删除的数据找不回来。
4.DQL数据查询语言
关键词:select
格式: select ... from 表名 where 条件 group by 分组字段 having 条件 order by 排序字段 ase|desc
或 select [distinct]*[列名,列名] from 表 [where 条件]
4.1初始化测试环境
建表:
创建商品表
create table products(
pid int primary key auto_increment,
pname varchar(20),
price double,
pnum int,
cno int,
pdate timestamp
);
插入数据:
insert into products values (null,'泰国大榴莲',98,12,1,null); insert into products values (null,'新疆大枣',38,123,1,null); insert into products values (null,'新疆切糕',68,50,2,null); insert into products values (null,'十三香',10,200,3,null); insert into products values (null,'老干妈',20,180,3,null); insert into products values (null,'豌豆黄',20,120,2,null);
4.2简单查询练习
1.查询所有的商品
select * from products;
2.查询商品名和商品价格.
-- 查看指定的字段
-- 格式: select 字段名1,字段名2 from 表名
select pname,price from products;
3.查询所有商品都有那些价格.
-- 去重操作 distinct
-- 格式: select distinct 字段名,字段名2 from 表名
select price from products;
select distinct price from products;
4.将所有商品的价格+10元进行显示.(别名)
-- 可以在查询的结果之上进行运算,不影响数据库中的值
-- 给列起别名 格式: 字段名 [as] 别名
select price+10 from products;
select price+10 新价格 from products;
select price+10 '新价格' from products;
select price+10 新 价 格 from products;-- 错误
select price+10 '新 价 格' from products;
select price+10 `新 价 格` from products;--错误,中文单引号
4.3条件查询练习
1.查询商品名称为十三香的商品所有信息:
select * from products where pname='十三香';
2.查询商品价格>60元的所有的商品信息:
select * from products where price>60;
3.查询商品名称中包含”新”的商品
-- 模糊匹配
-- 格式: 字段名 like "匹配规则";
-- 匹配内容 %
"龙" 值为龙
"%龙" 值以"龙"结尾
"龙%" 值以"龙"开头
"%龙%" 值包含"龙"
-- 匹配个数 "__" 占两个位置
select * from products where pname like '%新%';
4.查询价格为38,68,98的商品
select * from products where price=38 or price=68 or price=98;
select * from products where price in(38,68,98);
where后的条件写法: * > ,<,=,>=,<=,<>,!=
* like 使用占位符 _ 和 % _代表一个字符 %代表任意个字符. * select * from product where pname like '%新%';
* in在某个范围中获得值. * select * from product where pid in (2,5,8);
* between 较小值 and 较大值 select * from products where price between 50 and 70;
4.4排序查询
1.查询所有的商品,按价格进行排序.(asc-升序,desc-降序)
select * from products order by price asc;
select * from products order by price desc;
2.查询名称有新的商品的信息并且按价格降序排序.
select * from products where pname like '%新%' order by price desc;
3.查询所有商品的信息并且按价格降序、数量升序排列.
select * from products order by price desc,pnum asc;
4.5聚合函数
聚合函数: 对一列进行计算 返回值是一个,忽略null值
* sum(),avg(),max(),min(),count();
1.获得所有商品的价格的总和:
select sum(price) from products;
2.获得商品表中价格的平均数:
select avg(price) from products;
-- round(值,保留小数位)
select round(avg(price),3) from products ;
3.获得商品表中有多少条记录:
select count(*) from products;
4.获得商品表中最高的价格:
select max(price) from products ;
5.获得商品表中价格最小的商品信息:
select min(price) from products ;
4.6 group by分组
1.根据cno字段分组,分组后统计商品的个数.
select cno,count(*) from products group by cno;
2.根据cno分组,分组统计每组商品的总数量,并且总数量> 200;
select cno,sum(pnum) from products group by cno having sum(pnum)>200;
注意:
where和having区别:
1.where 是对分组前的数据进行过滤 ;having 是对分组后的数据进行过滤
2.where 后面不能使用聚合函数,having可以
4.7数据类型
java mysql
byte tinyint
short smallint
int int(★)
long bigint
char/String varchar(★)|char
varchar:可变长度 mysql的方言 varchar(20): 存放abc 只会占用三个
char:固定长度 char(20) 存放abc 占用20个
boolean tinyint|int 代替
float|double float|double
注意:
double(5,2):该小数长度为5个,小数占2个 最大值:999.99
java.sql.Date date 日期
java.sql.Time time 时间
java.sql.Timestamp timestamp(★) 时间戳 若给定值为null,数据库会把当前的系统时间存放到数据库中
datetime(★) 日期+时间
java.sql.Clob(长文本) mysql的方言(text)
java.sql.Blob(二进制) blob
5 约束
约束作用:
为了保证数据的有效性和完整性。
常用约束:
mysql常用约束:主键约束(primary key) 唯一约束(unique) 非空约束(not null) 外键约束(foreign key)
5.1主键约束
主键约束:被修饰过的字段唯一非空
注意:一张表只能有一个主键,这个主键可以包含多个字段
方式1:建表的同时添加约束 格式: 字段名称 字段类型 primary key
方式2:建表的同时在约束区域添加约束
所有的字段声明完成之后,就是约束区域了
格式: primary key(字段1,字段2)
方式3:建表之后,通过修改表结构添加约束
创建一张表,
create table pk01(
id int,
username varchar(20),
primary key (id)
);
insert into pk01 values(1,'hjh');-- 成功
insert into pk01 values(2,'ttt');-- 失败 Duplicate entry '2' for key 'PRIMARY'
insert into pk01 values(null,'tom');-- 失败 Column 'id' cannot be null
再次创建表pk01,
create table pk01(
id int primary key,
username varchar(20),
primary key (id)
);-- 错误的 一张表只能有一个主键
方式3:建表之后,通过修改表结构添加约束
create table pk02(
id int,
username varchar(20)
);
alter table pk02 add primary key(字段名1,字段名2..);
alter table pk02 add primary key(id,username);
给表pk02的id和username增加主键约束,所以id和username为联合主键,故id和username都是非空的,如下图
插入数据,
insert into pk02 values(1,'hejh');-- 成功
insert into pk02 values(1,'hehe');-- 成功
insert into pk02 values(1,'hehe');-- 失败
5.2 唯一约束
被修饰过的字段唯一,对null不起作用
方式1:建表的同时添加约束 格式: 字段名称 字段类型 unique
方式2:建表的同时在约束区域添加约束
方式3:建表之后,通过修改表结构添加约束
方式1:建表的同时添加约束 格式: 字段名称 字段类型 unique
create table un(
id int unique,
username varchar(20)
);
insert into un value(1,'kk');-- 成功
insert into un value(1,'ll');-- 错误 Duplicate entry '1' for key 'id'
insert into un value(null,'oo');-- 成功
insert into un value(null,'pp');-- 成功
方式2:建表的同时在约束区域添加约束
所有的字段声明完成之后,就是约束区域了
unique(字段1,字段值2...)
建表un11,给id设置唯一性约束,故id非空,
create table un11(
id int ,
username varchar(20) ,
unique(id)
);
方式3:建表之后,通过修改表结构添加约束
alter table 表名 add unique(字段1,字段2);-- 添加的联合唯一
alter table 表名 add unique(字段1);-- 给一个添加唯一
table 表名 add unique(字段2);-- 给另一个添加唯一
create table un01(
id int,
username varchar(20)
);
给id和username设置联合唯一,只有id和username都相同,插入数据时才会报错,如下图
alter table un01 add unique(id,username);
insert into un01 values(1,'tom');-- 成功
insert into un01 values(1,'jack');-- 成功
insert into un01 values(1,'tom');-- 失败 Duplicate entry '1-tom' for key 'id'
5.3 非空约束
非空约束(了解)
特点:被修饰过的字段非空
方式:
create table nn(
id int not null,
username varchar(20) not null
);
insert into nn values(null,'tom');-- 错误的 Column 'id' cannot be null
5.4外键约束
多个表之间是有关系的,那么关系靠谁来维护?
多表约束:外键约束.
alter table products add foreign key (cno) references category(cid);
1.一对多关系
客户和订单,分类和商品,部门和员工.
一对多建表原则:在多的一方创建一个字段,字段作为外键指向一的一方的主键.
用户和订单
-- 创建用户表
create table user(
id int primary key auto_increment,
username varchar(20)
);
-- 创建订单表
create table orders(
id int primary key auto_increment,
totalprice double,
user_id int
);
为了保证数据的有效性和完整性,添加约束(外键约束).
在多表的一方添加外键约束
格式:
alter table 多表名称 add foreign key(外键名称) references 一表名称(主键);
例如:
alter table orders add foreign key(user_id) references user(id);
添加了外键约束之后有如下特点:★
1.主表中不能删除从表中已引用的数据
2.从表中不能添加主表中不存在的数据
开发中处理一对多:
在多表中添加一个外键,名称一般为主表的名称_id,字段类型一般和主表的主键的类型保持一致,
为了保证数据的有效性和完整性,在多表的外键上添加外键约束即可.
2.多对多关系
学生和课程:
多对多关系建表原则:需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键.
例子:商品和订单
-- 创建商品表
create table product(
id int primary key auto_increment,
name varchar(20),
price double
);
-- 创建中间表
create table orderitem(
oid int,
pid int
);
-- 添加外键约束
alter table orderitem add foreign key(oid) references orders(id);
alter table orderitem add foreign key(pid) references product(id);
开发中处理多对多:
引入一张中间表,存放两张表的主键,一般会将这两个字段设置为联合主键,这样就可以将多对多的关系拆分成两个一对多了;
为了保证数据的有效性和完整性,需要在中间表上添加两个外键约束即可.
3.一对一关系
在实际的开发中应用不多.因为一对一可以创建成一张表.
两种建表原则:
唯一外键对应:假设一对一是一个一对多的关系,在多的一方创建一个外键指向一的一方的主键,将外键设置为unique.
主键对应:让一对一的双方的主键进行建立关系.
6.多表查询
建表与初始化数据
###创建分类表
create table category(
cid varchar(32) PRIMARY KEY ,
cname varchar(100) #分类名称
);
# 商品表
CREATE TABLE products (
pid varchar(32) PRIMARY KEY ,
name VARCHAR(40) ,
price DOUBLE
);
#添加外键字段
alter table products add column category_id varchar(32);
#添加约束
alter table products add constraint product_fk foreign key (category_id) references category (cid);
添加外键约束:
alter table 从表 add constraint [外键名称字段]_fk foreign key(从表外键字段) references 主表(主表主键字段);
[外键名称] 用于删除外键约束,一般以_fk结尾
alter table 从表drop foreign key [外键名称]
主要作用:保障数据的完整性. 不删除从表内容,主表不能删除.(因为在从表中有外键关联主表id,删除的时候只能先删除从表,后删主表,
可以理解为:删除从表,释放主表id,之后才能删除主表)
### 订单表
create table orders(
oid varchar(32) PRIMARY KEY ,
totalprice double #总计
);
### 订单项表
create table orderitem(
oid varchar(50),-- 订单id
pid varchar(50)-- 商品id
);
### 联合主键(可省略)
alter table orderitem add primary key (oid,pid);
###---- 订单表和订单项表的主外键关系
alter table orderitem add constraint orderitem_orders_fk foreign key (oid) references orders(oid);
###---- 商品表和订单项表的主外键关系
alter table orderitem add constraint orderitem_product_fk foreign key (pid) references products(pid);
-- 给分类表初始化数据
insert into category values('c001','电器');
insert into category values('c002','服饰');
insert into category values('c003','化妆品');
insert into category values('c004','书籍');
-- 给商品表初始化数据
insert into products(pid,name,price,category_id) values('p001','联想',5000,'c001');
insert into products(pid,name,price,category_id) values('p002','海尔',3000,'c001');
insert into products(pid,name,price,category_id) values('p003','雷神',5000,'c001');
insert into products(pid,name,price,category_id) values('p004','JACK JONES',800,'c002');
insert into products(pid,name,price,category_id) values('p005','真维斯',200,'c002');
insert into products(pid,name,price,category_id) values('p006','花花公子',440,'c002');
insert into products(pid,name,price,category_id) values('p007','劲霸',2000,'c002');
insert into products(pid,name,price,category_id) values('p008','香奈儿',800,'c003');
insert into products(pid,name,price,category_id) values('p009','相宜本草',200,'c003');
insert into products(pid,name,price,category_id) values('p010','梅明子',200,null);
6.1内连接
内连接查询(使用的关键字 inner join -- inner可以省略)
格式1:显式的内连接
select a.*,b.* from a [inner] join b on ab的连接条件
格式2:隐式的内连接
select a.*,b.* from a,b where ab的连接条件
建表与初始化
-- 用户表(user)
create table user (
id int auto_increment primary key,
username varchar(50) -- 用户姓名
);
-- 订单表(order)
create table order1 (
id int auto_increment primary key,
price double,
user_id int
);
-- 给订单表添加外键约束
alter table orders add constraint user_fk foreign key (user_id) references user(id);
-- 向user表中添加数据
insert into user values(1,'张三');
insert into user values(2,'李四');
insert into user values(3,'王五');
insert into user values(4,'赵六');
-- 向order1 表中插入数据
insert into order1 values(1,1314,3);
insert into order1 values(2,1314,3);
insert into order1 values(3,15,4);
insert into order1 values(4,315,null);
insert into order1 values(5,1014,null);
示例如下:查询用户的订单,没有订单的用户不显示
隐式内连接:
select user.*,order1.* from user ,order1 where user.id=order1.user_id;
显示内连接
select user.*,order1.* from user join order1 on user.id=order1.user_id;
6.2外连接
外连接查询(使用的关键字 outer join -- outer可以省略)
左外连接:left outer join
select a.*,b.* from a left [outer] join b on 连接条件;
意思:
先展示join左边的(a)表的所有数据,根据条件关联查询 join右边的表(b),符合条件则展示出来,不符合以null值展示.
右外连接:right outer join
select a.*,b.* from b right [outer] join a on 连接条件;
意思:
先展示jion右边的表(a)表的所有数据,根据条件关联查询join左边的表(b),符合条件则展示出来,不符合以null值展示.
查询所有用户的订单详情
左外连接: user在左
select user.*,order1.* from user left join order1 on user.id=order1.user_id;
查询所有订单的用户详情
右外连接:orders 在右
select order1.*,user.* from user right join order1 on user.id=order1.user_id;
6.3子查询
子查询:
一个查询依赖另一个查询,即当一个查询是另一个查询的条件时,称之为子查询
例如:select user.*,tmp.* from user,(select * from orders where price>300) as tmp where user.id=tmp.user_id;
查看用户为张三的订单详情
1.先查询张三的id
select id from User where username = '张三';// 3
2.select * from orders where user_id = ?;
两个合二为一
select * from order1 where user_id = (select id from User where username = '张三');
查询出订单的价格大于300的所有用户信息。
1.先查询出订单价格>300的用户的id
select user_id from orders where price >300;//(3,3,5,null)
2.select * from user where id in(3,3,5,null);
两个合二为一:
select * from user where id in(select user_id from order1 where price >300);
查询订单价格大于300的订单信息及相关用户的信息。
内连接:
select order1.*,user.* from order1,user where user.id=order1.user_id and orders.price>300 ;
6.4分页查询
分页查询每个数据库的语句是不通用的.
MYSQL:使用limit的关键字.
* select * from product limit a,b; --a:从哪开始,b:查询多少条.
Oracle:使用SQL语句嵌套.
SQLServer:使用top的关键字.
7.事务管理
7.1什么是事务管理
事务是恢复和并发控制的基本单位。
可以把一系列要执行的操作称为事务,而事务管理就是管理这些操作要么完全执行,要么完全不执行(很经典的一个例子是:A要给B转钱,首先A的钱减少了,但是突然的数据库断电了,导致无法给B加钱,然后由于丢失数据,B不承认收到A的钱;在这里事务就是确保加钱和减钱两个都完全执行或完全不执行)
事务管理的意义:保证数据操作的完整性
事务有四个特性(ACID):
原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)
- 原子性:事务是应用中最小的执行单位,就如原子是自然界最小颗粒,具有不可再分的特征一样。事务是应用中不可再分的最小逻辑执行体,一组事务,要么成功;要么撤回。
- 一致性:事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库中只包含事务成功提交的结果时,数据库处于一致性状态。一致性是通过原子性来保证的。有非法数据(外键约束之类),事务撤回。。
- 隔离性:各个事务的执行互不干扰,任意一个事务的内部操作对其他并发事务都是隔离的。即:并发执行事务之间不能看到对方的中间状态,并发执行的事务之间不能相互影响。事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。
- 持久性:事务一旦提交,对数据所做的任何改变,都要记录到永久存储器中,通常是保存进物理数据库。软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。
事务管理操作命令:
- 开启事务管理:开启之后,下面的sql语句并不会马上执行并把结果写到表中,而是会写到事务日志中。
- start transaction;
- 回退操作:回退会清掉开始事务管理之后写到事务日志中的内容,即恢复到开启事务管理之前。
- 语法:rollback;
- 注意:回退操作只是回退"写"的内容,对于普通的读表select语句不能回退。
- 事务提交:将sql语句的结果写到数据表中。
- 语法:commit:
建表与初始化数据:
create table bank(
bid int primary key auto_increment,
bname varchar(20),
money int
);
insert into bank values(null,'hejh',100);
insert into bank values(null,'swy',100);
开启事务:start transaction
在执行start transaction之后,执行的一系列操作,是先写在相关日志里的,命令执行下去实际数据库并没有生效;一旦执行commit命令,start transaction命令和commit之间执行的开始生效,即数据库数据已经被修改提交。
money被修改了。
在执行commit命令之前,如果执行了rollback命令,则start transaction命令 到 rollback命令 之间执行的命令不会生效,数据回滚到start transaction命令执行之前的数据。
注意:
- 当 commit 或 rollback 语句执行后,事务会自动关闭。
- 锁机制:在事务操作一个表时,如果使用索引来取值,那么会锁定到对应行;如果没有使用索引来取值,那么会锁定整个表。锁定之后其他连接无法操作指定行或表。
7.2回滚点
回滚点就是为了准确的回滚到某个操作之前,可以指定rollback回退的位置。
语法:
- 创建回滚点:savepoint 回滚点名;
- 回滚到回滚点:rollback to 回滚点名;
注意:回滚点在事务管理关闭(rollback或commit之后)之后失效,不要在事务之外使用回滚点。
1)执行start transaction;开启事务
start transaction;
2)接着插入2条数据
insert into bank values(null,'hh',333);
insert into bank values(null,'ss',444);
3)执行设置回滚点。在修改数据之前设置一个回滚点
savepoint before_update;
4)修改2条记录
update bank set money=money-100 where name='hejh';
update bank set money=money+100 where name='swy';
此时查询表中数据如下图:
5)一旦执行回滚命令,回滚到修改数据之前,数据表中数据显示如下图:
rollback to before_update;
7.3默认事务管理
默认情况下,mysql的事务管理是关闭(自动事务)的,语句的结果会马上写到数据表中。 可以通过select @@autocommit;来查看是否开启自动事务,值为1为自动事务已开启,为0则为关闭。
关闭自动事务:set autocommit =0;【关闭后需要commit来执行每一条语句,相当于开始了事务管理】
不过注意的是set autocommit针对的是会话变量,所以这个设置只在此次会话连接中生效。
敲入quit断开此次连接,然后再次连接,值为1:
8.序列
① mysql的自增长“序列”和序列是两回事,mysql本身不提供序列机制,只有一个auto_increment自增长字段
②mysql的auto_increment可以设置起始值,但是不能设置步长,其固定步长是1
③mysql一个表只能有一个自增长字段。自增长只能被分配给固定表的固定的某一字段,不能被多个表共用,并且只能是数字型
1.创建序列表sequence
create table sequence (
name varchar(50) collate utf8_bin not null comment ,
current_value int(11) not null comment ,
increment int(11) not null default 1 comment, // 序列的自增值
primary key(name)
)
engine=InnoDB default charset=utf8 collate=utf8_bin;
2.创建函数--取当前值
begin
declare value integer;
set value=0;
select current_value into value
from sequence
where name = seq_name;
return value;
end
3.创建函数--取下一个值
drop function if exists nextval;
delimiter $
create function nextval (seq_name varchar(50))
returns integer
language SQL
deterministic
contains SQl
SQL security definer
comment ''
begin
update sequence
set current_value = current_values + increment
where name = seq_name;
return currval(seq_name);
end
$
delimiter
4.创建函数--更新当前值
drop function id exists setval;
delimiter $ create function setval (seq_name varchar(50),value integer) returns integer language SQL deterministic contains SQL SQL security definer comment '' begin update sequence set current_value = value where name = seq_name; return currval(seq_name); end $ delimiter;
5.测试序列
insert into sequence values('testSeq',0,1);--添加一个sequence名称和初始值,以及自增幅度
select setval('testSeq',10);--设置指定sequence的初始值 select currval('testSeq');--查询指定sequence的当前值 select nextval('testSeq');--查询指定squence的下一个值
9.视图
9.1什么是视图
视图(view):是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。
通过视图,可以展现基表(创建视图的表base table)的部分数据;视图数据来自定义视图的查询中使用的表,使用视图动态生成。
9.2视图的特点
视图是对若干张基本表的引用,是一张虚表,是查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);
可以跟基本表一样,进行增删改查操作(ps:增删改操作有条件限制);
视图的优点:
①简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
②安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。
③数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。
视图使用场景:
①权限控制的时候,不希望用户访问表中某些含敏感信息的列,比如salary...
②关键信息来源于多个复杂关联表,可以创建视图提取我们需要的信息,简化操作;
9.2示例
建表和数据初始化:用户(user)、课程(course)、用户课程中间表(user_course)
drop table if exists course;
create table course(
id bigint(20) not null auto_increment,
name varchar(20) not null,
descroption varchar(200) not null,
primary key(id)
) engine=InnoDB auto_increment=4 default charset=utf8;//从4开始自增
insert into course values(null,'java','java从入门到精通');
insert into course values(null,'javascript','javascript进阶');
insert into course values(null,'vue','vue从入门到进阶');
drop table if exists user;
create table user(
id int(20) not null auto_increment,
account varchar(200) not null,
name varchar(20) not null,
address varchar(200) default null,
primary key(id)
) engine=InnoDB auto_increment=1 default charset=utf8;
insert into user values(null,'user1','hjh','中国上海');
insert into user values(null,'user2','swy','中国广州');
insert into user values(null,'user1','qyd','中国南昌');
drop table if exists user_course;
create table user_course(
id int(20) not null auto_increment,
userid int(20) not null,
courseid int(20) not null,
primary key(id)
) engine=InnoDB auto_increment=1 default charset=utf8;
user的id是从1开始到3,course的id是从4到6,所以插入的时候数据是以下样式的:
insert into user_course values(null,1,4);
insert into user_course values(2,1,5);
insert into user_course values(3,2,3);
insert into user_course values(4,2,4);
insert into user_course values(5,2,5);
insert into user_course values(6,3,4);
创建视图view_user_course
drop view if exists view_user_course;
create view view_user_course as (
select uc.id as id,u.name as username,c.name as coursename
from (
(
user u left join user_course uc on ((u.id = uc.userid))
)
left join course c on ((uc.courseid = c.id))
)
);
查询hejh用户上的所以课程相关信息(hejh用户不存在,所以查询结果是empty)
查询hjh用户上的所以课程相关信息(初始化数据时插入过一个用户名为hjh的用户,所以查询结果不为empty)
由多张表建立起来的视图中,不能做同时修改2张以上表数据的操作,会报错:
可参考博文https://www.cnblogs.com/geaozhang/p/6792369.html#chuangjianshitu
9.3视图的修改
基本格式:create or replace view view_name as select语句;
在视图存在的情况下可对视图进行修改,视图不在的情况下可创建视图
9.4drop删除视图
删除视图是指删除数据库中已存在的视图,删除视图时,只能删除视图的定义,不会删除数据,即不动基表。
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
使用IF EXISTS选项使得删除不存在的视图时不抛出异常
10.索引
10.1索引的分类
索引分单列索引(主键索引,唯一索引,普通索引)和组合索引。
单列索引:即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引
组合索引:即一个索引包含多个列
创建索引时,需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
索引的优点:
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度(在数据量很大的时候,效果更明显)。
索引的缺点:
虽然索引大大提高了查询速度,但是同时也会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE操作。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。
10.2普通索引
创建索引
最基本的索引,没有限制,创建方式如下:
create index 索引名 on 表名(字段(字段长度));
如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length
通过修改表结构来添加索引:
alter table 表名 add index 索引名(字段名);
建表时直接指定索引:
create table 表名(
字段 数据类型 约束, 字段 数据类型 约束, index [索引名] (字段(字段长度)) );
删除索引:
drop index 索引名 on 表名
10.3 唯一索引
与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
直接创建唯一索引:
create unique index 索引名 on 表名(字段(字段长度))
修改表结构创建唯一索引:
alter table 表名 add unique [索引名](字段名(字段长度))
创建表的时候直接指定唯一索引:
create table 表名(
字段1 数据类型 约束,
字段2 数据类型 约束,
......
unique [索引名] (字段名(字段长度))
)
使用ALTER 命令添加和删除索引:
有四种方式来添加数据表的索引:
①alter table 表名 add primary key(字段列表);//添加一个主键,这意味着索引值必须是唯一的,且不能为NULL
②alter table 表名 add unique 索引名(字段列表);//创建索引的值必须是唯一的(输了Null外,null可能会出现很多次)
③alter table 表名 add index 索引名 (字段列表);//添加普通索引,索引值可以出现多次
④alter table 表名 add fulltext 索引名(字段列表);//指定索引为fulltext,用于全文索引
ALTER 命令中使用 DROP 子句来删除索引。尝试以下实例删除索引:
alter table 表名 drop index 索引名;
使用 ALTER 命令添加和删除主键
主键只能作用于一个列上,添加主键索引时,你需要确保该主键默认不为空(NOT NULL)。实例如下
alter table 表名 modify 字段 数据类型 约束;
alter table 表名 add primary key(字段名);
也可以使用 ALTER 命令删除主键:
alter table 表名 drop primary key;
删除主键时只需指定PRIMARY KEY,但在删除索引时,必须知道索引名。
显示索引信息:show index
使用 SHOW INDEX 命令列出表中的相关索引信息。可以通过添加 \G 来格式化输出信息。
尝试以下实例:
show index from 表名; \G
参见博文:细说mysql索引 https://www.cnblogs.com/chenshishuo/p/5030029.html