MySQL学习总结

一、数据库的基本概念

1. 什么是数据库?
	* 用于存储和管理的仓库
2. 数据库的特点:
	(1)持久化存储数据,其实数据库就是一个文件系统
	(2)方便存储和管理数据
	(3)使用了统一的方式操作数据库 SQL

二、MySQL数据库软件

1. [安装][1]
(http://jimshen.com/index.php/2021/04/09/windows-mysql-5-5-install)
2. 操作
	* MySQL服务启停:使用管理员打开CMD
		(1) 启动MySQL: net start mysql
		(2) 关闭MySQL: net stop mysql
	* MySQL登录({xxx}为占位符)
		(1)mysql -u{root} -p{密码}
		(2)mysql --host={ip} --user={root} --password={连接目标的密码}
	* MySQL退出
		(1)exit
		(2)quit
   * MySQL的目录结构
   		(1)安装目录: basedir="D:/dev/MySQL/MySQL Server 5.5/"
			配置文件:my.ini
		(2)MySQL数据目录:basedir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
			该目录下,一个文件夹是一个数据库,里面一个文件对应一张表

三、SQL概念

1. 什么是SQL?
	Structured Query Language:结构化查询语言
	其实就是定义了操作所有关系型数据库的规则。
	每一种数据库操作的方式存在不一样的地方,称为"方言"(dialogue)。
2. SQL通用语法
	(1SQL语句可以单行或多行书写,以分号结尾。
	(2)可以使用空格和缩进来增强语句的可读性
	(3)MySQL数据库的SQL语句不区分大小写,关键字建议使用大写。
	(4)注释(3种):
		* 单行注释: -- 注释内容
		* 多行注释: /* 注释 */
		* mysql特有: # 注释内容
3. SQL分类
	(1)DDL(Data Definition Language) 数据定义语言
		用来定义数据库对象:数据库,表,列等。关键字:createdropalter等
	(2)DML(Data Manipulation Language) 数据操作语言
		用来对数据库中表的数据进行增删改查。关键字:insertdeleteupdate等
	(3)DQL(Data Query Language)数据查询语言
		用来查询数据库中表的记录(数据)。关键字:selectwhere等
	(4)DCL(Data Control Language)数据控制语言
		用来定义数据库的访问权限和安全级别,以及创建用户。关键字:grantrevoke

1. DDL: 操作数据库、表

(1) 操作数据库:CRUD

	 a)C(Create):创建
		* 创建数据库:
			`CREATE DATABASE 数据库名称;`
			`CREATE DATABASE IF NOT EXISTS 数据库名称;`
			`CREATE DATABASE 数据库名称 CHARACTER SET 字符集名称`
		例如:创建test数据库,判断是否存在,并指定字符集为utf8
			`CREATE DATABASE IF NOT EXISTS TEST CHARACTER SET UTF8`

	 b)R(Retrieve):查询
		* 查询所有数据库的名称:
			`show databases;`
		* 查询某个数据库的字符集、查询某个数据库的创建语句
			`show create database {数据库名称}`
	 c)U(Update):修改
		* 修改数据库的字符集
			`alter database {数据库名称} character set {字符集名称};`
	 d)D(Delete):删除
		* 删除数据库、如果数据库存在则删除
			`drop database {数据库名称};`
			`drop database if exists {数据库名称}`
	 e)使用数据库
		* 查询当前正在使用的数据库名称
			`select database();`
		* 使用数据库
			`use {数据库名称};`

(2) 操作表

   a)创建 & 常用数据类型:
		* 基本语法
			创建:`create table {表名}(列名1 数据类型1, ..., 列名2 数据类型2);`
			复制: `create table {表名} like {被复制的表名};`
		* 例子:
			`create table student (
				id int,
				name varchar(32),
				age int,
				score double(4,1),
				birthday date,
				insert_time timestamp
			);`
			
			/* 
			  数据库类型:
					1. int:整数类型
						* age int,
					2. double:小数类型
						* score double(5,2)   //最大值999.99 (总位数,小数点后面的位数)
					3. date:日期,只包含年月日,yyyy-MM-dd
					4. datetime:日期,包含年月日时分秒	 yyyy-MM-dd HH:mm:ss
					5. timestamp:时间戳类型	包含年月日时分秒	 yyyy-MM-dd HH:mm:ss	
						* 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值

					6. varchar:字符串
						* name varchar(20):姓名最大20个字符
						* zhangsan 8个字符  张三 2个字符
				*/
				
		b)R 查询
			* 查询某个数据库中所有表的名称
				show tables;
			* 查询表结构
				desc 表名;
				
		c)M 修改
			* 表名
				alter table 表名 rename to 新表名
			* 字符集
				alter table 表名 character set 字符集名称
				例:
				alter table stu character set utf8;
			* 添加列
				alter table 表名 add 列名 数据类型
			* 修改列
				alter table 表名 change 列名 新列名 新类型   -- 修改列名和类型
				alter table 表名 modify 列名 新类型 -- 仅修改字段的类型
				alter table 表名 drop primary key, add primary key(列名1,列名2,..) -- 修改表的主键
			* 删除列
				alter table 表名 drop 要删除的列名
		
		d)D 删除
			* 删除数据表
			drop table 表名;
			drop table if exists 表名;
			
			

2. DML: 增删改表中数据

(1) 添加数据

语法:
insert into 表名 (列名1, 列名2, ..., 列名n) values (1,2, ..., 值n);
/* 注意
	** 列名与值一一对应
	** 如果表名后,不定义列名,则默认给所有列添加值:insert into 表名 values(列值...)
	** 除了数字类型,其他类型都需要使用引号引起来
*/

例:
insert into student (id,name,age) values (1,'shen',28);

(2) 删除数据

语法:
delete from 表名 [where 条件]

/* 注意:
	** 如果不加条件,则删除表中所有记录
	** 如果要删除所有记录 */
		a) delete from 表名;  -- 不推荐使用,有多少条记录就会执行多少次删除操作
		b) trunk table 表名;  -- 推荐,效率更高,先删除表,然后再创建一张一样的表

(3) 修改数据

语法:
update 表名 set 列名1=1,列名2=2, ..., 列名n=值n [where 条件]

/** 注意:
		** 如果不加条件,会将表中所有记录全部修改
*/

3. DQL: 查询表中的记录

(1) 语法

select 
	字段列表
from
	表名列表
where
	条件列表
group by
	分组字段
having
	分组之后的条件
order by
	排序
limit
	分页限定

(2) 基础查询

a) 多个字段的查询
	select 字段名1,字段名2,... from 表名;
	-- 注意:如果查询所有字段,则可以使用*来替代字段列表
b) 去除重复的结果集
	distinct
	例:select name,age from xxx; -- 会对name+age进行去重
	
c) 计算列
	-- 一般可以使用四则运算计算一些列的值(一般只会进行数值型的计算)
	-- ifnull(expr1, expr2) : null参与的运算,计算结果都为null
		-- expr1: 哪个字段需要判断是否为null
		-- expr2: default value
d) 别名
		as
		-- 可省略

(3) 条件查询

a) where子句后跟条件
b)运算符
      * ><<=>==<>
			* BETWEEN...AND    [a,b]
			* IN( 集合) 
			* LIKE:模糊查询
				* 占位符:
					* _:单个任意字符    一个字符
					* %:多个任意字符   字符数(0~x)
			* IS NULL  
			* and&&
			* or|| 
			* not!
			
	  -- 注意:null值不能使用=或!=判断
			

(4) 排序查询

语法:order by子句
order by 排序字段1 排序方式1, 排序字段2 排序方式2, ...

排序方式:
asc:升序,默认
desc:降序

-- 注意:如果有多个排序条件,则当前面的条件值一样时,才会去判断第二个条件

(5) 聚合函数

将一列数据作为一个整体进行纵向的计算
-- 聚合函数的计算,排除null值,即不会将null纳入其中计算

count:计算个数
	-- 一般选择非空的列:主键
	-- count(*) :只要一行中,至少有一列非null,则会纳入计算
max: 计算最大值
min: 计算最小值
sum: 计算和
avg: 计算平均值

(6) 分组查询

语法:group by 分组字段

-- 注意:
	-- 分组之后查询的字段:分组字段、聚合函数 (select中的字段)
	-- where和having的区别?
		a) where在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足条件,则不会被查询出来(where对行过滤,having对分的组过滤)
		b) where后不可以跟聚合函数,having可以进行聚合函数的判断
		
例:
	--  按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组,分组之后。人数要大于2个人
	select gender, avg(math) avg, count(id) count from stu where math > 70 group by gender having count > 2;
	

(7) 分页查询

语法:limit 开始的索引,每页查询的条数  (mysql方言)

公式:开始的索引 =(当前的页码 - 1* 每页显示的条数
例:
select * from stu limit 0,3; -- 第一页
select * from stu limit 3,3; -- 第二页

四、 约束

1. 概念

对表中数据进行限定,保证数据的正确性、有效性和完整性

2. 分类

  • 主键约束 primary key
  • 非空约束 not null
  • 唯一约束 unique
  • 外键约束 foreign key

3. 非空约束 not null

not null 某一列的值不能为null

添加约束:
(1)  在创建表时添加
	create table stu(
  	id int,
    name varchar(20) not null -- name为非空
  );2) 创建表完后,添加
	alter table stu modify name varchar(20) not null; -- 字段类型修改+约束3) 删除name的非空约束
	alter table stu modify name varchar(20); -- 字段修改,不加约束

4. 唯一约束 unique

unique,某一列的值不能重复

-- 注意:唯一约束可以有null值,但是只能有一条记录为null
添加约束:
(1) 创建表时添加约束
	create table stu(
  	id int,
    phone_number varchar(20) unique
  );2) 创建完后添加
	alter table stu modify phone_number varchar(20) unique;3) 删除唯一键
  alter table drop index phone_number;

5. 主键 primary key

5.1 主键就是表中记录的唯一标识(非空且唯一)

-- 注意:一张表只能有一个字段为主键 ?
添加约束
(1) 创建表时添加约束
	create table stu(
  	id int primary key,
    name varchar(20)
  );2) 创建后添加约束
	alter table modify id int primary key;3) 删除主键
  alter table drop primary key;

5.2 自动增长:如果某一列是数值类型的,使用auto_increment,可以来完成值的自动增长

-- 默认从1开始增长,每次加11) 创建
	create table stu(
  	id int primary key auto_increment,
    name varchar(20)
  );2) 创建后添加
	alter table stu modify id int auto_increment;3) 删除
	alter table stu modify id int;   -- 不会删除主键,会将自增长删除

五、 多表查询

-- 准备sql
-- 创建部门表
	CREATE TABLE dept(
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(20)
	);
	INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
		
-- 创建员工表
	CREATE TABLE emp (
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(10),
			gender CHAR(1), -- 性别
			salary DOUBLE, -- 工资
			join_date DATE, -- 入职日期
			dept_id INT,
			FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键)
	);
	
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);

1. 笛卡尔积

  • 有两个集合A, B,取这两个集合的所有组成情况
  • 要完成多表查询,需要消除无用的数据

2. 内连接查询

2.1 隐式内连接

使用where条件消除无用数据

-- 例:查询员工表的名称,性别,部门表的名称
SELECT 
			t1.name, -- 员工表的姓名
			t1.gender,-- 员工表的性别
			t2.name -- 部门表的名称
FROM
			emp t1,
			dept t2
WHERE 
			t1.`dept_id` = t2.`id`;

2.2 显示内连接

-- 语法:select 字段列表 from 表名1 [inner] join 表名2 on 条件
-- 例:
SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;	
SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;	

注意:

  • 从哪写表中查数据
  • 连接条件是什么
  • 查询哪些字段

3. 外连接查询

3.1 左外连接

-- 语法:select 字段列表 from 表1 left [outer] join 表2 on 条件;
-- 查询的是左表所有数据以及其交集部分
-- 例:
-- 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称
SELECT t1.*,t2.name FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;

3.2 右外连接

-- 语法:select 字段列表 from 表1 right [outer] join 表2 on 条件;
-- 查询的是右表所有数据以及其交集部分
-- 例:
SELECT 	* FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;

4. 子查询

4.1 子查询的结果是单行单列的

  • 子查询可以作为条件,使用运算符去判断。> >= < <= =
-- 例:查询员工工资小于平均工资的人
select * from emp where emp.salary < (select avg(salary) from emp)

4.2 子查询的结果是多行多列的

  • 子查询可以作为条件,使用运算符in来判断
-- 查询'财务部'和'市场部'所有的员工信息
select id from dept where name='财务部' name='市场部';
select * from emp where dept_id=3 or dept_id=2;
-- 子查询
select * from emp where dept_id in (select id from dept where name='财务部' name='市场部');

4.3 子查询的结果是多行多列的

  • 子查询可以微微一张虚拟表参与查询(子查询或内连接)
-- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息
-- 子查询
SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 WHERE t1.id = t2.dept_id;
					
-- 普通内连接
SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` >  '2011-11-11'

六、 事务

1. 概念

  • 如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。

2. 操作

  • 开启事务:start transaction

  • 回滚:rollback

  • 提交:commmit

-- 例:转账
CREATE TABLE account (
				id INT PRIMARY KEY AUTO_INCREMENT,
				NAME VARCHAR(10),
				balance DOUBLE
			);
-- 添加数据
INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);
SELECT * FROM account;
UPDATE account SET balance = 1000;


-- 张三给李四转账 500 元			
	-- 0. 开启事务
	START TRANSACTION;
		-- 1. 张三账户 -500
		UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
		
		-- 2. 李四账户 +500
		-- 中间过程是否出错了...
		UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi'; -- 成功
		
		-- 发现执行没有问题,提交事务
			COMMIT;

	  -- 发现出问题了,回滚事务
			ROLLBACK;

3. 数据库事务的提交方式

  1. 事务提交的两种方式:

    • 自动提交:
      • mysql就是自动提交的
      • 一条DML(增删改)语句会自动提交一次事务。
    • 手动提交:
      • Oracle 数据库默认是手动提交事务
      • 需要先开启事务,再提交
  2. 查看事务的默认提交方式:

    SELECT @@autocommit; – 1 代表自动提交 0 代表手动提交

  3. 修改默认提交方式:

    set @@autocommit = 0;

4. 事务的四大特征

  • 原子性:

    ​ 是不可分割的最小操作单位,要么同时成功,要么同时失败

  • 持久性

    ​ 当提交或回滚后,数据库会持久化保存的数据

  • 隔离性

    ​ 多个事务之间,相互独立

  • 一致性

    ​ 事务操作前后,数据总量不变

5. 事务的隔离级别

  • 概念:多个事务之间是隔离、相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题

  • 存在的问题:

    • 脏读:一个事务,读取到另一个事务中没有提交的数据
    • 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样
    • 幻读:一个事务操作(dml)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
  • 隔离级别

    • read uncomitted:读未提交
      • 产生的问题:脏读、不可重复读
    • read committed: 读已提交 (oracle默认)
      • 产生的问题:不可重复读,幻读
    • repeatable read:可重复读 ( mysql默认)
      • 产生的问题:幻读
    • serializable:串行化
      • 可解决所有问题

    – 隔离级别从小到大,安全性越来越高,但是效率越来越低

  • 隔离级别修改

    • 查询
      • select @@tx_isolation;
    • 修改
      • set global transaction isolation level 级别字符串;

七、JDBC

1. 概念

  • Java DataBase Connectivity: java 数据库连接
    官方定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。

2. 导入依赖

<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
</dependencies>

3. 步骤

// 1. 导入jar包
// 2. 注册驱动 8.0以前使用com.mysql.jdbc.Driver
Class.forName('com.mysql.cj.jdbc.Driver');
// 3. 获取数据库连接对象 8.0后需要在url中增加参数 useSLL
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname?userSSL=false", "root", "root");
// 4. 定义sql语句
String sql = "update account set balance = 500 where id = 1";
String preSql = "update account set balance = ? where id = ?";
// 5. 获取执行sql的对象 statement
Statement stmt = conn.createStatement();
PreparedStatement pstmt = conn.preparedStatement(preSql);
// 6. 执行sql
int count = stmt.executeUpdate(sql);
int count = pstmt.executeUpdate(sql);
// 7. 封装结果集
// 8. 释放资源
stmt.close();
conn.close();

4. 实际例子

// 新增数据
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false", "root", "123456");
Statement statement = connection.createStatement();
String sql = "insert into user values (1, 'jimmy', '123')";
int count = statement.executeUpdate(sql);
System.out.println("affected rows " + count);
statement.close();
connection.close();
// 预编译修改数据
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false", "root", "123456");
String psql = "update user set password = ? where id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(psql);
preparedStatement.setString(1, "12345"); // 参数索引从1开始
preparedStatement.setInt(2, 1);
int count = preparedStatement.executeUpdate();
System.out.println("affected rows " + count);
preparedStatement.close();
connection.close();
// 查询
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false", "root", "123456");
String sql = "select id, username, password from user";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
    User user = new User();
    user.setId(rs.getInt("id"));
    user.setUsername(rs.getString("username"));
    user.setPassword(rs.getString("password"));
    System.out.println(user);
}
rs.close();
preparedStatement.close();
connection.close();

更新日志

【2021/11/11】DDL 补充修改数据表主键语法例子
【2021/11/14】增加jdbc 插入、更新、查询例子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值