ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL数据库

2021-05-14 20:58:48  阅读:1022  来源: 互联网

标签:INSERT -- 数据库 查询 MySQL id SELECT


MySQL基础和SQL入门

数据库的基本概念

什么是数据库

1、数据库(DataBase) 就是存储和管理数据的仓库

2、本质上是一个文件系统,还是以文件的方式,将数据保存在电脑上

为什么使用数据库

数据存储方式的比较

存储方式优点缺点
内存速度快不能够永久保存,数据是临时状态
文件数据是可以永久保存使用IO流操作文件,不方便
数据库1.数据可以永久保存
2.方便存储和管理数据
3.使用统一的方式操作数据库(SQL)
占用资源,有些数据库需要付费(比如Oracle数据库)

通过上面的比较,我们可以看出,使用数据库存储数据,用户可以非常方便对数据库中的数据进行增加,删除,修改及查询操作。

常见的数据库

数据库名介绍
MySql数据库开源免费的数据库
因为免费开源、运作简单的特点,常作为中小型的项目的数据库首选。MySQL1996年开始运作,目前已经被Oracle公司收购了.MySQL6.x开始收费
Oracle数据库收费的大型数据库,Oracle公司的核心产品。 安全性高
DB2IBM公司的数据库产品,收费的超大型数据库。常在银行系统中使用
SQL ServerMicroSoft 微软公司收费的中型的数据库。
C#、.net等语言常使用。但该数据库只能运行在windows机器上,扩展性、稳定性、安全性、性能都表现平平。

MySQL的安装及配置

安装MySQL

卸载MySQL

MySQL环境变量配置

MySQL的启动与关闭

方式一 : window服务启动 MySQL
  1. 右键此电脑 --> 管理

  2. 选择服务–> 找到MysQL服务

  3. 右键选择 --> 启动或停止

方式二: DOS 命令方式启动
  1. 首先以管理员身份 打开命令行窗口

  2. 启动MySql — net start mysql57

  3. 关闭MySql — net stop mysql57

命令行登录数据库

​ MySQL是一个需要账户名密码登录的数据库,登陆后使用,它提供了一个默认的root账号,使用安装时设置的密码即可登录。

命令说明
mysql -u 用户名 -p 密码使用指定用户名和密码登录当前计算机中的MySQL数据库
mysql -h 主机IP -u 用户名 -p 密码-h 指定IP方式,进行登录

命令演示:

mysql -uroot -p123456
mysql -h127.0.0.1 -uroot -p123456

退出命令:
exit/quit

SqlYog的使用

简介

​ SQLyog是业界著名的Webyog公司出品的一款简洁高效、功能强大的图形化MySQL数据库管理工具。使用 SQLyog 可以快速直观地让您从世界的任何角落通过网络来维护远端的 MySQL 数据库。

MySql的目录结构

MySQL安装目录

MySql的默认安装目录在 C:\Program Files\MySQL\MySQL Server 5.7

目录目录内容
bin放置一些可执行文件(如:mysql.exe)
docs文档
include包含(头)文件
lib依赖库
share用于存放字符集、语言等信息
MySQL配置文件 与 数据库及 数据表所在目录

默认数据文件在C:\ProgramData\MySQL\MySQL Server 5.7

1、my.ini 文件 是 mysql 的配置文件,一般不建议去修改

2、Data<目录> Mysql管理的数据库文件所在的目录(数据库和数据表信息)

3、几个概念

数据库: 文件夹
数据表: 文件
数据: 文件中的记录

数据库管理系统

什么是数据库管理系统 ?

​ 数据库管理系统(DataBase Management System,DBMS):指一种操作和管理维护数据库的大型软件。
MySQL就是一个数据库管理系统软件,安装了Mysql的电脑,我们叫它数据库服务器。

数据库管理系统的作用

​ 用于建立、使用和维护数据库,对数据库进行统一的管理。

数据库管理系统、数据库 和表之间的关系

​ MySQL中管理着很多数据库,在实际开发环境中一个数据库一般对应一个应用,数据库当中保存着多张表,每一张表对应着不同的业务,表中保存着对应业务的数据。

数据库表

​ 数据库中以表为组织单位存储数据,表类似我们Java中的类,每个字段都有对应的数据类型。

使用Java程序来与关系型数据对比:

类 -----> 表

类中属性 ----> 表中字段

对象 ---> 数据记录

SQL(重点)

SQL的概念

​ 结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。

SQL 的作用

1、是所有关系型数据库的统一查询规范,不同的关系型数据库都支持SQL
2、所有的关系型数据库都可以使用SQL
3、不同数据库之间的SQL有一些区别——方言

SQL通用语法

1、SQL语句可以单行 或者 多行书写,以分号 结尾 ; (Sqlyog中可以不用写分号)
2、可以使用空格和缩进来增加语句的可读性。
3、MySql中使用SQL不区分大小写,一般关键字大写,数据库名 表名列名 小写。
4、注释方式

注释语法说明
– 空格单行注释
/* */多行注释
#MySql特有的单行注释
show databases; #单行注释
show databases; -- 单行注释
show databases; /* 多行注释 */

SQL的分类

分类说明
数据定义简称DDL(Data Definition Language),用来定义数据库对象:数据库,表,列等
数据操作简称DML(Data Manipulation Language),用来对数据库中表的记录进行更新
数据查询简称DQL(Data Query Language),用来查询数据库中表的记录
数据控制简称DCL(Data Control Language),用来定义数据库的访问权限和安全级别,及创建用户(了解)

DDL 操作数据库

创建数据库
命令说明
create database 数据库名;创建指定名称的数据库
create database 数据库名 character set 字符集;创建指定名称的数据库,并且指定字符集(一般都指定utf-8)
/*
    对数据库操作的分类
	CRUD
	C create 创建
	R retrieve 查询
	U update 修改
	D delete 删除
	使用数据库
*/	
/*
    创建数据库 方式1:指定名称的数据库
    latin1 编码
*/
CREATE DATABASE db1;

/*
    方式2:指定字符集创建数据库
    utf8
*/
CREATE DATABASE db1_1 CHARACTER SET utf8;
查看/选择数据库
命令说明
use 数据库切换数据库
select database();查看当前正在使用的数据库
show databases;查看Mysql中都有哪些数据库
show create database 数据库名;查看一个数据库的定义信息
/*
    查看数据库
*/
# 切换数据库
USE db1_1;

# 查询当前正在使用的数据库
SELECT DATABASE();

# 查询MySQL中都有哪些数据库
SHOW DATABASES;

# 查看一个数据库的定义信息
SHOW CREATE DATABASE db1;
修改数据库
命令说明
alter database 数据库名 character set 字符集;数据库的字符集修改操作
-- 修改数据库字符集
-- 语法格式: alter database 数据库名 character set utf8
ALTER DATABASE db1 CHARACTER SET utf8;

-- 查询当前数据库的基本信息
SHOW CREATE DATABASE db1;
删除数据库
命令说明
drop database 数据库名从MySql中永久的删除某个数据库
-- 删除数据库
-- 语法格式:drop database 数据库名称	将数据库从MySql中永久删除
DROP DATABASE db1_1;	-- 慎用

DDL 操作数据表

MySQL常见的数据类型

1、常用的数据类型:

类型描述
int整型
double浮点型
varchar字符串型
data日期类型,给是为 yyyy-MM-dd ,只有年月日,没有时分秒
/*
	创建表的语法格式
	    create table 表名(
		字段名称 字段类型(长度),
		字段名称2 字段类型,
		字段名称3 字段类型	最后一个字段不要加逗号
	    );
	    
	 MySQL中常见的数据类型
	 int 整型
	 double 浮点型
	 varchar 字符串类型
	 date 日期类型 只显示年月日 没有时分秒 yyyy-MM-dd
	 datetime 年月日时分秒 yyyy-MM-dd HH:mm:ss
	 char 类型 在MySQL中char 类型也代表字符串
*/

2、详细的数据类型(了解即可)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GktxCd5r-1620996416221)(E:\MarkDown\拉勾笔记\MySQL数据类型)]

3、注意:

​ MySQL中的 char类型与 varchar类型,都对应了Java中的字符串类型,区别在于:

​ char类型是固定长度的: 根据定义的字符串长度分配足够的空间。
​ varchar类型是可变长度的: 只使用字符串长度所需的空间

比如:保存字符串 “abc”

x char(10)	占用10个字节
y varchar(10)	占用3个字节

4、使用场景

​ char类型适合存储 固定长度的字符串,比如 密码 ,性别一类
​ varchar类型适合存储 在一定范围内,有长度变化的字符串

创建表

1、语法格式:

CREATE TABLE 表名(
    字段名称1 字段类型(长度),
    字段名称2 字段类型 注意 最后一列不要加逗号
);

2、需求1: 创建商品分类表

表名:category
表中字段:
分类ID :cid ,为整型
分类名称:cname,为字符串类型,指定长度20

3、SQL实现

-- 创建商品分类表
/*
	表名 category
	    cid int 分类id
	    cname varchar 分类的名称
*/

-- 选择要使用的数据库
USE db1;

-- 创建分类表
CREATE TABLE category(
	cid INT,
	cname VARCHAR(20)
);

4、需求2: 创建测试表

表名: test1
表中字段:
    测试ID : tid ,为整型
    测试时间: tdate , 为年月日的日期类型

5、SQL实现

-- 创建测试表
/*
	表名 test1
	    tid int
	    tdate date
*/
CREATE TABLE test1(
	tid INT,
	tdate DATE
);

6、需求3: 快速创建一个表结构相同的表(复制表结构)

语法格式:

create table 新表明 like 旧表名
-- 快速创建一个表结构相同的表(复制表结构)
-- 语法结构 create table 新表明 like 旧表名

-- 创建一个与test1表结构相同的 test2表
CREATE TABLE test2 LIKE test1;

-- 查看表结构
DESC test2;
查看表
命令说明
show tables;查看当前数据库中的所有表名
desc 表名;查看数据表的结构
-- 查看表
-- 查看当前数据库中所有的表
SHOW TABLES;

-- 查看创建表的 sql语句
SHOW CREATE TABLE category;

-- 查看表结构
DESC category;
删除表
命令说明
drop table 表名;删除表(从数据库中永久删除某一张表)
drop table if exists 表名;判断表是否存在, 存在的话就删除,不存在就不执行删除
/*
	表的删除
	语法格式
	    drop table 表名; 从数据库中永久删除一张表
	    drop table if exists 表名; 判断表是否存在,如果存在就删除,不存在就不执行删除
*/

-- 删除test1表
DROP TABLE test1;

-- 使用先判断后删除方式
DROP TABLE IF EXISTS test2;
修改表

1、修改表名

语法格式

rename table 旧表名 to 新表名

2、修改表的字符集

语法格式

alter table 表名 character set 字符集

3、向表中添加列,关键字 ADD
语法格式:

alert table 表名 add 字段名称 字段类型

4、修改表中列的数据类型或长度,关键字 MODIFY
语法格式:

alter table 表名 modify 字段名称 字段类型

5、修改列名称,关键字 CHANGE
语法格式:

alter table 表名 change 旧列名 新列名 类型(长度);

6、删除列,关键字 DROP
语法格式:

alter table 表名 drop 列名;
/*
	修改表的名称
	修改表的字符集
	修改标中的某一项(数据类型 名称 长度)
	向表中添加一列
	删除表中的某一项
*/

-- 修改表名称 语法格式:rename table 旧表名 to 旧表名
RENAME TABLE category TO category1;

-- 修改表的字符集为 gbk
-- 语法格式:alter table 表名 character set 字符集
ALTER TABLE category1 CHARACTER SET gbk;

-- 向表中添加一个字段 关键字:add
-- 语法格式:alter table 表名 add 字段名称 字段类型(长度)
-- 添加分类描述字段
ALTER TABLE category1 ADD cdesc VARCHAR(`category1`20);

-- 修改表中列的类型或长度
-- 语法格式 alter table 表名 modify 字段名称 字段类型
-- 修改cdesc 字段长度为 50
ALTER TABLE category1 MODIFY cdesc VARCHAR(50);	-- 修改字段长度
ALTER TABLE category1 MODIFY cdesc CHAR(20);	-- 修改字段类型

-- 修改列的名称	关键字:change
-- 语法格式:alter table 表名 change 旧列名 新列明 类型(长度)
-- 修改cdesc字段 名称改为 description varchar(30)
ALTER TABLE category1 CHANGE cdesc description VARCHAR(30);

-- 删除列 关键字:drop
-- 语法格式:alter table 表名 drop 列名
ALTER TABLE category1 DROP description;

DML 操作表中数据

SQL中的DML 用于对表中的数据进行增删改操作

插入数据

语法格式:

insert into 表名 (字段名1,字段名2...) values(字段值1,字段值2...);

1、代码准备,创建一个学生表:

表名:student
表中字段:
    学员ID, sid int
    姓名, sname varchar(20)
    年龄, age int
    性别, sex char(1)
    地址, address varchar(40)

2、向学生表中添加数据,3种方式

方式1: 插入全部字段, 将所有字段名都写出来

方式2: 插入全部字段,不写字段名

方式3:插入指定字段的值

3、注意:

a、值与字段必须要对应,个数相同&数据类型相同
b、值的数据大小,必须在字段指定的长度范围内

c、varchar char date类型的值必须使用单引号,或者双引号 包裹
d、如果要插入空值,可以忽略不写,或者插入null
e、如果插入指定字段的值,必须要上写列名

/*
	DML 对表中数据进行 增删改
	增加
	    语法格式:insert into 表名 (字段名1,字段名2...) values(字段值1,字段值2...)
*/
-- 创建学生表
CREATE TABLE student(
	sid INT,
	sname VARCHAR(20),
	age INT,
	sex CHAR(1),
	address VARCHAR(40)
);


-- 向学生表中插入数据
-- 方式1:插入全部字段, 将所有字段名都写出来
INSERT INTO student (sid,sname,age,sex,address) VALUES(1,'孙悟空',18,'男','花果山');

-- 方式2:插入全部字段,不写字段名
INSERT INTO student VALUES(2,'孙悟饭',5,'男','地球');

-- 方式3:插入指定字段的值
INSERT INTO student (sid,sname) VALUES(3,'蜘蛛精');

-- 注意事项
	-- 1.值与字段必须对应,个数、数据类型、长度都必须一致
	INSERT INTO student (sid,sname,age,sex,address) VALUES(4,'孙悟空',18,'男','花果山');
	-- 2.在插入 varchar char date 类型的时候,必须要使用 单引号 或者双引号进行包裹
	INSERT INTO student (sid,sname,age,sex,address) VALUES(4,'孙悟空',18,'男','花果山');
	-- 3.如果要插入空值,可以忽略不写,或者写null
	INSERT INTO student (sid,sname) VALUES(5,'唐僧');
	INSERT INTO student (sid,sname,age,sex,address) VALUES(6,'八戒',NULL,NULL,NULL);
更改数据

语法格式1:不带条件的修改

update 表名 set 列名 = 值

语法格式2:带条件的修改

update 表名 set 列名 = 值 [where 条件表达式:字段名 = 值 ]
/*
	修改操作
	    语法格式1:update 表名 set 列名 = 值
	    语法格式2:update 表名 set 列名 = 值 [where 条件表达式:字段名 = 值 ]
*/

-- 修改表中的所有学生性别为女
UPDATE student SET sex = '女';		-- (慎用!!)

-- 带条件的修改 将sid为 1的数据,性别改为男
UPDATE student SET sex = '男' WHERE sid = 1;

-- 一次性修改多个列
-- 修改sid为 5的这条数据,年龄改为20,地址改为 大唐
UPDATE student SET age = 20, address = '大唐' WHERE sid = 5;
删除数据

语法格式1:删除所有数据

delete from 表名

语法格式2: 指定条件 删除数据

delete from 表名 [where 字段名 = 值]
/*
	删除
	    语法格式1:delete from 表名
	    语法格式2:delete from 表名 [where 字段名 = 值]
*/

-- 删除sid为 6的数据
DELETE FROM student WHERE sid = 6;

-- 删除所有数据
DELETE FROM student;

-- 删除所有数据的方式:两种
	-- 1.delete from 表; 不推荐,对表中的数据逐条删除,效率低
	-- 2.truncate table 表; 推荐,删除整张表然后再创建一个一模一样的新表

INSERT INTO student VALUES(1,'孙悟空',20,'男','花果山');
TRUNCATE TABLE student;

DQL 查询表中数据

准备数据
-- 员工表 emp
CREATE TABLE emp(
	eid INT,
	ename VARCHAR(20),
	sex CHAR(1),
	salary DOUBLE,
	hire_date DATE,
	dept_name VARCHAR(20)
);

#添加数据
INSERT INTO emp VALUES(1,'孙悟空','男',7200,'2013-02-04','教学部');
INSERT INTO emp VALUES(2,'猪八戒','男',3600,'2010-12-02','教学部');
INSERT INTO emp VALUES(3,'唐僧','男',9000,'2008-08-08','教学部');
INSERT INTO emp VALUES(4,'白骨精','女',5000,'2015-10-07','市场部');
INSERT INTO emp VALUES(5,'蜘蛛精','女',5000,'2011-03-14','市场部');
INSERT INTO emp VALUES(6,'玉兔精','女',200,'2000-03-14','市场部');
INSERT INTO emp VALUES(7,'林黛玉','女',10000,'2019-10-07','财务部');
INSERT INTO emp VALUES(8,'黄蓉','女',3500,'2011-09-14','财务部');
INSERT INTO emp VALUES(9,'吴承恩','男',20000,'2000-03-14',NULL);
INSERT INTO emp VALUES(10,'孙悟饭','男', 10,'2020-03-14','财务部');
简单查询

查询不会对数据库中的数据进行修改,只是一种显示数据的方式 SELECT

语法格式

select 列名 from 表名
/*
	DQL
	    简单查询
		select 列名 from 表名;
*/

-- 查询emp 表中的所有数据
SELECT * FROM emp;	-- * 表示所有的列

-- 查询所有数据 只显示 id 和 name
SELECT eid, ename FROM emp;

-- 查询所有的数据,然后给列名 改为中文
SELECT * FROM emp;

-- 别名查询 使用关键字 as
SELECT 
	eid AS '编号',
	ename AS '姓名',
	sex AS '性别',
	salary AS '薪资',
	hire_date AS '入职时间',
	dept_name '部门名称'	-- as 可以省略
FROM emp;

-- 查询一共有几个部门
SELECT dept_name FROM emp;;
-- 去重操作 关键字:distinct
SELECT DISTINCT dept_name FROM emp;

-- 将员工薪资数据 +1000
SELECT ename, salary+1000 AS salary FROM emp;

-- 注意:查询操作不会对数据库中的数据进行修改,只是一致显示的方式
条件查询

如果查询语句中没有设置条件,就会查询所有的行信息,在实际应用中,一定要指定查询条件,对记录进行过滤
语法格式

select 列名 from 表名 where 条件表达式

* 先取出表中的每条数据,满足条件的数据就返回,不满足的就过滤掉
运算符

1、 比较运算符

运算符说明
> < <= >= = <> !=大于、小于、大于(小于)等于、不等于
BETWEEN …AND…显示在某一区间的值。例如: 2000-10000之间: Between 2000 and 10000
IN(集合)集合表示多个值,使用逗号分隔,例如: name in (悟空,八戒)
in中的每个数据都会作为一次条件,只要满足条件就会显示
LIKE ‘%张%’模糊查询
IS NULL查询某一列为NULL的值, 注: 不能写 = NULL

2、 逻辑运算符

运算符说明
And &&多个条件同时成立
Or ||多个条件任一成立
Not不成立,取反

3、模糊查询 通配符

通配符说明
%表示匹配任意多个字符串
_表示匹配一个字符
/*
	条件查询
	语法格式:select 列名 from 表名 where 条件表达式
	
	比较运算符
	    >  <  <=  >=  =  <>  !=
	    BETWEEN  ...AND...
	    IN(集合)
	    LIKE
	    IS NULL
	逻辑运算符
	    AND &&
	    Or  ||
	    Not
*/

# 查询员工姓名为黄蓉的员工信息
-- 1.查哪张表	2.查哪些字段	3.查询条件
SELECT * FROM emp WHERE ename = '黄蓉';

# 查询薪水价格为5000的员工信息
SELECT * FROM emp WHERE salary = 5000; 

# 查询薪水价格不是5000的所有员工信息
SELECT * FROM emp WHERE salary != 5000;
SELECT * FROM emp WHERE salary <> 5000;

# 查询薪水价格大于6000元的所有员工信息
SELECT * FROM emp WHERE salary > 6000;

# 查询薪水价格在5000到10000之间所有员工信息
SELECT * FROM emp WHERE salary BETWEEN 5000 AND 10000;
SELECT * FROM emp WHERE salary >= 5000 AND salary <= 10000;

# 查询薪水价格是3600或7200或者20000的所有员工信息
SELECT * FROM emp WHERE salary = 3600 OR salary = 7200 OR salary = 20000;
SELECT * FROM emp WHERE salary IN(3600,7200,20000);

/*
	like '%精%'
	    % 通配符,表示匹配任意多个字符串
	    _ 通配符,表示匹配你一个字符
*/

# 查询含有'精'字的所有员工信息
SELECT * FROM emp WHERE ename LIKE '%精%';

# 查询以'孙'开头的所有员工信息
SELECT * FROM emp WHERE ename LIKE '孙%';

# 查询第二个字为'兔'的所有员工信息
SELECT * FROM emp WHERE ename LIKE '_兔%';

# 查询没有部门的员工信息
-- SELECT * FROM emp WHERE dept_name = null; 错误方式
SELECT * FROM emp WHERE dept_name IS NULL;

# 查询有部门的员工信息
SELECT * FROM emp WHERE dept_name IS NOT NULL;

-- 条件查询 先取出表中的每条数据,满足条件就返回,不满足的就过滤

MySQL单表&约束&事务

DQL操作单表

创建数据库、复制表

1、创建一个新的数据库 db2

2、将db1数据库中的emp表复制到当前db2数据库

排序

通过 ORDER BY 子句,可以将查询出的结果进行排序(排序只是显示效果,不会影响真实数据)

语法结构:

SELECT 字段名 FROM 表名 [WHERE 字段 = 值] ORDER BY 字段名 [ASC / DESC]

ASC 表示升序排序(默认)
DESC 表示降序排序
排序方式

1、单列排序

只按照某一个字段进行排序,就是单列排序

2、组合排序

同时对多个字段进行排序,如果第一个字段相同就按照第二个字段进行排序,以此类推

/*
	排序
	使用 order by 字句
	语法结构:select 字段名 from 表名 [where 字段名 = 值] order by 字段名称 [ASC/DESC]
	     ASC:升序排序(默认)
	     DESC:降序排序
*/

-- 单列排序 按照某一个字段进行排序
-- 使用salary 字段 对emp表进行排序
SELECT * FROM emp ORDER BY salary;	-- 默认升序
SELECT * FROM emp ORDER BY salary DESC;	-- 降序排序

-- 组合排序 同时对东哥字段进行排序
-- 在薪资的平思绪基础上,再取使用 id字段进行排序
SELECT * FROM emp ORDER BY salary DESC ,eid DESC;

-- 组合排序的特点:如果第一个字段值相同,就按照第二个字段进行排序

聚合函数

​ 之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对某一列的值进行计算,然后返回一个单一的值(另外聚合函数会忽略null空值);

语法结构:

SELECT 聚合函数(字段名) FROM 表名;
常用5个聚合函数
聚合函数作用
count(字段)统计指定列不为NULL的记录行数
sum(字段)计算指定列的数值和
max(字段)计算指定列的最大值
min(字段)计算指定列的最小值
avg(字段)计算指定列的平均值
/*
	聚合函数
	    作用:将一列数据作为一个整体,进行纵向计算
	常用聚合函数
		count(字段) 统计记录数
		sum(字段)   求和操作
		max(字段)   求最大值
		min(字段)   求最小值
		avg(子弹)   求平均值
	语法格式:select 聚合函数(字段名) from 表名 [where 条件]
*/

#1 查询员工总数
SELECT COUNT(*) FROM emp;
SELECT COUNT(1) FROM emp;
SELECT COUNT(eid) FROM emp;

-- count函数在统计时会忽略空值
-- 注意不要使用带空值的列进行 count
SELECT COUNT(dept_name) FROM emp;

#2 查看员工总薪水、最高薪水、最小薪水、薪水的平均值
SELECT 
	SUM(salary) AS '总薪水',
	MAX(salary) AS '最高薪水',
	MIN(salary) AS '最小薪水',
	AVG(salary) AS '平均薪水'
FROM emp;

#3 查询薪水大于4000员工的个数
SELECT COUNT(*) FROM emp WHERE salary > 4000;

#4 查询部门为'教学部'的所有员工的个数
SELECT COUNT(*) FROM emp WHERE dept_name = '教学部';

#5 查询部门为'市场部'所有员工的平均薪水
SELECT AVG(salary) FROM emp WHERE dept_name = '市场部';

分组

分组查询指的是使用 GROUP BY 语句,对查询的信息进行分组,相同数据作为一组

语法格式:

SELECT 分组字段/聚合函数 FROM 表名 GROUP BY 分组字段 [HAVING 条件];

where 与 having的区别

过滤方式特点
wherewhere 进行分组前的过滤
where 后面不能写 聚合函数
havinghaving 是分组后的过滤
having 后面可以写 聚合函数
/*
	分组查询  使用 group by 语句
	语法格式:select 分组字段/聚合函数 from 表名 group by 分组字段
*/

-- select * from emp group by sex; 没有意义,将男女分为两组后返回每组的第一个数据
-- 注意:分组的目的就是为了统计,所以一般分组会和聚合函数一起使用,单独进行分组是没有意义的

# 通过性别字段 进行分组,求各组的平均薪资
SELECT sex, AVG(salary) FROM emp GROUP BY sex;

#1.查询所有部门信息
SELECT dept_name AS '部门名称' FROM emp GROUP BY dept_name;

#2.查询每个部门的平均薪资
SELECT dept_name, AVG(salary) FROM emp GROUP BY dept_name;

#3.查询每个部门的平均薪资, 部门名称不能为null
SELECT 
	dept_name AS '部门名称',
	AVG(salary) AS '部门平均薪资'	
FROM emp 
WHERE dept_name IS NOT NULL
GROUP BY dept_name;

# 查询平均薪资大于6000的部门
-- 1.首先要分组求平均薪资
-- 2.求出 平均薪资大于6000的部门

-- 在分组之后 进行条件过滤 使用:having 判断条件

SELECT
	dept_name,
	AVG(salary) 
FROM emp
WHERE dept_name IS NOT NULL
GROUP BY dept_name HAVING AVG(salary) > 6000;

limit关键字

1、limit 关键字的作用
a、limit是限制的意思,用于限制返回的查询结果的行数 (可以通过limit指定查询多少行数据)
b、limit 语法是 MySql的方言,用来完成分页

2、语法结构

SELECT 字段1,字段2... FROM 表名 LIMIT offset , length;

3、参数说明

​ a、limit offset , length; 关键字可以接受一个 或者两个 为0 或者正整数的参数

​ b、offset 起始行数, 从0开始记数, 如果省略 则默认为 0

​ c、length 返回的行数

/*
	limit 通过limit去指定要查询的数据的条数 行数
	
	语法格式:
		select 字段 from 表名 limit offset, length;
	参数说明:
		offset:起始行数,默认从 0开始计数
		length:返回的行数(要查询几条数据)
*/

# 查询emp表中的前 5条数据
SELECT * FROM emp LIMIT 0, 5;
SELECT * FROM emp LIMIT 5;

# 查询emp表中 从第4条开始,查询6条
SELECT * FROM emp LIMIT 3, 6;

-- limit 分页操作,每页显示3条
SELECT * FROM emp LIMIT 0, 3;	-- 第一页
SELECT * FROM emp LIMIT 3, 3;	-- 第二页
SELECT * FROM emp LIMIT 6, 3;	-- 第三页	3-1=2*3=6

-- 分页公式:起始行数 = (当前页码 - 1) * 每页显示条数

SQL约束

主键约束

特点:不可重复 唯一 非空

作用:用来表示数据库中的每一条记录

/*
	约束
	    约束是指对数据进行一定的限制,来保证数据的完整性 有效性 正确性
	
	常见的约束
	    主键约束	primary key
	    唯一约束	unique
	    非空约束	not null
	    外键约束	foreign key
*/
添加主键约束

语法格式:

字段名 字段类型 primary key
删除主键约束

删除表中的主键约束 (了解)

/*
	主键约束
	    特点:不可重复   唯一   非空
	    作用:用来表示数据库中的每一条记录
	    
	语法格式:
	    字段名 字段类型 primary key
*/

-- 方式1:创建一个带有主键的表
CREATE TABLE emp2(
	-- 设置主键 唯一 非空
	eid INT PRIMARY KEY,
	ename VARCHAR(20),
	sex CHAR(1)
);

DESC emp2;

-- 方式2:创建一个带主键的表
DROP TABLE emp2;  -- 删除表

CREATE TABLE emp2(
	eid INT,
	ename VARCHAR(20),
	sex CHAR(1),
	PRIMARY KEY(eid)	-- 指定eid为主键
);

-- 方式3:创建表之后,再添加主键
CREATE TABLE emp2(
	eid INT,
	ename VARCHAR(20),
	sex CHAR(1)
);

-- 通过DDL语句 添加主键约束
ALTER TABLE emp2 ADD PRIMARY KEY(eid);

-- 删除主键 DDL语句
ALTER TABLE emp2 DROP PRIMARY KEY;
主键的自增

注: 主键如果让我们自己添加很有可能重复,我们通常希望在每次插入新记录时,数据库自动生成主键字段的值

关键字:
AUTO_INCREMENT 表示自动增长(字段类型必须是整数类型)
修改主键自增的起始值

默认地 AUTO_INCREMENT 的开始值是 1,如果希望修改起始值,请使用下面的方式

/*
	主键的自增
	    关键字:auto_increment 主键的自动增长(字段类型必须是整数类型)
*/

-- 创建主键自增的表
CREATE TABLE emp2(
	-- 主键自增
	eid INT PRIMARY KEY AUTO_INCREMENT,
	ename VARCHAR(20),
	sex CHAR(1)
);

# 添加数据 观察主键变化
INSERT INTO emp2(ename,sex) VALUES('张三','男');
INSERT INTO emp2(ename,sex) VALUES('李四','男');
INSERT INTO emp2 VALUES(NULL, '翠花', '女');
INSERT INTO emp2 VALUES(NULL, '秋艳', '女');


-- 修改主键自增的起始值

-- 重新创建主键自增的表,自定义自增的起始位置
CREATE TABLE emp2(
	eid INT PRIMARY KEY AUTO_INCREMENT,
	ename VARCHAR(20),
	sex CHAR(1)
)AUTO_INCREMENT=100;
DELETE和TRUNCATE对自增长的影响

删除表中所有数据有两种方式

清空表数据的方式特点
DELETE只是删除表中所有数据,对自增没有影响
TRUNCATEtruncate 是将整个表删除掉,然后创建一个新的表自增的主键,重新从 1开始
/*
	DELETE和TRUNCATE对自增长的影响
	
	delete删除表中所有数据,将表中所有数据逐条删除
	TRUNCATE删除表中所有数据,将整个表删除,然后再创建一个结构相同表
*/

-- delete 方式删除所有数据
DELETE FROM emp2;	-- delete 删除对自增没有影响

INSERT INTO emp2(ename,sex) VALUES('张三','男');	-- 102
INSERT INTO emp2(ename,sex) VALUES('李四','男');	-- 103

-- TRUNCATE 删除所有数据
TRUNCATE TABLE emp2;	-- 自增从1开始

INSERT INTO emp2(ename,sex) VALUES('张三','男');	-- 1
INSERT INTO emp2(ename,sex) VALUES('李四','男');	-- 2

非空约束

非空约束的特点: 某一列不予许为空

语法格式:

字段名 字段类型 not null
/*
	非空约束
	    特点:某一列不予为空
	    
	语法格式:
	    字段名 字段类型 not null
*/

CREATE TABLE emp2(
	eid INT PRIMARY KEY AUTO_INCREMENT,
	-- 将ename字段添加了非空约束
	ename VARCHAR(20) NOT NULL,
	sex CHAR(1)
);

唯一约束

唯一约束的特点: 表中的某一列的值不能重复( 对null不做唯一的判断 )

语法格式:

字段名 字段值 unique

主键约束与唯一约束的区别:

1、主键约束,唯一且不能够为空

2、唯一约束,唯一但是可以为空

3、一个表中只能有一个主键,但是可以有多个唯一约束

/*
	唯一约束
	    特点:表中的某一列不能重复(对null值不做唯一判断)
	    
	语法格式:
	    字段名 字段类型 unique
*/

-- 创建 emp3表 为ename添加唯一约束
CREATE TABLE emp3(
	eid INT PRIMARY KEY AUTO_INCREMENT,
	ename VARCHAR(20) UNIQUE,
	sex CHAR(1)
);

-- 测试唯一约束
INSERT INTO emp3 VALUES(1, '张百万', '女');

-- Duplicate entry '张百万' for key 'ename' 不能重复
INSERT INTO emp3 VALUES(2, '张百万', '女');

-- 唯一约束的值 可以为null
INSERT INTO emp3 VALUES(2,NULL, '女');

-- 主键约束与唯一约束的区别
	-- 主键约束,唯一且不能够为空
	-- 唯一约束,唯一但是可以为空
	-- 一个表中只能有一个主键,但是可以有多个唯一约束

外键约束

FOREIGN KEY 表示外键约束,将在多表中学习。

默认值

默认值约束 用来指定某列的默认值

语法格式:

字段名 字段类型 DEFAULT 默认值
/*
	默认值
	    特点:用来指定某列的默认值
	    
	语法格式:
	    字段名 字段类型 default 默认值
*/
-- 创建emp4表,指定sex默认为女
CREATE TABLE emp4(
	eid INT PRIMARY KEY,
	ename VARCHAR(20),
	sex CHAR(1) DEFAULT '女'
);

INSERT INTO emp4(eid,ename) VALUES(1, '杨幂');
INSERT INTO emp4(eid,ename) VALUES(2, '柳岩');

-- 不适用默认值
INSERT INTO emp4(eid,ename,sex) VALUES(3, '蔡徐坤','男');

数据库事务

什么是事务

​ 事务是一个整体,由一条或者多条SQL语句组成,这些SQL语句要么都执行成功,要么都执行失败,只要有一条SQL出现异常,整个操作就会回滚,整个业务执行失败。

比如: 银行的转账业务,张三给李四转账500元 , 至少要操作两次数据库, 张三 -500, 李四 + 500,这中间任何一步出现问题,整个操作就必须全部回滚, 这样才能保证用户和银行都没有损失.

回滚
即在事务运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,滚回到事务开始时的状态。(在提交之前执行)

模拟转账操作

-- 创建账户表
CREATE TABLE bankaccount(
	-- 主键
	id INT PRIMARY KEY AUTO_INCREMENT,
	-- 姓名
	NAME VARCHAR(10),
	-- 余额
	money DOUBLE
);


-- 添加两个用户
INSERT INTO bankaccount(NAME,money) VALUES('tom', 1000), ('jack', 1000);

-- tom账户 -500元
UPDATE bankaccount SET money = money - 500 WHERE NAME = 'tom';

出错了

-- Jack账户 +500元
UPDATE bankaccount SET money = money + 500 WHERE NAME = 'jack';


MySQL事务操作

MYSQL 中可以有两种方式进行事务的操作:
a、手动提交事务
b、自动提交事务

手动提交事务
语法格式
功能语句
开启事务start transaction; 或者 BEGIN;
提交事务commit;
回滚事务rollback;

START TRANSACTION

​ 这个语句显式地标记一个事务的起始点。

COMMIT

​ 表示提交事务,即提交事务的所有操作,具体地说,就是将事务中所有对数据库的更新都写到磁盘上的物理数据库中,事务正常结束。

ROLLBACK

​ 表示撤销事务,即在事务运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态。

手动提交事务流程

a、执行成功的情况: 开启事务 -> 执行多条 SQL 语句 -> 成功提交事务
b、执行失败的情况: 开启事务 -> 执行多条 SQL 语句 -> 事务的回滚

成功案例 演示
use db2;
show tables;
---------------+
| Tables_in_db2 |
+---------------+
| bankaccount   |
| emp           |
| emp2          |
| emp3          |
| emp4          |
+---------------+
start transaction;
update bankaccount set money = money - 500 where name = 'tom';
		Query OK, 1 row affected (0.11 sec)
		Rows matched: 1  Changed: 1  Warnings: 0
update bankaccount set money = money + 500 where name = 'jack';
        Query OK, 1 row affected (0.00 sec)
        Rows matched: 1  Changed: 1  Warnings: 0
commit;
		Query OK, 0 rows affected (0.13 sec)
        
事务回滚演示

​ 如果事务中,有某条sql语句执行时报错了,我们没有手动的commit,那整个事务会自动回滚。

自动提交事务

​ MySQL 默认每一条 DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,语句执行完毕 自动提交事务,MySQL 默认开始自动提交事务。
​ MySQL默认是自动提交事务

自动提交事务演示
update bankaccount set money = money + 500 where name = 'tom';

SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
取消自动提交

MySQL默认是自动提交事务,设置为手动提交

set @@autocommit=off;

SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+

update bankaccount set money = money - 500 where name = 'jack';
commit;

事务的四大特性 ACID

特性含义
原子性每个事务都是一个整体,不可再拆分,事务中所有的 SQL 语句要么都执行成功,要么都失败
一致性事务在执行前数据库的状态与执行后数据库的状态保持一致。如:转账前2个人的 总金额是2000,转账后 2 个人总金额也是2000
隔离性事务与事务之间不应该相互影响,执行时保持隔离的状态
持久性一旦事务执行成功,对数据库的修改是持久的。就算关机,数据也是要保存下的

MySQL 事务隔离级别(了解)

数据并发访问

​ 一个数据库可能拥有多个访问客户端,这些客户端都可以并发方式访问数据库。数据库的相同数据可能被多个事务同时访问,如果不采取隔离措施,就会导致各种问题,破坏数据的完整性。

并发访问会产生的问题

​ 事务在操作时的理想状态: 所有的事务之间保持隔离,互不影响。因为并发操作,多个用户同时访问同一个数据。可能引发并发访问的问题

并发访问的问题说明
脏读一个事务读取到了另一个事务中尚未提交的数据
不可重复读一个事务中两次读取的数据内容不一致,要求的是在一个事务中多次读取时数据是一致的。这是进行 update 操作时引发的问题
幻读一个事务中,某一次的 select 操作得到的结果所表征的数据状态,无法支撑后续的业务操作。查询得到的数据状态不准确,导致幻读
四种隔离级别

通过设置隔离级别,可以防止上面的三种并发问题。
MySQL数据库有四种隔离级别 。上面的级别最低,下面的级别最高

✔ 会出现问题
✘ 不会出现问题

级别名字隔离级别脏读不可重复读幻读数据库的默认隔离级别
1读未提交read uncommitted
2读已提交read committedOracle和SQLServer
3可重复读repeatable readMySql
4串行化serializable
隔离级别相关命令
/*
	MySQL的事务隔离级别
	    务在操作时的理想状态: 所有的事务之间保持隔离,互不影响。因为并发操作,多个用户同时访问同一个数据。可能引发并发访问的问题
	    通过设置隔离级别,来解决对应的问题
	    
	并发访问问题
	    脏读:一个事务读取到了另一个事务中尚未提交的数据
	    不可重复读:一个事务中两次读取的数据内容不一致
	    幻读:一个事务中,一次查询的结果无法支撑后续的业务操作
	    
	设置隔离级别
	    read uncommitted:读未提交
		可以防止哪些问题:无
		
	    read committed:读已提交	(Oracle默认隔离级别)
		可以防止:脏读
		
	    repeatable:可重复读	(MySQL默认的隔离级别)
		可以防止:脏读,不可重复读
		
	    serializable:串行化
		可以防止:脏读,不可重复读,幻读
		
	注意:隔离级别 从小到大 安全性是越来越高的,但是效率是越来越低的
	根据不同的情况选择不同的隔离级别
*/

/*
	隔离级别相关命令
	    1.查看隔离级别
		select @@tx_isolation;
		
	    2.设置隔离级别
		set global transaction isolation level 级别名称;
		read uncommitted 读未提交
		read committed   读已提交
		repeatable read  可重复读
		serializable     串行化
*/

-- 查看
SELECT @@tx_isolation;

-- 设置
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

隔离性问题演示

脏读演示

1、打开窗口登录 MySQL,设置全局的隔离级别为最低

2、关闭窗口,开一个新的窗口A ,再次查询隔离级别

3、再开启一个新的窗口B

解决脏读问题

​ 脏读非常危险的,比如张三向李四购买商品,张三开启事务,向李四账号转入 500 块,然后打电话给李四说钱 已经转了。李四一查询钱到账了,发货给张三。张三收到货后回滚事务,李四的再查看钱没了。

解决方案
将全局的隔离级别进行提升为: read committed

不可重复读演示
解决不可重复读问题

将全局的隔离级别进行提升为: repeatable read

幻读演示
解决幻读问题

将事务隔离级别设置到最高 SERIALIZABLE ,以挡住幻读的发生

MySQL多表&外键&数据库设计

多表

多表简述

​ 实际开发中,一个项目通常需要很多张表才能完成。

单表的缺点

​ 冗余,同一个字段中出现大量的重复数据

-- 创建emp表,主键自增
CREATE TABLE emp(
	eid INT PRIMARY KEY AUTO_INCREMENT,
	ename VARCHAR(20),
	age INT,
	dep_name VARCHAR(20),
	dep_location VARCHAR(20)
);

-- 添加数据
INSERT INTO emp(ename,age,dep_name,dep_location) VALUES('张百万',20,'研发部','广州');
INSERT INTO emp(ename,age,dep_name,dep_location) VALUES('赵四',21,'研发部','广州');
INSERT INTO emp(ename,age,dep_name,dep_location) VALUES('广坤',20,'研发部','广州');
INSERT INTO emp(ename,age,dep_name,dep_location) VALUES('小斌',20,'销售部','深圳');
INSERT INTO emp(ename,age,dep_name,dep_location) VALUES('秋艳',22,'销售部','深圳');
INSERT INTO emp(ename,age,dep_name,dep_location) VALUES('大玲子',18,'销售部','深圳');

解决方案

设计为两张表
-- 创建两张表
-- 一方,主表
CREATE TABLE department(
	id INT PRIMARY KEY AUTO_INCREMENT,
	dep_name VARCHAR(30),
	dep_location VARCHAR(30)
);

-- 创建员工表
-- 多方 ,从表
CREATE TABLE employee(
	eid INT PRIMARY KEY AUTO_INCREMENT,
	ename VARCHAR(20),
	age INT,
	dept_id INT
);

-- 添加2个部门
INSERT INTO department VALUES(NULL,'研发部','广州'),(NULL,'销售部','深圳');
SELECT * FROM department;

-- 添加员工,dep_id表示员工所在的部门
INSERT INTO employee (ename, age, dept_id) VALUES ('张百万', 20, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('赵四', 21, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('广坤', 20, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('小斌', 20, 2);
INSERT INTO employee (ename, age, dept_id) VALUES ('艳秋', 22, 2);
INSERT INTO employee (ename, age, dept_id) VALUES ('大玲子', 18, 2);

SELECT * FROM employee;

1、员工表中有一个字段dept_id与部门表中的主键对应,员工表的这个字段就叫做外键

2、拥有外键的员工表被称为从表 , 与外键对应的主键所在的表叫做主表

多表设计上的问题
-- 插入一条 不存在部门的数据,
-- 员工表的 dept_id里面输入不存在的部门id,数据依然可以添加,显然这是不合理的
INSERT INTO employee (ename,age,dept_id) VALUES('无名',35,3);

外键约束

什么是外键

​ 外键指的是在从表中主表的主键对应的那个字段

​ 使用外键约束可以让两张表之间产生一个对应关系,从而保证主从表的引用的完整性

​ 主表: 主键id所在的表,约束别人的表
​ 从表: 外键所在的表,被约束的表

创建外键约束
  1. 创建新表时添加外键
[CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
/*
	外键约束
	    作用:使用外键约束可以让两张表之间产生一个对应关系,从而保证主从表的引用的完整性
	    
	外键
	    外键指的是在从表中与主表的主键对应的字段
	    
	主表和从表
	    主表: 主键id所在的表,约束别人的表,一的一方
	    从表: 外键所在的表,被约束的表,多的一方
	    
	添加外键约束的语法格式
	    1.创建表的时候添加外键
	    create table 表名(
		字段...
		[constraint] [外键约束名] foreign key(外键字段名) references 主表(主键字段)
	    );
*/

-- 创建员工表,添加外键
CREATE TABLE employee(
	eid INT PRIMARY KEY AUTO_INCREMENT,
	ename VARCHAR(20),
	age INT,
	dept_id INT,	-- 外键字段 指向主表的主键
	-- 添加外键约束
	CONSTRAINT emp_dept_fk FOREIGN KEY (dept_id) REFERENCES department(id)
);

-- 正常添加数据 (从表外键 对应主表主键)
INSERT INTO employee (ename, age, dept_id) VALUES ('张百万', 20, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('赵四', 21, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('广坤', 20, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('小斌', 20, 2);
INSERT INTO employee (ename, age, dept_id) VALUES ('艳秋', 22, 2);
INSERT INTO employee (ename, age, dept_id) VALUES ('大玲子', 18, 2);

-- 插入一条错误的数据 (部门id不存在)
-- 添加外键约束之后,会产生一个强制的外键约束检查,保证数据完整性和一致性
INSERT INTO employee (ename, age, dept_id) VALUES ('错误', 18, 3);
删除外键约束
/*
	删除外键约束
	语法格式:
	    alter table 从表 drop foreign key 外键约束的名称
*/

-- 删除employee表的外键约束
ALTER TABLE employee DROP FOREIGN KEY emp_dept_fk;


-- 2.创建表之后添加外键约束
-- 语法格式:alter table 从表 add [constraint] [外键约束名] foreign key(外键字段名) references 主表(主键字段)

-- 简写 不写外键约束名 自动生产成本的外键约束名:employee_ibfk_1
ALTER TABLE employee ADD FOREIGN KEY(dept_id) REFERENCES department(id);
外键约束的注意事项

1.从表外键类型必须与主表主键类型一致,否则创建失败

2.添加数据时,应该先添加主表中的数据

3.删除数据时,应该先删除从表中的数据

/*
	外键约束的注意事项
	    1.从表外键类型必须与主表主键类型一致,否则创建失败
	    2.添加数据时, 应该先添加主表中的数据
	    3.删除数据时,应该先删除从表中的数据
*/

-- 添加一个新的部门
INSERT INTO department(dep_name,dep_location) VALUES('市场部','北京');

-- 添加一个属于市场部的员工
INSERT INTO employee(ename,age,dept_id) VALUES('老胡',24,3);
级联删除操作(了解)

​ 指删除主表数据的同时,也可以删除预制相关的从表数据

语法格式:

ON DELETE CASCADE
/*
	级联删除
	    指删除主表数据的同时,也可以删除预制相关的从表数据
	语法格式:
	    ON DELETE CASCADE
*/

-- 重新创建添加级联操作
CREATE TABLE employee(
eid INT PRIMARY KEY AUTO_INCREMENT,
ename VARCHAR(20),
age INT,
dept_id INT,
CONSTRAINT emp_dept_fk FOREIGN KEY(dept_id) REFERENCES department(id)
-- 添加级联删除
ON DELETE CASCADE
);

-- 添加数据
INSERT INTO employee (ename, age, dept_id) VALUES ('张百万', 20, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('赵四', 21, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('广坤', 20, 1);
INSERT INTO employee (ename, age, dept_id) VALUES ('小斌', 20, 2);
INSERT INTO employee (ename, age, dept_id) VALUES ('艳秋', 22, 2);
INSERT INTO employee (ename, age, dept_id) VALUES ('大玲子', 18, 2);

-- 删除部门编号为2的数据
DELETE FROM department WHERE id = 2;

多表关系设计

表与表之间的三种关系

1、一对多关系(1:n 常见):班级和学生 部门和员工
2、多对多关系(n:n 常见):学生与课程 演员和角色
3、一对一关系(1:1 了解):身份证和人

一对多关系(1:n 常见)

建表原则:在多的一方(从表)建立外键,指向一的一方(主表)的主键

多对多关系(n:n 常见)

建表原则:需要创建第三张表,中间表中至少两个字段,是两张表中的主键字段,作为中间表的外键

一对一关系(1:1 了解)

建表原则:可以在任意一方建立外键指向另一方的主键

设计省&市表

一对多关系

主表:省

从表:市

-- 常见省表 主表
CREATE TABLE province(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20),
	description VARCHAR(20)
);

-- 创建市表 从表 外键字段指向主表的主键
CREATE TABLE city(
	cid INT PRIMARY KEY AUTO_INCREMENT,
	cname VARCHAR(20),
	description VARCHAR(20),
	
	-- 创建外键添加外键约束
	pid INT,
	FOREIGN KEY(pid) REFERENCES province(id)
);

设计演员与角色表

多对多关系型

-- 多对多关系 演员与角色

-- 演员表
CREATE TABLE actor(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
);

-- 角色表
CREATE TABLE role(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
);


-- 创建中间表
CREATE TABLE actor_role(
	-- 中间表的主键
	id INT PRIMARY KEY AUTO_INCREMENT,
	
	-- aid 字段指向actor表的主键
	aid INT,
	
	-- rid 字段指向role表的主键
	rid INT
);


-- 添加外键约束

-- aid 字段添加外键约束
ALTER TABLE actor_role ADD FOREIGN KEY(aid) REFERENCES actor(id);

-- rid 字段添加外键约束
ALTER TABLE actor_role ADD FOREIGN KEY(rid) REFERENCES role(id);

多表查询

什么是多表查询

DQL:查询多张表,获取到需要的数据

/*
	多表查询的语法
	    select 字段列表 from 表名列表;
*/

CREATE DATABASE db3_2 CHARACTER SET utf8;

#分类表 (一方 主表)
CREATE TABLE category (
	cid VARCHAR(32) PRIMARY KEY ,
	cname VARCHAR(50)
);


#商品表 (多方 从表)
CREATE TABLE products(
	pid VARCHAR(32) PRIMARY KEY,
	pname VARCHAR(50),
	price INT,
	flag VARCHAR(2),	#是否上架标记为:1表示上架、0表示下架
	
	category_id VARCHAR(32),
	
	-- 添加外键约束
	FOREIGN KEY (category_id) REFERENCES category (cid)
);

#分类数据
INSERT INTO category(cid,cname) VALUES('c001','家电');
INSERT INTO category(cid,cname) VALUES('c002','鞋服');
INSERT INTO category(cid,cname) VALUES('c003','化妆品');
INSERT INTO category(cid,cname) VALUES('c004','汽车');

#商品数据
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p001','小米电视机',5000,'1','c001');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p002','格力空调',3000,'1','c001');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p003','美的冰箱',4500,'1','c001');
INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p004','篮球鞋',800,'1','c002');
INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p005','运动裤',200,'1','c002');
INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p006','T恤',300,'1','c002');
INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p007','冲锋衣',2000,'1','c002');
INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p008','神仙水',800,'1','c003');
INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p009','大宝',200,'1','c003');

笛卡尔积

交叉连接查询,因为会产生笛卡尔积,所以基本不会使用

语法格式:

SELECT 字段名 FROM 表1, 表2;
SELECT * FROM products, category;

多表查询分类

内连接查询

特点:通过指定的条件去匹配两张表中的内容,匹配不上的不显示

1、隐式内连接
语法格式:

select 字段名... from 左表,右表 where 连接条件
-- 1.查询所有商品信息和对应的分类信息
-- 隐式内连接查询
SELECT * FROM products, category WHERE category_id = cid;

-- 2.查询商品表的商品名称和价格,以及商品的分类信息
-- 多表查询中可以使用给表其别名的方式 简化查询
SELECT
	p.pname,
	p.price,
	c.cname
FROM products p, category c WHERE p.category_id = c.cid;

-- 3.查询格力空调是属于哪一分类下的商品
SELECT
	p.pname,
	c.cname	
FROM products p, category c WHERE p.category_id = c.cid AND p.pid = 'p002';

2、显示内连接

语法格式:

select 字段名... from 左表 [inner] join 右表 on 连接条件
-- 1.查询所有商品信息和对应的分类信息
-- 显示内连接查询

SELECT * FROM products p 
INNER JOIN category c ON p.category_id = c.cid;

-- 查询鞋服分类下,价格大于500的商品名称和价格
/*
	查询之前要确定几件事
	    1.查询几张表
	    2.表的连接条件 p.category_id = c.cid; 从表.外键 = 主表.主键
	    3.查询的字段 商品名称 价格
	    4.查询条件  分类 = 鞋服, 价格 > 500
*/

SELECT
	p.pname,
	p.price
FROM products p
INNER JOIN category c ON p.category_id = c.cid
WHERE p.price > 500 AND c.cname = '鞋服';
外连接查询

1、左外连接

语法格式:

关键字:left [outer] join
select 字段名 from 左表 left join 右表 on 连接条件

左外连接特点:
以左表为基准,匹配右表中的数据,如果能匹配上就显示
如果匹配不上,左表中的数据正常展示,右表数据显示为null

-- 左外连接查询
SELECT
*
FROM category c
LEFT JOIN products p ON c.cid = p.category_id;

-- 查询每个分类下的商品个数
/*
	1.查询的表
	2.查询条件 分组 统计
	3.查询的字段 分类 分类下商品个数信息
	4.表的连接条件
*/

SELECT
	c.cname,
	COUNT(p.pid)
FROM 
-- 表连接
category c LEFT JOIN products p ON c.cid = p.category_id
-- 分组
GROUP BY c.cname;

2、右外连接

语法格式:

关键字:right [outer] join
select 字段名 from 左表 right join 右表 on 连接条件

右外连接特点:
以右表为基准,匹配左表中的数据,如果能匹配上就显示
如果匹配不上,右表中的数据正常展示左表数据显示为null

-- 右外连接查询
SELECT * FROM products p RIGHT JOIN category c ON p.category_id = c.cid;
各种连接方式的总结

内连接: inner join,只获取两张表中交集部分的数据
左外连接: left join,以左表为基准,查询左表的所有数据,以及与右表有交集的部分
右外连接: right join,以右表为基准,查询右表的所有的数据,以及与左表有交集的部分

子查询 (SubQuery)

什么是子查询

1、子查询概念
一条select 查询语句的结果,作为另一条 select 语句的一部分

2、子查询的特点

​ 子查询必须要放在小括号中

​ 子查询作为父查询的条件使用(更多的时候)

3、子查询分类

​ where型子查询:将子查询的结果,作为父查询的比较条件使用
​ from型子查询:将子查询的结果作为一张表使用
​ exists型子查询:查询结果是单列多行的情况,可以将子查询的结果作为父查询的 in函数中的条件使用

子查询的结果作为查询条件(where型)

语法格式:

SELECT 查询字段 FROM 表 WHERE 字段=(子查询);
-- 查询价格最高的商品信息
-- 1.查询除最高的价格
SELECT MAX(price) FROM products;	-- 5000

-- 2.根据最高价格查询商品信息
SELECT * FROM products WHERE price = 5000;

-- 使用一条SQL完成 子查询方式
SELECT * FROM products WHERE price = (SELECT MAX(price) FROM products);


-- 子查询作为查询条件
-- 1.查询化妆品分类下的 商品名称 商品价格
-- 查询除华章品分类的 id
SELECT cid FROM category WHERE cname = '化妆品';	-- c003

-- 2.根据化妆品id 查询对应商品信息
SELECT
	p.pname,
	p.price
FROM products p
WHERE p.category_id = (SELECT cid FROM category WHERE cname = '化妆品');

-- 查询小于平均价格的商品信息
-- 1.求出平均价格
SELECT AVG(price) FROM products; -- 1866

-- 2.获取小于平均价格的商品信息
SELECT
	*
FROM products
WHERE price < (SELECT AVG(price) FROM products);

子查询的结果作为一张表(from型)

语法格式:

SELECT 查询字段 FROM (子查询)表别名 WHERE 条件;
-- 子查询结果作为一张表使用
-- 查询商品中,价格大于500的商品信息,包括 商品名称 商品价格 商品所属分类名称
SELECT * FROM category;

SELECT
	p.pname,
	p.price,
	c.cname
FROM products p
-- 注意:子查询作为一张表使用时,要起一个别名,否则无法访问表中的字段
INNER JOIN (SELECT * FROM category) c ON p.category_id = c.cid
WHERE p.price > 500;

子查询结果是单列多行(exists型)

语法格式:

SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);
/*
	子查询结果是单列多行,作为父查询的 in函数中的条件使用
	语法格式
	    selecct 字段名 from 表名 where 字段 in(子查询);
*/
-- 查询价格小于两千的商品,来自于哪些分类(名称)

-- 1.查询出小于2000的商品的 分类id
SELECT DISTINCT category_id FROM products WHERE price < 2000;

-- 2.根据分类 id 查询分类信息
SELECT * FROM category 
WHERE cid IN
(SELECT DISTINCT category_id FROM products WHERE price < 2000);

-- 查询家电类 与 鞋服类下面的全部商品信息
-- 1.首先要获取 家电类和鞋服类的 分类id
SELECT cid FROM category WHERE cname IN('家电','鞋服');

-- 2.根据 分类id 查找商品信息
SELECT
	*
FROM products WHERE category_id IN
(SELECT cid FROM category WHERE cname IN('家电','鞋服'));

子查询总结

1.子查询如果是一个字段(单列),那么就放在where后面做条件
2.如果是多个字段(多列),就当做一张表使用(要起别名)

数据库设计

数据库三范式(空间最省)

​ 三范式指的就是数据库设计的一个规则
​ 作用:为了创建冗余较小,结构合理的数据库
​ 范式:设计数据库的要求(规范)

第一范式(1NF) :满足最低要求的范式
第二范式(2NF):在满足第一范式的基础之上,进一步满足更多的规范
第三范式(3NF):以此类推

第一范式(1NF)

​ 列具有原子性,设计列要做到列不可拆分

数据库表里面字段都是单一属性的,不可再分,如果数据表中每个字段都是不可再分的最小数据单元,则满足第一范式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E8gII3MU-1620996416248)(E:\MarkDown\拉勾笔记\数据库第一范式(1NF))]

第二范式(2NF)

​ 一张表只能描述一件事

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g4oKVBKK-1620996416258)(E:\MarkDown\拉勾笔记\数据库设计第二范式(2NF))]

第三范式(3NF)

​ 消除传递依赖

​ 表中信息如果能被推导出来,就不要设计一个字段单独来记录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90bG5Wkk-1620996416272)(E:\MarkDown\拉勾笔记\数据库设计第三范式(3NF))]

三范式就是空间最省原则

数据库反三范式

1、概念

​ 指通过增加冗余或者重复数据,来提高数据库的性能
​ 浪费存储空间,节省查询时间(以空间换时间)

2、冗余字段

​ 某一个字段,属于一张表,但是它又在多张表中都有出现

3、示例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AnNDPJNT-1620996416290)(E:\MarkDown\拉勾笔记\数据库设计反三范式)]

冗余字段name

4、总结

​ 1.尽量根据三范式规则去设计数据库

​ 2.可以合理的增加冗余字段,减少join操作,让数据库执行得更快

MySQL索引&视图&存储过程

MySQL 索引

概念

​ 通过对数据表中的字段创建索引,来提高查询速度。

常见索引分类

1、主键索引(primary key):主键是一种唯一性索引,每个表只能有一个主键,用于标识数据表中的每一条记录

2、唯一索引(unique):索引列的所有值都只能出现一次,必须唯一

3、普通索引(index):最常见的索引,作用就是提高对数据的访问速度

​ 表对应的索引都保存在同一个索引文件中,如果对数据进行增删改操作,MySql都会自动的更新索引。

主键索引 (PRIMARY KEY)

1、创建表的时候,直接添加主键

2、创建表之后添加索引,使用DDL

CREATE TABLE demo01(
	did INT,
	dname VARCHAR(20),
	hobby VARCHAR(30)
);

/*
	主键索引
	    1.创建表的时候,直接添加主键
	    2.创建表之后添加索引,使用DDL
*/

-- 为demo01表添加主键索引
ALTER TABLE demo01 ADD PRIMARY KEY(did);
唯一索引(UNIQUE)
/*
	唯一索引的创建
	    create unique index 索引名 on 表名(列名(长度))
*/

-- 为demo01表的hobby字段添加唯一索引
CREATE UNIQUE INDEX ind_hobby ON demo01(hobby);

-- 添加唯一索引的列,列的所有值都只能出现一次
INSERT INTO demo01 VALUES(1,'tom','篮球');

-- Duplicate entry '篮球' for key 'ind_hobby'
-- 唯一索引保证数据的唯一性,同时也提升了查询的效率
INSERT INTO demo01 VALUES(2,'jack','篮球');
普通索引 (INDEX)
/*
	普通索引
	    1.create index 索引名 on 表名(列名[长度])
	    2.ALTER TABLE 表名 ADD INDEX 索引名 (列名)
*/

-- 为demo01表中的dname 字段添加普通索引
ALTER TABLE demo01 ADD INDEX ind_dname(dname);
删除索引
/*
	删除索引
	    ALTER TABLE 表名 DROP INDEX index_name;
*/

-- 删除demo01表上dname字段上的索引
ALTER TABLE demo01 DROP INDEX ind_dname;

索引性能测试

/*
	索引性能测试
	导入 test_index SQL脚本
*/

-- 表中有 500万条数据
SELECT COUNT(*) FROM test_index;

-- 通过id 查询一条数据(添加了索引)		0.001秒
SELECT * FROM test_index WHERE id = 100001;

-- 通过dname 查询一条数据(没有添加索引)	耗时4秒
SELECT * FROM test_index WHERE dname = 'name5200';

-- 执行分组查询  dname没有添加索引 1分28秒
SELECT * FROM test_index GROUP BY dname;

-- 为dname 添加索引
ALTER TABLE test_index ADD INDEX dname_index(dname);

-- dename字段添加索引后 0.08秒
SELECT * FROM test_index GROUP BY dname;

索引总结

1、创建索引原则
优先选择为经常出现在 查询条件或者排序分组 后面的字段创建索引

2、索引的优点
1.可以大大的提高查询速度
2.减少查询中分组和排序时间
3.通过创建唯一索引保证数据的唯一性

3、索引的缺点
1.创建和维护索引需要时间,数据量越大,时间越长
2.表中的数据进行增删改操作时,索引也需要进行维护,降低了维护的速度
3.索引文件需要占据磁盘空间

MySQL 视图

概念

​ 视图是由查询结果形成的一张虚拟的表

作用

​ 如果某个查询的结果出现十分频繁,并且查询语法比较复杂,那么这个时候就可以根据这条查询语句构建一张视图,方便查询

视图使用

1、语法格式:

create view 视图名[字段列表] as select 查询语句;

    view 表示视图
    字段列表一般跟后面的查询语句相同
    as select 查询语句 表示给视图提供数据的查询语句

2、创建视图

-- 创建视图
-- 1.查询所有商品和商品对应分类的信息
SELECT * FROM products p LEFT JOIN category c ON p.category_id = c.cid;

-- 2.根据上面的查询语句 构建一张视图
CREATE VIEW products_category_view AS
SELECT * FROM products p LEFT JOIN category c ON p.category_id = c.cid;

-- 操作视图就相当于操作一张 只读表
SELECT * FROM products_category_view;

2、通过视图进行查询

-- 使用视图记性处查询操作
-- 查询各个分类下的商品平均价格
/*
	1.查询那些表:分类表 商品表
	2.查询条件:分组操作
	3.查询字段:平均价格 分类名
	4.多表的连接条件 category_id = cid
*/

-- 使用多表方式查询
SELECT
	c.cname,
	AVG(p.price)
FROM products p LEFT JOIN category c ON p.category_id = c.cid
GROUP BY c.cname; 

-- 通过视图查询
SELECT 
	pc.cname,
	AVG(pc.price)
FROM products_category_view pc GROUP BY pc.cname;

-- 查询鞋服分类下最贵的商品的全部信息
-- 多表查询
-- 1.查询鞋服分类中 最高的商品价格
SELECT
	MAX(p.price)
FROM products p LEFT JOIN category c ON p.category_id = c.cid
WHERE c.cname = '鞋服';

-- 2.进行子查询,将上面的查询结果作为条件
SELECT
*
FROM products p LEFT JOIN category c 
ON p.category_id = c.cid
WHERE c.cname = '鞋服' AND p.price =
(
	SELECT
		MAX(p.price)
	FROM products p LEFT JOIN category c ON p.category_id = c.cid
	WHERE c.cname = '鞋服'
);

-- 通过视图查询
SELECT 
	* 
FROM products_category_view pc 
WHERE pc.cname = '鞋服' AND pc.price = 
(
-- 子查询:求出鞋服分类下的最高价格
SELECT MAX(pc.price) FROM products_category_view pc 
WHERE pc.cname = '鞋服');

视图与表的区别

1、视图是建立在表的基础之上

2、通过视图,不要进行增删改操作,视图主要就是用来简化查询的

3、删除视图表不受影响,但是删除表视图就不再起作用了

MySQL 存储过程(了解)

概念

存储过程其实就是一堆SQL语句的合并。中间加入了一些逻辑控制。

优缺点

1、优点:

​ a.调试完成就可以稳定运行(在业务需求相对稳定情况)

​ b.存储过程可以减少业务系统与数据库的交互

2、缺点:

​ a.互联网项目中较少使用存储过程,因为业务需求变化太快

​ b.存储过程的移植十分困难

创建方式

准备数据

# 商品表
CREATE TABLE goods(
	gid INT,
	NAME VARCHAR(20),
	num INT  -- 库存
);

# 订单表
CREATE TABLE orders(
	oid INT,
	gid INT,
	price INT -- 订单价格
);

# 向商品表中添加3条数据
INSERT INTO goods VALUES(1,'奶茶',20);
INSERT INTO goods VALUES(2,'绿茶',100);
INSERT INTO goods VALUES(3,'花茶',25);
方式一

语法格式:

delimiter $$			-- 声明语句的结束符号(自定义)
create procedure 存储过程名称()	-- 声明存储过程
begin				-- 开始编写存储过程    
	-- 要执行的SQL
end $$				-- 存储过程结束
-- 编写存储过程,查询所有商品信息
DELIMITER $$ 
CREATE PROCEDURE goods_proc()
BEGIN
	-- 查询商品数据
	SELECT * FROM goods;
END $$;

-- 调用存储过程 call
CALL goods_proc;
方式二

创建一个接收参数的存储过程

语法格式:

create procedure 存储过程名(in 参数名 参数类型)
-- 创建存储过程 
-- 接收一个商品id,根据id删除数据
DELIMITER $$
CREATE PROCEDURE goods_proc02(IN goods_id INT)
BEGIN
	-- 根据id删除数据
	DELETE FROM goods WHERE gid = goods_id;
END $$

-- 调用存储过程 传递参数
CALL goods_proc02(1);
方式三

格式:

1.变量的赋值
	SET @变量名 = 值
2.OUT 输出参数
	OUT 变量名 数据类型
-- 向订单表插入一条数据,返回1,表示插入成功
DELIMITER $$
CREATE PROCEDURE orders_proc(IN o_oid INT, IN o_gid INT, IN o_price INT, OUT out_num INT)
BEGIN
	-- 执行插入操作
	INSERT INTO orders VALUES(o_oid, o_gid, o_price);
	-- 设置 out_num值为1
	SET @out_num = 1;
	
	-- 返回out_num
	SELECT @out_num;
END $$

-- 调用存储过程,获取返回值
CALL orders_proc(1,2,50,@out_num);

MySQL触发器(了解)

概念

​ 当我们执行一条sql语句的时候,这条sql语句的执行会自动去触发执行其他的sql语句。

触发器创建的四个要素

1、监视地点(table)

2、监视事件(insert/update/delete)

3、触发时间(before/after)

4、触发事件(insert/update/delete)

创建触发器

语法结构:

delimiter $							-- 自定义结束符号
create trigger 触发器名
after/before(insert/update/delete)	-- 触发的时机和监视的事件
on 表名							   -- 触发器所在的表
for each row						-- 固定写法,表示行触发器
begin
		-- 被触发的事件
end $
-- 向商品中添加一条数据
INSERT INTO goods VALUES(4,'book',40);

-- 需求:在下订单的时候,对应的商品的库存量要相应的减少,卖出商品之后减少库存量
/*
	监视的表:orders
	监视的事件:insert
	触发的时间:after
	触发的事件:update
*/

-- 1.修改结束符号
DELIMITER $
-- 2.创建触发器
CREATE TRIGGER t1
-- 3.设置触发的时间,监视的事件以及监视的表
AFTER INSERT ON orders
-- 4.行触发器
FOR EACH ROW
-- 5.触发后要执行的操作
BEGIN
	-- 执行库存修改操作 订单+1,库存-1
	UPDATE goods SET num = num - 1 WHERE gid = 4;
END $

-- 向orders表插入一个订单
INSERT INTO orders VALUES(1,4,25);

DCL(数据控制语言)

创建用户

语法格式:

create user '用户名'@'主机名' identified by '密码';
-- 创建 admin1 用户,只能在localhost这个服务器登录mysql服务器,密码为123456
CREATE USER 'admin1'@'localhost' IDENTIFIED BY '123456';

-- 创建 admin2 用户可以在任何电脑上登录 mysql 服务器,密码为 123456
CREATE USER 'admin2'@'%' IDENTIFIED BY '123456';	-- %表示在任意用户电脑都能登陆

用户授权

语法格式:

grant 权限1,权限2 ... on 数据库名.表 to '用户名'@'主机名';
-- 给 admin1 用户分配对 db4 数据库中 products 表的 操作权限:查询
GRANT SELECT ON db4.products TO 'admin1'@'localhost';

-- 给 admin2 用户分配所有权限,对所有数据库的所有表
GRANT ALL ON *.* TO 'admin2'@'%';



-- 查询商品表
SELECT * FROM products;

-- 插入商品数据
-- INSERT command denied to user 'admin1'@'localhost' for table 'products'
-- admin1 用户只有查询权限
INSERT INTO products VALUES('p010','小鸟伏特加',3000,NULL);

查看权限

语法格式:

show grants for '用户名'@'主机名';
-- 查看root 用户的权限
SHOW GRANTS FOR 'root'@'localhost';

-- 查看admin1用户权限
SHOW GRANTS FOR 'admin1'@'localhost';

删除和查询用户

-- 删除用户
DROP USER 'admin1'@'localhost';

-- 查询用户
SELECT * FROM USER;

数据库备份&还原

SQLYog 数据备份&恢复

命令行备份&恢复

语法格式:

备份:mysqldump -u用户名 -p密码 数据库名 > 文件路径
还原:source sql文件地址

备份:
C:\Program Files\MySQL\MySQL Server 5.7\bin>mysqldump -uroot -p123456 db2 > G:/db02.sql

还原:
mysql> use db2;
Database changed
mysql> source G:db02.sql;

标签:INSERT,--,数据库,查询,MySQL,id,SELECT
来源: https://blog.csdn.net/heywei_/article/details/116805405

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有