开始MySQL的学习之路--------------
1.数据库 database DB(关系型数据库)
1.1 数据库概念
简称DB,全称为database。就是一个存储数据的仓库,用于存储不同数据类型的数据。
作用(目的):1.可以直观的看到不同类型的数据,对数据进行持久化(永久存储)操作 2.进行数据分析
1.2 数据库的分类
存储位置的不同进行分类:
基于磁盘的存储(MySQL,Oracle,SQLServer等。将数据写入文件,底层是IO.)
优势:完全保证数据的持久化
弊端:底层是IO实现,读写性能偏低
基于缓存存储(Redies)
优势:性能快 弊端:不能完全持久化
持久化策略:Redis后期可以使用RDB以及AOF进行解决
从数据间是否存在关系进行分类
1.关系型数据库
(数据-数据) (字段-字段) (表与表)之间是有关系的。Eg:MySQL Oracle SQLServer
2.非关系型数据库
NOSQL(NOT ONLY SQL) 非关系型 Redis mongodb 压根没有表。 所有的数据存储形式为键值对 key:value
2.DBMS(DataBase Managemebt System)
我们要学习的就是一个基于磁盘存储的关系型数据库。 MySQL(数据库管理系统软件)
其实,我们学习的是一个软件(服务器软件)
MySQL就是一个软件,就是一个DBMS. 服务器软件。 Mysql就是一个服务器。
Mysql服务器(8.0版本)的下载与安装:(2024 年 MySQL 8.0 安装 配置 教程 最简易(保姆级)_mysql安装-CSDN博客)
2.1DBMS概念
"数据库管理系统软件"是一种操纵和管理数据库的大型软件(使用DBMS可以操作和管理很多数据库),用于建立、使用和维护数据库,简称DBMS.它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。
用户通过DBMS访问数据库中的数据,数据库管理员也通过DBMS进行数据库的维护工作。
3.MySQL
3.1 了解MySQL
MySQL 是一个数据库管理系统软件。MySQL 是目前最流行的开源SQL数据库管理系统,目前由 Oracle 公司进行开发,发布和支持。目前最新的版本是8.0.。在开发中最常用的服务器版本是5.7.或者8.0.*
注:MySQL 软件采用了双授权政策,分为社区版和商业版
3.2 MySQL特点
- MySQL 数据库是关系型的
- 其体积小、速度快、总体拥有成本低
- MySQL 软件是开源的
- 使用 C 和 C++ 编写
- MySQ 数据库服务器非常快速、可靠、可扩展且易于使用
- 使用非常快速的B树磁盘表(MyISAM)和索引压缩
- 使用非常快速的基于线程的内存分配系统
4.简单操作
4.1 cmd命令提示窗口链接MySQL服务
结合相关的dos命名或者一些指定实现。 DOS: 磁盘操作系统 disk operateing system
在客户端操作服务器
1. 启动MySQL服务器
2. 成功连接服务器(服务器就是一个软件)
要连接哪一台计算机上面的那一个软件???
ip 端口
-- mysql -hip -u用户名 -p
-- 测试ip: 127.0.0.1 localhost
mysql -h127.0.0.1 -uroot -p
"出现问题: 命名无法执行"----> 需要配置环境变量(下文链接)
在path中 配置mysql的bin目录----> 有很多exe
配置MYSQL环境变量
学习链接:(MySQL环境变量配置教程-CSDN博客)
4.2 图形化界面的工具作为客户端(Navicat)
Navicat Premium
cmd也可以作为客户端去操作MySQL服务器,但是太麻烦。
因此很多厂商研发了很多可视化的客户端工具,提高数据的可读性以及方便开发人员的使用。
目前企业级里面比较常用的工具/软件:
1.Navicat 收费 (学习期间使用这个)
2.sqlyog 收费
3.MySQL_Front 免费
4.3 MySQL服务器里面有什么?
MySQL服务器,里面有很多数据库。一个数据库就有点像一个excel文件。
- 一个数据库中有很多表(table)
- 存储过程
- 存储函数
- 索引
- 触发器
4.4 表里面有什么?
列(字段) 数据(行记录) 数据类型 约束...
4.5 关于数据库指令(命令)
不区分大小写。
建议:关键字都大写 数据---->小写 一行命令的结束要有 ;
mysql> SHOW DATABASES; -- 展示指定服务器里面所有的数据库
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
mysql> SELECT database(); -- 查询目前正在操作的数据库
+------------+
| database() |
+------------+
| NULL |
+------------+
mysql> USE mysql; -- 切换要操作的数据库
Database changed
mysql> SELECT database();
+------------+
| database() |
+------------+
| mysql |
+------------+
mysql> SHOW TABLES; -- 查询指定数据库里面所有的表
mysql> SELECT * FROM user; -- 查询指定表中的所有列的数据 *: 通配符 代表所有的列
mysql> SELECT host,user FROM user;
+-----------+------------------+
| host | user |
+-----------+------------------+
| localhost | mysql.infoschema |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | root |
+-----------+------------------+
5.关于SQL
5.1 SQL概念
SQL (structure query language) 结构化查询语言,专门与DBMS通信的语言,所有RDBMS(关系型数据库 如MySQL,Oracle,SQLserver等)都支持。因此我们在学习了解DBMS中,是要使用SQL操作里面的库、表、字段、数据等。
5.2 SQL标准
SQL标准(ANSI/ISO)有: SQL-92:1992年发布的SQL语言标准; SQL:1999:1999年发布的SQL语言标准; SQL:2003:2003年发布的SQL语言标准; SQL:2011•:进一步扩展了时态数据处理、序列和更复杂的查询功能。 SQL:2023•:最新的标准,于2023年发布,包含11个部分的内容,新增了图形查询语言(GQL)功能。 这些标准就与JDK的版本一样,在新的版本中总要有一些语法的变化。不同时期的数据库对不同标准做了实现。
5.3 SQL分类
1. DDL data nation language 数据定义语言。 用来定义数据库对象:库、表、列等 CREATE DROP ALTER TRUNCATE 2. DML data defination language 数据操作语言。 用于新增、更新操作 INSERT DELETE UPDATE (更新) 3. DQL Date Query Language 数据查询语言。 SELECT 4. DCL 数据控制语言。 GRANT REVOKE 5. TCL 事务控制语言。 COMMIT ROLLBACK
5.4 SQL语法
SQL语句可以单行或多行书写,以分号结尾; 可以用空格和缩进来来增强语句的可读性; 关键字不区别大小写,建议使用大写;
6.常用SQL命令
在MySQL里面, 不管是指令还是sql语句还是数据,都是大小写不敏感。但是可以参考前文4.5关于数据库命令的建议
1. mysql -hip -uroot -p -- 在cmd窗口 使用此指令连接数据库服务器
2. show databases; -- 查看mysql所有的数据库
3. select database();-- 查看目前正在操作的数据库
4. use 数据库的名称; -- 切换要操作的数据库
5. show tables; -- 展示指定的数据库里面所有的表
6. desc 表名; -- 查看指定的表的表结构 属性/列,数据类型,约束
7.mysqladmin -u用户名 -p旧密码 password 新密码 -- 修改密码操作
8.mysqldump host -u root -p dbname >dbname_backup.sql --备份数据库
9.mysq host -u root -p dbname < dbname_backup.sql --恢复数据库
10.net start mysql_name -- 启动数据库服务命令
11.net stop mysql_name -- 关闭数据库服务命令
7.常用数据类型
-
MySQL常用字段(列,属性)数据类型
-
MySQL主要提供了数值型、 字符串类型 、日期和时间类型等一些其他类型。
7.1 整数类型
类型 | 大小(字节) | 有符号范围 | 无符号范围(unsigned) |
---|---|---|---|
TINYINT(m) | 1 | -128-127 | 0 - 255 |
SMALLINT(m) | 2 | -32768-32767 | 0 - 65535 |
MEDIUMINT(m) | 3 | -8388608-8388607 | 0 - 16777215 |
INT(m) | 4 | -2147483648-2147483647 | 0 - 4294967295 |
BIGINT(m) | 8 | -9223372036854775808 - 9223372036854775807 | 0 - 18446744073709551615 |
-
m表示SELECT查询结果集中的显示宽度,与取值范围无关。 m最大值11
-
tinyint(1) unsingned ,数值只能是0与1,对应java里面的boolean类型。否则就是对应java语言里面的byte或者int
-
zerodfill属性: int(5) 00100 如果不满5个数字,会在数值之前使用0进行填充。
-
常用字段:年龄 库存 编号......
7.2 浮点类型
类型 | 大小 | 有符号范围 | 无符号范围 |
---|---|---|---|
FLOAT(m,d) | 4 | -3.402823466E+38 to -1.165494351E-38 | |
DOUBLE(m,d) | 7 | ||
DECIMAL(m,d) | 可变 | 根据M和D 的值 |
-
m为数字的总个数,d为小数点之后的个数。
-
定点数在MySQL内部以字符串形式存放 比浮点数更精确 适合用来存放货币等精度高的数据;
-
浮点数和定点数都可以在后面加(M,D) M表示显示的位数 D表示小数的位数,当存入的小数位过长时 此三者都会进行四舍五入
-
Decimal(m,d) 定点数 参数m<65 是总个数,d<30且 d<m 是小数位。 BigDecimal
-
decimal在不指定精度时,默认的整数位时10,默认的小数位是0
-
常用字段:成绩 单价 钱(decimal)......
7.3 字符类型
类型 | 最大长度 |
---|---|
CHAR(m) | 255字符 |
VARCHAR(m) | 65535 |
TEXT | 16KB |
LONGTEXT | 4G |
-
m: 用来限定存储字符个数
-
char与varchar 类似都是用来保存MySQL中较短的字符串,主要区别在于存储方式不同。
-
char列的长度固定为创建表时声明的长度 ,长度可以是0-255中的任意值;
-
varchar为可变长字符串 长度可以指定0-65535间的任意值
-
常用字段:姓名 介绍 描述......char:手机号,定长数据
7.4 日期时间类型
类型 | 字节 | 最小值 |
---|---|---|
date | 4 | 1000-01-01 |
datetime | 8 | 1000-01-01 00:00:00 |
timestamp | 4 | 1970-01-01 08:00:01 |
time | 3 | -838:59:59 |
year | 1 | 1901 |
-
可以知道每种日期类型都有一个有效取值范围
-
timestamp有个重要的特点就是和时区有关,2个不同时区的用户看到的同一个日期时不一样的
-
也就是表中存的值是同一份数据,但是不同时区的用户查询出的结果是不一样的;
timestamp和datetime的区别:
- timestamp的取值范围小,最大到2038年的某个时间,datetime取值范围更大;两者都支持 on update current_timestamp属性 使得日期列可以随着其他列的更新而自动更新为最新时间.
- timestamp的插入和查询受到时区的影响 更能反映出实际的日期;datetime只能反映插入时当时的时区
- timestamp的属性受到MySQL版本和服务器sqlMode的影响很大
8.数据定义语言DDL
8.1 操作库
用来实现数据库、表的创建和删除。 更新表结构等。
-- 创建数据库
CREATE DATABASE 数据库名称; -- 数据库一旦创建 名称无法更改
-- 查询创建数据库的完整信息
mysql> show create database mydb;
+----------+--------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database |
+----------+--------------------------------------------------------------------------------------------------------------------------------+
| mydb | CREATE DATABASE `mydb` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+------------------------------
-- 删除数据库 所有的表 数据也是无法回滚
DROP DATABASE 数据库名称;
8.2 操作表(创建/删除表)
-- 创建表语法
-- 一张表必不可少的3个列 id create_time update_time
CREATE TABLE 表名(
字段/列名1 数据类型 [约束],
字段/列名2 数据类型 [约束],
...
字段/列名n 数据类型 [约束]
);
例如(创建一个学生表):
CREATE TABLE student(
id int,
name varchar(20),
gender char(1),
age tinyint(2) unsigned,
balance float(5,2),
create_time datetime,
update_time datetime
);
mysql> desc student; -- 查询指定表的结构
+-------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| gender | char(1) | YES | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| balance | float(5,2) | YES | | NULL | |
| create_time | datetime | YES | | NULL | |
| update_time | datetime | YES | | NULL | |
+-------------+------------------+------+-----+---------+-------+
-- 删除指定的表 数据无法回滚
mysql> drop table student;
Query OK, 0 rows affected (0.33 sec)
-- 字段/列名 自己起名
-- 数据类型 mysql定义好的
-- 约束 mysql定义好的
-- 表名/列名 一般都是小写 多个单词要使用_(下划线)连接
8.3 更新表结构 ALTER
-- 更新表结构 alter
-- 1. 新增新的列/字段 address
ALTER TABLE tb_userinfo add address varchar(50);
-- 2.删除指定的列
ALTER TABLE tb_userinfo drop address;
-- 3.修改指定列的列名 age->user_age
ALTER TABLE tb_userinfo change age user_age tinyint(2) unsigned;
-- 4.修改指定列的数据类型
ALTER TABLE tb_userinfo change username username char(30);
ALTER TABLE tb_userinfo modify username varchar(30);
-- 5.修改指定表的表名
ALTER TABLE tb_userinfo rename userinfo;
9.数据操作语言DML
-
数据操作语言。主要包含:
-
INSERT 新增
-
DELETE 删除
-
UPDATE 修改
9.1 INSERT 新增
新增行记录. 可以一次新增一行,也可以批处理。
--1. insert 对表里面的所有的列进行赋值。
-- 语法1:
-- insert into (数据库.)表名 values (数据1,数据2....数据n); 数据的数量取决于列的数量 不建议使用。
例如:
INSERT INTO userinfo VALUES (1,'张三',20,'1234','男','游戏,代码',100000,'2000-01-01','2022-12-03 12:00:00',null);
-- 一次新增1行 表里面的行记录是1行受影响了。
-- 2. insert 指定列进行新增
-- 语法2:
-- insert into 表名 (列1,列2...列n) values (数据1,数据2....数据n);
例如:
INSERT INTO userinfo (id,username,password,create_time) VALUES (4,'李四','1111',now());
-- 一次新增1行 表里面的行记录是1行受影响了。
-- 3.INSERT 批处理 一次新增多行记录
-- 语法3
-- 一次新增多行 表里面的行记录是多行受影响了
INSERT INTO 表名 VALUES (数据1,数据2....数据n),(数据1,数据2....数据n)....;
INSERT INTO 表名 (列1,列2...列n) VALUES (数据1,数据2....数据n),(数据1,数据2....数据n);
例如:
INSERT INTO userinfo VALUES (1001,'张三',20,'1234','男','游戏,代码',100000,'2000-01-01','2022-12-03 12:00:00',null),
(1002,'张三',20,'1234','男','游戏,代码',100000,'2000-01-01','2022-12-03 12:00:00',null);
INSERT INTO userinfo (id,username,password,create_time) VALUES (1003,'李四','1111',now()),(1004,'李四','1111',now());
9.2 DELETE 删除
在开发中,执行删除之前必须有查询*
删除行/记录. 可以一次删除一行,也可以删除多行。也可以清空表记录
-- 删除语法:DELETE 与 TRUNCATE 的区别
-- DELETE FROM 表名; 清空表数据(在开启事务的前提下 数据可以回滚的)
mysql> DELETE FROM userinfo;
Query OK, 10 rows affected (0.02 sec)
-- 实现逻辑:遍历式删除
-- 特点:性能低,可以回滚,DML, 与事务有关
-- TRUNCATE
TRUNCATE TABLE 表名
-- 实现逻辑:先DROP表,再CREATE表
-- 特点:性能高,不会回滚,DDL,与事务无关
***********************************************************
-- 一般是根据id删除 因为id是唯一的
DELETE FROM userinfo WHERE id=1001;
-- 在条件下执行删除
-- 语法:
--DELETE from 表名 where 条件1 and/or 条件2;
DELETE FROM userinfo WHERE username='张三';
DELETE FROM userinfo WHERE id=1001;
DELETE FROM userinfo WHERE user_age IS NULL;
--批量删除(以下语法等价)
DELETE FROM userinfo WHERE id=1001 OR id = 3;
DELETE FROM userinfo WHERE id IN (12,4);
9.3 UPDATE 修改
执行修改前也有查询
更新记录,多个字段之间使用逗号。可以一次更新一行,也可以更新多行。
-- 语法
-- UPDATE 表名 SET 列1=新数据1,列2=新数据2...列n=新数据n; 等价于修改表里面所有的记录,很少使用。
-- 语法
-- UPDATE userinfo SET balance='200000';
-- 一次修改一行记录 表里面受影响的行记录数为1
UPDATE 表名 SET 列1=新数据1,列2=新数据3...列n=新数据n WHERE 条件1 AND/OR 条件2;-- 建议使用
UPDATE userinfo SET user_age=18,gender='男',birthday=now(),update_time=now() WHERE id=4;
10.约束
-
在MySQL服务中,约束分为行级约束与表级约束。
-
限制列的数据,保证数据的正确性。维护表与表的关系。
创建表的时候:(在创建表的时候指定某些列的约束问题) create table a( id int, name varchar(20) ); 1.1 列级约束 放在列的后面; 范围只对当前列生效。 1.2 表级约束 在最后一个字段的后面,添加约束; 范围对多个列生效。 -- 列级约束 -- 1. 非空约束 not null -- 2. 唯一性约束/索引 unique -- 3. 默认约束 default -- 4. 主键约束 primary key -- 表级约束 -- 1. 主键约束 primary key -- 2. 外键约束 foreign key -- 3. 唯一性约束/索引 unique
10.1 非空约束 NOT NULL
非空约束。只能作为列级约束,限制列的数据不能为NULL,新增/修改时必须有值。
-- 1.非空约束 NOT NULL
CREATE TABLE demo(
id INT,
name VARCHAR(20),
age TINYINT UNSIGNED
);
DESC demo;
INSERT INTO demo (id,name,age) VALUES (1,'jijm',18);
INSERT INTO demo (id,name) VALUES (2,'jijm');
SELECT * FROM demo;
*************************************************
-- 修改id/name/age不能为null
-- 在创建表成功的前提下 使用alter操作即可
ALTER TABLE demo modify id int NOT NULL;
-- DESC demo;
*************************************************
-- 在创建table的时候 直接对列进行约束
CREATE TABLE b(
id int NOT NULL,
name VARCHAR(20) NOT NULL
);
10.2 唯一性约束/索引 UNIQUE
唯一性约束,限制列的值不能重复。
若列只使用了UNIQUE 列的数据可以使用多次NULL
在查询的sql中,有索引的列作为条件进行查询,性能会比普通列的性能高很多。
-- 2.唯一性约束
DROP TABLE b;//删除b表
CREATE TABLE b(
id INT UNIQUE NOT NULL,
name varchar(20) NOT NULL,
age int
);
INSERT INTO b (id,name) VALUES (2,'jim');
-- DESC b;
********************************************
ALTER TABLE b modify id int UNIQUE NOT NULL;
********************************************
DESC b;
SELECT * FROM b;
10.3 主键约束 PRIMARK KEY
主键约束修饰的列的数据,是不能能为NULL且唯一的
NOT NULL + UNIQUE = PRIMARK KEY(一个表中只能有一个主键约束)
数据特征:非空且唯一
-- 3.主键约束
-- 列使用主键约束 这个列就称为"主键列"。
-- 要求: 一张表里面有且只有1个主键列。一张表里面主键约束只能使用/出现一次。
-- 列使用了主键约束,这个列的数据: 就是非空+唯一。
-- 任意类型的列都可以作为主键列使用。
-- 一般都是id作为主键列使用。
DROP TABLE b;
CREATE TABLE b(
id INT PRIMARY KEY auto_increment, -- 行级约束
name varchar(20) NOT NULL UNIQUE,
gender CHAR(1)
);
-- id 作为主键列存在 保证数据的唯一性。 标识每行记录的唯一性。
-- 如何保证id数据唯一? mysql的特性实现
-- 1. id是数值类型 int bigint 这个时候可以将主键列更改为值可以自增处理。
-- auto_increment 只能与主键列一块使用。
ALTER TABLE b modify id int auto_increment;
-- id的数据就可以自己自增。 从1开始 每次+1
-- DESC b;
-- 修改自增的初始值 自增的步长
ALTER TABLE b auto_increment 1001;
--设置全局配置,重启链接生效
SET GLOBAL auto_increment_increment=1;
10.3.1 关于自动增长
auto_increment -- 让主键自动增长
修改已有表
ALTER TABLE b modify id int auto_increment;
创建表时增加自动增长
CREATE TABLE c(
id INT PRIMARY KEY auto_increment, -- 行级约束
name varchar(20) NOT NULL UNIQUE,
gender CHAR(1)
);
10.3.2 如何保证id的唯一性?
-- 2. id是字符类型的。保证id的唯一性?
-- 解决方式: 1.1 使用代码传过来一个唯一的id 1.2 uuid()
CREATE TABLE a(
id VARCHAR(100),
name VARCHAR(20),
PRIMARY KEY(id)
);
-- INSERT INTO a (id) VALUES (UUID()),(UUID());
-- SELECT * FROM a;
-- DESC a;
-- 联合主键。(多个列同时作为一个主键列存在的。)----> 表级约束
-- 一般是体现在中间表使用(维护多表的关系)
CREATE TABLE d(
name VARCHAR(20),
pass VARCHAR(20),
age int,
PRIMARY KEY (name,pass) -- 表级约束
);
-- Duplicate entry 'jim-1234' for key 'd.PRIMARY'
INSERT INTO d (name,pass) values ('jim','1234');
SELECT * FROM d;
DESC d;
10.4 外键约束 FOREIGN KEY
外键约束修饰的列,一般我们成为外键列。外键是一个表级约束,"维护多张表之间的关系"。服务于表设计
-
一张表中可以有多个列作为外键列。
-
一张表中可以创建多个外键约束。
-
外键列的数据要严格参照主表里面的主键列的数据。------------>外键列的数据类型要与主表里面主键列的类型是一致的。
-
外键列在的表一般称为子表/从表。---->从表里面外键列的数据要严格参照主表里面主键列的数据
-
一张表的外键代表着另外一张表的主键。外键的值必须从另外一张表的主键中进行选择
-
外键列的数据严格参照主表里面主键列的数据
-
一般外键约束,主要满足与表设计,维护多表的关系。
-
在正常开发中,尤其是数据量大的情况下,其实我们很少使用外键约束。外键列正常存在,不加约束。
-
外键约束优势:能保证数据安全性 。 弊端: 性能低。
-
但是在学习期间,我们还是要知道如何使用外键约束以及良好的进行表设计。
知识补充:表设计的三大范式:
设计表的前提是正确判断表关系,再进行表的设计
1.保证列的原子性(列不可再分)
2.保证每行数据的唯一性(必须有主键列)。
3.尽可能减少列和数据的冗余。允许外键列的数据冗余
10.4.1 表关系:一对一
-- 以用户和部门关系举例
-- 用户表
用户有 角色 ....
-- 部门表
部门 岗位 ....
-- 添加外键约束
ALTER TABLE sys_user ADD CONSTRAINT FOREIGN KEY (did) REFERENCES dept(id);
DESC sys_user;
注意:
-- 伪外键
-- 只有新增了外键约束 foreign key的列才叫外键列
-- 外键列就是一个普通列,大型数据不允许使用外键约束
用户与购物车的关系:一个用户一个购物车,双方来看都是一对一的关系,可以在任意1的地方添加外键列
10.4.2 表关系:一对多
外键列在多的一方
-- 用户表
用户有 角色 部门 岗位 ....
-- 添加外键约束
ALTER TABLE sys_user ADD CONSTRAINT FOREIGN KEY (did) REFERENCES dept(id);
DESC sys_user;
-- 伪外键
-- 只有新增了外键约束 foreign key的列才叫外键列
-- 外键列就是一个普通列,大型数据不允许使用外键约束
10.4.1 表关系:多对多
不能在任一表中添加外键列,依靠中间表维护2张表的关系
例如:角色和菜单表
rid | mid |
---|---|
1 | 2 |
1 | 3 |
2 | 1 |
2 | 2 |
2 | 3 |
10.5 默认约束 DEFAULT
默认值的概念
“默认值(Default)”的完整称呼是“默认值约束(Default Constraint)”。MySQL 默认值约束用来指定某列的默认值。
10.5.1 设置默认值
使用 DEFAULT 关键字设置默认值约束,具体的语法规则如下:
<字段名> <数据类型> DEFAULT <默认值>;
--示例:
CREATE TABLE student3(
id INT PRIMARY KEY,
name VARCHAR (50) NOT NULL UNIQUE,
sex CHAR (2) DEFAULT '女',
-- 设置默认值,如果添加记录时没有给值,则数据库保存默认值
phone CHAR (18),
age INT CHECK (age BETWEEN 17 AND 22),
create_time DATETIME DEFAULT NOW()
);
10.5.2 修改表中的默认值
ALTER TABLE <数据表名>
CHANGE COLUMN <字段名> <数据类型> DEFAULT <默认值>;
-- 示例
ALTER TABLE student3
CHANGE COLUMN sex
sex CHAR(2) DEFAULT '男';
DESC student3;
10.5.3 删除默认值约束
删除,就是把默认值设为空就好了
修改表时删除默认值约束的语法规则如下:
ALTER TABLE <数据表名>
CHANGE COLUMN <字段名> <字段名> <数据类型> DEFAULT NULL;
知识补充:动态链接ip
如何链接他人的服务器:根据ip链接
方法:给root用户授权:进入mysql数据库的user表,把root用户的host改为通配符“%”,重启MySQL服务,生效。
11.数据查询语言DQL
整体编写无法确定。需求 条件 完全不同
查询都会查询出来一个结果集。都在一张虚拟表中
11.1 基本语法
SELECT
列名1,列名2....列名n /*要查询的字段,多个字段用逗号隔开*/
FROM
表1,表2...表n /*要查询的表名称*/
[WHERE 条件1 AND/OR 条件1] -- 条件(表中的列参与)过滤
[GROUP BY 列] -- 根据指定的列进行分组 分组查询 优先级高于
[HAVING 条件1 AND/OR 条件1] -- 条件过滤(分组之后的数据进行过滤) 不能和where一起出现
[ORDER BY 列1,列2 ASC/DESC] -- 根据列进行排序 默认升序 ASC 降序: DESC
[LIMIT ?/?,?] -- 限定结果集(分页查询);
SELECT 后面可以是表中的字段、常量值、表达式、函数;
查询的结果是一个虚拟的表格/临时表。
11.2 建库建表
下图表案例可自己创建,练习巩固前面学习的数据库语言。
CREATE TABLE stu (
sid CHAR(6),
sname VARCHAR(50),
age INT,
gender VARCHAR(50)
);
INSERT INTO stu VALUES('S_1001', 'liuYi', 35, 'male');
INSERT INTO stu VALUES('S_1002', 'chenEr', 15, 'female');
INSERT INTO stu VALUES('S_1003', 'zhangSan', 95, 'male');
INSERT INTO stu VALUES('S_1004', 'liSi', 65, 'female');
INSERT INTO stu VALUES('S_1005', 'wangWu', 55, 'male');
INSERT INTO stu VALUES('S_1006', 'zhaoLiu', 75, 'female');
INSERT INTO stu VALUES('S_1007', 'sunQi', 25, 'male');
INSERT INTO stu VALUES('S_1008', 'zhouBa', 45, 'female');
INSERT INTO stu VALUES('S_1009', 'wuJiu', 85, 'male');
INSERT INTO stu VALUES('S_1010', 'zhengShi', 5, 'female');
INSERT INTO stu VALUES('S_1011', 'xxx', NULL, NULL);
字段名称 | 字段类型 | 说明 |
---|---|---|
empno | int | 员工编号 |
ename | varchar(50) | 员工姓名 |
job | varchar(50) | 员工工作 |
mgr | int | 领导编号 |
hiredate | date | 入职日期 |
sal | decimal(7,2) | 月薪 |
comm | decimal(7,2) | 奖金 |
deptno | int | 部门编号 |
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm decimal(7,2),
deptno INT
) ;
INSERT INTO emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
字段名称 | 字段类型 | 说明 |
---|---|---|
deptno | int | 部门分编码 |
dname | varchar(50) | 部门名称 |
loc | varchar(50) | 部门所在地点 |
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm decimal(7,2),
deptno INT
) ;
INSERT INTO emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
11.3 基础查询
-- 1.查询所有列
SELECT * FROM stu;
-- 2.查询指定列
SELECT sid,sname,sage FROM stu;
11.4 条件查询 WHERE
条件查询就是在查询时给出WHERE子句,在WHERE子句中可以使用如下运算符及关键字:
=、!=、<>不等于、<、<=、>、>=;
BETWEEN…AND;是否满足一个区间范围 >= <=
IN(set);条件的集合
IS NULL;
AND; 连接多个条件的查询
OR;or 满足其中一个条件就可以
NOT
根据需求练习:
1. 查询学生性别为女,并且年龄50的记录
2、查询学号为S_1001,S_1002,S_1003的记录
3、查询学号不是S_1001,S_1002,S_1003的记录
4、查询年龄为null的记录
5、查询年龄在20到40之间的学生记录
6、查询性别非男的学生记录
7、查询姓名不为null的学生记录
代码参考:
-- 1、查询学生性别为女,并且年龄50的记录
SELECT * FROM stu WHERE gender='FEMALE' AND age=15;
-- 2、查询学号为S_1001,S_1002,S_1003的记录
SELECT * FROM stu WHERE sid ='s_1001' OR sid ='s_1002' OR sid ='s_1003';
SELECT * FROM stu WHERE sid IN ('s_1001','s_1002','s_1003');
-- 3、查询学号不是S_1001,S_1002,S_1003的记录
SELECT * FROM stu WHERE sid !='s_1001' AND sid <>'s_1002' AND sid !='s_1003';
SELECT * FROM stu WHERE sid NOT IN ('s_1001','s_1002','s_1003');
-- 4、查询年龄为null的记录
SELECT * FROM stu WHERE age IS NOT NULL;
-- 5、查询年龄在20到40之间的学生记录
SELECT * FROM stu WHERE age>=20 AND age<=40;
SELECT * FROM stu WHERE age BETWEEN 20 AND 40;
-- 6、查询性别非男的学生记录
SELECT * FROM stu WHERE gender !='male' OR gender IS NULL;
11.5 模糊查询 LIKE
模糊查询,处理字符类型.
_:通配任意一个字符(数字,字母,汉字,特殊符号等)
%:表示0或多个字符
根据需求联系:
1、查询姓名由5个字母构成的学生记录
2、查询姓名以“z”开头的学生记录
3、查询姓名中第2个字母为“i”的学生记录
4、查询姓名中包含“a”字母的学生记录
代码参考:
-- 1、查询姓名由5个字符构成的学生记录
-- 通配符: 数据 一个字符使用 _
SELECT * FROM stu WHERE sname LIKE '_____';
SELECT * FROM stu WHERE CHAR_LENGTH(sname)=5;
-- 通配不定数量的字符的数据 %
-- 2、查询姓名以“z”开头的学生记录
SELECT * FROM stu WHERE sname LIKE 'z%';
-- 3、查询姓名中第2个字母为“i”的学生记录
SELECT * FROM stu WHERE sname LIKE '_i%';
-- 4、查询姓名中包含“a”字母的学生记录
SELECT * FROM stu WHERE sname LIKE '%a%';
11.6 字段控制查询
1 DISTINCT
●对指定的列的数据进行去重.对行记录去重
●去除重复记录(两行或两行以上记录中系列的上的数据都相同),例如emp表中sal字段就存在相同的记录。当只查询emp表的sal字段时,那么会出现重复记录,那么想去除重复记录,需要使用DISTINCT:
1. 查询学生表中的所有性别
2. 查询所有的员工信息
-- 1. 查询学生表中的所有性别
SELECT gender FROM stu;
SELECT DISTINCT gender FROM stu ;
-- 2. 查询所有的员工信息
SELECT empno,ename,sal,mgr FROM emp;
-- -- DISTINCT去重 后面有多个字段 当这多个字段的值都相同的时候认为是重复的
SELECT DISTINCT empno,ename,sal,mgr FROM emp;
2 IFNULL(列名,自定义的默认值)
数据和NULL做运算最后结果依然是NULL.IFNULL函数:对指定列的数据进行判断 列的值为NULL 那就使用自定义的值进行运算 否则,依然使用当前列的值进行运算
1.查询学生的明年的年龄
2.查询员工的月薪和佣金之和
-- 查询学生的明年的年龄
-- 概念: 临时表/虚拟表 所有的查询的结果都在一张临时表/虚拟表中。
-- 查询的虚拟表 在物理内存中不一定存在的。
-- 列的数据是null 执行任意算术运算 结果还是null
-- IFNULL(列,默认数据)
SELECT sid,sname,age,gender,age+1 FROM stu;
-- 查询所有员工的薪水+奖金之和
SELECT empno,ename,sal,comm, sal+IFNULL(comm,0) FROM emp;
3 AS
●在上面查询中出现列名为sal+IFNULL(comm,0),这很不美观,现在我们给这一列给出一个别名,为total:
●给列起别名时,是可以省略AS关键字的
●表名,字段名等都可以使用别名查询
-- 很多时候 在查询期间 会有 很多新的列 列名使用默认的数据作为列名
-- 建议起别名进行查询 AS AS 可以省略
-- 重名情况使用别名可以区分
-- 对列 表都可以起别名
SELECT empno,ename,sal,comm, sal+IFNULL(comm,0) AS money FROM emp;
SELECT u.id FROM demo.tb_userinfo AS u;
SELECT sid AS '学生id',sname AS '学生姓名' FROM stu;
11.7 排序 ORDER BY
●排序。对行记录进行升序或者降序排列。
●可以跟单个字段,多个字段,表达式,函数,别名进行排序。
●默认是升序 ASC , 降序为DESC.
-- 很多时候 在查询期间 会有 很多新的列 列名使用默认的数据作为列名
-- 建议起别名进行查询 AS AS 可以省略
-- 重名情况使用别名可以区分
-- 对列 表都可以起别名
SELECT empno,ename,sal,comm, sal+IFNULL(comm,0) AS money FROM emp;
SELECT u.id FROM demo.tb_userinfo AS u;
SELECT sid AS '学生id',sname AS '学生姓名' FROM stu;
11.8 组函数:聚合函数
- ●还可以称为组函数、分组函数
- ●用作统计使用,又称为聚合函数或者统计函数或者组函数
- ●聚合函数是用来做纵向运算的函数:
- ●COUNT(字段/列):统计指定列不为NULL的记录行数;一般使用count(*)统计行数,不论是否为NULL值
- ●MAX(字段/列):计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;
- ●MIN(字段/列):计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
- ●SUM(字段/列):计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;
- ●AVG(字段/列):计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;
- ●SUM、AVG一般处理数值型
- ●MAX、MIN、COUNT可以处理任意数据类型 ●分组函数都忽略了NULL值,可以和DISTINCT搭配使用 ●注意点:组函数可以出现多个,但是不能嵌套;如果没有GROUP BY 子句,结果集中所有行数作为一组
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
11.9 分组查询 GROUP BY
●对行记录进行分组查询。
●查询出来的字段要求是 GROUP BY 后的字段,查询字段中可以出现组函数
●SELECT 后面的字段 是分组字段
●GROUP BY后面可以跟聚合函数 可以起别名
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
11.10 HAVING
●与WHERE的功能一样,都是用来实现条件过滤。
●WHERE VS HAVING
●1、 WHERE是对分组前进行过滤;HAVING是对分组后进行过滤
●2、WHERE是比分组先执行的,HAVING是在分组之后执行的;
●3、WHERE中不能出现分组/聚合函数,HAVING中可以出现
●4、HAVING后面可以跟别名
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
.........................................................
11.11 LIMIT
●分页查询。限定查询的结果集。
● 对最后的结果进行限定(mysql独有)
●SELECT * FROM 表 LIMIT size; 指定从第一条记录开始查询 查size条
●SELECT * FROM 表 LIMIT ?,size 指定从第n条记录(index)开始查询 查size条
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
11.12 多表查询
●多表查询,也可以称为关联查询。
●查询多张表的记录。
1 内连接
●多表等值连接的结果是多表的交集部分,N表连接,至少需要N-1个连接条件,没有顺序要求,一般起别名
●非等值连接,只要不是等号连接的都是非等值连接
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
2 外连接
●外连接,有主表有从表,主表肯定会显示完整的内容 ●左外连接,以左表为主,右表没有的数据使用NULL或者0进行填充。
●右外连接,以右表为主,左表 没有的数据使用NULL或者0进行填充。
●左外与右外的条件必须使用ON进行关联。
●ON后面的条件(ON条件)和WHERE条件的区别:
ON条件:是过滤两个链接表笛卡尔积形成中间表的约束条件
WHERE条件:在没有ON的单表查询中,是限制物理表或者中间查询结果返回记录的约束。 在两表或多表连 接中是限制连接形成最终中间表的返回结果的约束。 ●建议:ON只进行外连接操作,WHERE只过滤中间表的记录
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
3 自连接
●本表与本表进行关联查询。 把一张表看成多张表进行处理。
●通过别名,将同一张表视为多张表;
●什么情况下使用自连接;同一张表中某个字段要去关联另外一个字段
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
11.13 子查询
也可称为嵌套查询。
●子查询的作用:查询条件未知的事物.
●查询条件已知的问题:例如:查询工资为800的员工信息
●查询条件未知的问题:例如:查询工资为20号部门平均工资的员工信息
根据子查询查询的结果不同,分为
●标量子查询(子查询结果为单个值)
●列子查询(子查询结果为1列)
●行子查询(子查询结果为1行)
●表子查询(子查询结果为多行多了)
1、查询emp表中记录数:
2、查询emp表中有佣金的人数:注意,因为count()函数中给出的是comm列,那么只统计comm列非NULL的行数。
3、查询emp表中月薪大于2500的人数:
4、统计月薪与佣金之和大于2500元的人数:
5、查询有佣金的人数,以及有领导的人数:
6、查询所有雇员月薪和:
7、查询所有雇员月薪和,以及所有雇员佣金和:
8、查询所有雇员月薪+佣金和:
9、统计所有员工平均工资:
10、查询最高工资和最低工资
-- 查询emp表中有佣金的人数,统计指定列不为NULL的记录行数
SELECT count(comm) a FROM emp;
-- SELECT 200+null;
SELECT count(empno) AS '总人数' FROM emp;
SELECT count(*) AS '总人数' FROM emp;
SELECT count(1) AS '总人数' FROM emp;
-- 查询emp表中有佣金的人数
SELECT count(comm) FROM emp;
-- 查询emp表中月薪大于2500的人数:
SELECT * FROM emp WHERE sal>2500;
-- 统计月薪与佣金之和大于2500元的人数: ifnull(表达式1,表达式2) 如果表达式1为null那么取表达式2的值,否则取表达式1的值
SELECT * FROM emp WHERE sal+ifnull(comm,0) >2500;
-- 查询有佣金的人数,以及有领导的人数:
SELECT count(comm) FROM emp WHERE mgr is not null;
-- 查询所有雇员月薪和:
SELECT sum(sal) 总薪资 FROM emp;
-- 查询所有雇员月薪和,以及所有雇员佣金和:
SELECT sum(sal) 总薪资,SUM(comm) 总佣金 FROM emp;
-- 查询所有雇员月薪+佣金和
SELECT sum(sal+ifnull(comm,0)) 总佣金 FROM emp;
SELECT sum(sal)+sum(ifnull(comm,0)) 总佣金 FROM emp;
-- 统计所有员工平均工资
SELECT avg(sal) 平均薪资 FROM emp;
-- 查询最高工资和最低工资
SELECT max(sal),min(sal) FROM emp;
11.14 集合运算
●UNION VS UNION ALL
●UNION:二个集合中,如果都有相同的,取其一(行记录)
●UNION ALL:二个集合中,如果都有相同的,都取
-- 一张表数据分成多张表处理的时候
-- 前提: 查询的列的数量以及列的数据类型。
-- 使用1条sql: 查询所有的用户信息
-- 12条
-- 需要将多次查询的结果集合并在一起
-- 集合运算
-- UNION 可以去重
-- UNION ALL 全部展示
SELECT DISTINCT * FROM
(SELECT * FROM user0
UNION ALL
SELECT * FROM user1
UNION ALL
SELECT * FROM user2
UNION ALL
SELECT * FROM user3
UNION ALL
SELECT * FROM user4) AS temp;
SELECT * FROM user0
UNION
SELECT * FROM user1
UNION
SELECT * FROM user2
UNION
SELECT * FROM user3
UNION
SELECT * FROM user4;
SELECT empno, ename FROM emp
UNION
SELECT sid,sname FROM stu;
-- MySQL 可以实现去重操作?
-- 1. DISTINCT
-- 2. UNION
-- 3. GROUP BY
11.15 执行顺序
DQL语句的执行顺序
12.常用函数
12.1 字符函数
函数 | 功能 |
---|---|
concat(str1,str2,…) | 连接字符串 |
insert(str,pos,len,newstr) | 字符串str从第pos位置开始的len个字符替换为新字符串newstr |
lower(str) | 转成小写 |
upper(str) | 转成大写 |
length(str) | 返回字符串str的长度 |
char_length(str) | 返回字符串str的长度 |
lpad(str,ien,padstr) | 返回字符串str,其左边由字符串padstr填补到len字符串长度 |
rpad(str,len,padstr) | 返回字符串str,其左边由字符串padstr填补到len字符串长度 |
trim(str) | 去掉字符串str前缀和后缀的空格 |
repeat(str,count) | 返回str重复count次的结果 |
replace(str,from_str,to_str) | 用字符串to_str替换字符串str中所有的字符串from_str |
substring(str,pos,len) | 从字符串str的pos位置起len个字符长度的子串 |
-- 字符串连接
SELECT concat('java','sun','aa');
-- length() 字节长度
SELECT length(sname),sname FROM tb_stu;
-- 字符长度
SELECT CHAR_LENGTH('java');
-- 去除前后空格
SELECT trim(' ja va ');
-- 重复指定次数
SELECT repeat('ja',4);
-- 字符串替换
SELECT REPLACE('javaoror','or','sun');
-- 截取字串
SELECT substring('javasun',5,3);
12.2 数值函数
函数 | 功能 |
---|---|
abs(x) | 返回x的绝对值 |
ceil(x) | 返回不小于x的最小整数 |
floor(x) | 返回不大于x的最大整数 |
mod(x,y) | 返回x/y的模 |
rand() | 返回0-1之间的随机浮点数 |
round(x,y) | 返回x的四舍五入有y位的小数值 |
truncate(x,y) | 返回x截断位y位的小数值 |
-- 取绝对值
SELECT abs(-32);
-- 向上取最小整数
SELECT ceil(3.2);
-- 向下取最大整数
SELECT floor(3.2);
SELECT floor(score),score FROM tb_stu;
-- 取余数
SELECT mod(21,3);
-- 得到 0-1之间的随机值
SELECT rand();
-- 有2位小数的四舍五入值
SELECT round(5.678,2);
-- 截断,小数位保持2位
SELECT TRUNCATE(5.67888,2);
12.3 日期函数
函数 | 功能 |
---|---|
CURDATE() | 返回当前日期 |
CURTIME() | 返回当前时间 |
NOW() | 返回当前的日期和时间 |
WEEK(date) | 返回指定日期为一年中的第几周 |
YEAR(date) | 返回日期的年份 |
HOUR(time) | 返回time的小时值 |
MINUTE(time) | 返回time的分钟值 |
MONTHNAME(date) | 返回date的月份名 |
DATEDIFF(expr,expr2) | 返回起始时间expr和结束时间exrp2之间的天数 |
DATE_FORMAT(date,fmt) | 返回按字符串fmt格式化日期date值 |
from_unixtime(unix_timestamp,”%Y-%m-%d %H:%i:%S”)常用来将毫秒数转换为时间格式 |
-- 当前日期,当前时间,日期和时间
SELECT CURDATE(),CURTIME(),now();
-- 指定日期是一年中的第几周
SELECT WEEK(now());
-- 返回指定日期的年份
SELECT YEAR(now());
-- 返回指定时间的小时
SELECT hour(now()),hour(CURTIME());
-- 返回date的月份名
SELECT MONTHNAME(now());
12.4 流程函数
SELECT if(value,m,n); -- 如果value为true,则返回m,否则返回n
SELECT ifnull(value,default);
-- 如果value为null,则返回default,否则返回value
CASE WHEN END 函数
简单函数:
CASE 列 WHEN 数据 THEN 数据 ELSE 数据 END;
搜索函数:
CASE
WHEN 条件1 THEN 数据1
WHEN 条件2 THEN 数据2
...
WHEN 条件n THEN 数据n
ELSE 数据
END
12.5 其他函数
SELECT VERSION();
SELECT USER();
SELECT DATABASE();
SELECT MD5();
SELECT UUID();
SELECT LAST_INSERT_ID();
SELECT IF(10>2,'10','2') a;
13.数据库范式
●关系型数据库;使用关系模型去组织数据的数据库 称之为关系型数据库 关系模型就是 二维表格;表格与表格之间有关联;
●其实是一种 规范,规则.
●第一范式(1NF)用来确保每列的原子性,要求每列(或者每个属性值)都是不可再分的最小数据单元(也称为最小的原子单元)。
●第二范式(2NF)在第一范式的基础上更进一层,要求表中的每列都和主键相关,即要求实体的唯一性。如果一个表满足第一范式,并且除了主键以外的其他列全部都依赖于该主键,那么该表满足第二范式。
●第三范式(3NF)在第二范式的基础上更进一层,第三范式是确保每列都和主键列直接相关,而不是间接相关,即限制列的冗余性。如果一个关系满足第二范式,并且除了主键以外的其他列都依赖于主键列,列和列之间不存在相互依赖关系,则满足第三范式。
●在开发中,具体表的设计要看实际。
14.存储引擎
15.备份
●备份数据库表结构,表数据
●1. 物理备份 在my.ini datadir C:\ProgramData\MySQL\MySQL Server 8.0\data (忽略)
●2. 命名行备份 xxx.sql 2.1 导出 mysqldump -uroot -proot demo > D:\a.sql mysqldump -uroot -proot demo sys_user product > D:\b.sql 2.2 导入 在登录服务器成功状态下 source 文件路径 mysql> source D:\a.sql
●3. 使用navicat 3.1 选择数据库或者表 转储sql 3.2 选择数据库 运行sql实现导入
●4. navicat里面备份的功能
16.DCL
概念: DCL(Data Control Language)数据控制语言,用来管理数据库用户,控制数据库的访问权限。
16.1 管理用户
MySQL里面,所有与系统用户相关的信息都存储在了mysql数据库中的user表中。 程序员操作较少,一般都是DBA/运维使用。
1.1 语法
1. 查询用户
USE mysql;
SELECT * FROM user;
2. 创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
3. 修改用户密码
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码'
4.删除用户
DROP USER '用户名'@'主机名';
1.2 操作
USE mysql;
SELECT * FROM user;
-- 创建用户
-- 默认没有权限,只能在localhost访问
CREATE USER 'lisa'@'127.0.0.1' IDENTIFIED BY '1234';
CREATE USER 'jim'@'localhost' IDENTIFIED BY '1234';
-- 创建用户,可以在任意主机访问该数据库
CREATE USER 'zhangsan'@'%' IDENTIFIED BY '1234';
-- 修改用户密码
ALTER USER 'zhangsan'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
-- 删除用户
DROP USER 'jim'@'localhost';
16.2 权限控制
以上我们使用相关语句操作了用户,但是他们都没有权限。
MySQL中定义了多种权限,常用的有以下(想要了解更多,可查询官网文档):
权限 | 说明 |
---|---|
ALL, ALL PRIVILEGES | 所有权限 |
SELECT | 查询数据 |
INSERT | 新增数据 |
UPDATE | 修改数据 |
DELETE | 删除数据 |
DROP | 删除数据库/表/视图 |
CREATE | 创建数据库/表 |
ALTER | 修改表结构 |
相关语法
-- 查询权限
SHOW GRANTS FOR '用户名'@'主机名';
-- 授予权限
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
-- 撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';
基本操作
-- 1. 查询权限
SHOW GRANTS FOR 'zhangsan'@'%';
SHOW GRANTS FOR 'root'@'localhost';
-- 2.授予权限
GRANT ALL ON demo.* TO 'zhangsan'@'%';
-- 3. 撤销权限
REVOKE ALL ON demo.* FROM 'zhangsan'@'%';
17.数据库事务
17.1 事务概念
●Transaction
●事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)
●一个完整的业务需要批量的DML(INSERT、UPDATE、DELETE)语句共同联合完成
●事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同
17.2 四大特性ACID
●原子性(Atomicity):事务不可分割的最小工作单元,事务内的操作要么全做,要么全不做。事务具有要么全部成功 要么全部失败 这就是原子性。
●一致性(Consistency):在事务执行前数据库的数据处于正确的状态,需事务执行完后数据库的数据依然处于正确的状态,即数据完整性约束没有被破坏,如A给B转帐,不论转帐是否成功,转帐之后的A和B的帐户总额和转帐之前是相同的 3000 4000
●隔离性(Isolation):当多个事务处于并发访问同一个数据库资源时,事务之间相互影响,不同的隔离级别决定了各个事务对数据资源访问的不同行为
●持久性(Durability):事务一旦执行成功,它对数据库的改变是不可逆的
●在业务逻辑层,一个service层的某个业务方法可能需要执行多次增删改操作,如果这期间发生了异常,数据库事务不回滚的话 数据库中的数据就会不完整,举个例子,订单信息中包含订单明细,现在在保存订单的业务逻辑方法中,先保存订单成功了,再保存订单明细,如果保存订单明细的过程中失败了,肯定希望之前的保存订单数据回滚。
17.3 TCL
● 开启事务 start transaction | begin ● commit:提交 ● rollback:回滚
-- 在mysql这个DBMS里面 mysql的事务自动提交的。
-- 查询mysql的事务是否是自动提交的
SHOW VARIABLES LIKE '%commit%';
-- autocommit=on/true
SET autocommit=1; -- 关闭数据库事务自动提交
-- SELECT * FROM sysuser;
-- INSERT INTO sysuser (username) values ('aaaa');
-- SELECT * FROM sysuser;
-- COMMIT; -- 将虚拟表的数据更新到物理表
-- ROLLBACK; -- 回滚到事务的开始之前的数据
-- 目前是默认mysql是自动提交事务
-- 手动控制事务
begin; -- 开启事务
update sysuser set balance=balance-1000 where username= '莫扎特';
insert into sysuser (username) values ('aa',100);
update sysuser set balance=balance+1000 where username= '志鹏';
ROLLBACK;
commit;
事务何时开启 何时结束
●开始标志:Mysql默认情况下 任何一条DML语句(insert、update、delete,select)执行,标志事务的开启
●结束标志:
○提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步
○回滚:失败的结束,将所有的DML语句操作历史记录全部清空
●在MySQL中,默认情况下,事务是自动提交的,也就是说,只要执行一条DML语句就开启了事务,并且提交了事务。 ●自动提交机制是可以关闭的,可以由程序控制何时提交。
17.4 与底层数据库的关系
●在事务进行过程中,未结束之前,DML语句是不会更改底层数据,只是将历史操作记录一下,在内存中完成记录。
●只有在事务结束的时候,而且是成功的结束的时候,才会修改底层硬盘文件中的数据。
●如果执行失败,则清空内存中所有的历史操作记录,不会对底层硬盘文件中(数据表)数据做任何修改。
-- 开启事务
START TRANSACTION;
INSERT into stu(sid,sname) VALUES(5,'jerry');
-- rollback 的执行不会更新 磁盘文件
-- commit是事务执行成功 提交
COMMIT;
17.5 隔离级别机制
●主要是与数据库的隔离性有关系。
●不同事务之间具有隔离性,隔离级别分四个:
- ●读未提交:read uncommitted(读到未提交的数据) ○事务A和事务B,事物A未提交的数据,事物B可以读取到 ○这里读取到的数据叫做“脏数据”(已经被改动数据) ○这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别 ○老板给小明发奖金 发了20000 但是事务并没有提交,小明查看奖金 一看到账20000,开心坏了。老板一看数额不对,应该是发2000,赶紧回滚事务 ,修改金额,提交事务, 这时候小明再去查看奖金,发现卡里变成2000
- ●读已提交:read committed(读到已提交的数据) ○事物A和事物B,事物A提交的数据,事物B才能读取到 ○这种隔离级别高于读未提交 ○这种级别可以避免“脏数据” ○这种隔离级别会导致“不可重复读取”(事务B两次读取到的数据不一致) ○这是Oracle默认隔离级别 ○小明拿着工资卡去消费,系统读取到卡里确实有2000元,而此时他的老婆也正好在转账,把小明工资卡的2000元转到另一账户,并在小明之前提交了事务,当小明消费完扣款时,系统检查到小明的工资卡已经没有钱,扣款失败, 小明十分纳闷,查看有2000 却没有扣钱成功。
- ●可重复读:repeatable read ○事务A和事务B,事务A提交之后的数据,事务B读取不到 ○事务B是可重复读取数据 ○这种隔离级别高于读已提交 ○换句话说,对方提交之后的数据,我还是读取不到 ○这种隔离级别可以避免“不可重复读取”,达到可重复读取 ○这是MySQL默认级别 ○虽然可以达到可重复读取,但是会导致“幻读”(A把所有数据都清空了,B在这个时候修改了其中一条数据,当A结束后发现还存在一条数据,就好像产生了幻觉一样,这就是幻读) ○小明卡里2000 要取钱 一旦开始读取卡里余额的时候 事务已经开始,小明老婆就不能对卡里数据进行修改 也就是不能转账 虽然Repeatable read避免了不可重复读,但还有可能出现幻读。 (小明老婆是银行职员 经常通过银行内部系统查询小明卡消费记录 有一天 她查到小明本月消费金额为200。而此时小明正在买单消费1000元 新增了一条消费1000的消费记录 并提交了事务 她老婆把消费明细打印出来,却发现消费总额为1200 很是不解 以为出现了幻觉 幻读就是这样产生的。)
- ●串行化:serializable ○事务A和事务B,事务A在操作数据库时,事务B只能排队等待 ○这种隔离级别很少使用,吞吐量太低,用户体验差(特别的慢) ○这种级别可以避免“幻读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行,而不并发
隔离级别机制 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | Y | Y | Y |
读已提交 | N | Y | Y |
可重复读 | N | N | Y |
串行化 | N | N | N |
-- 串行化: 完全保证数据的安全性。性能最低,代价高。 几乎没有软件使用。
-- mysql这个软件 默认的隔离级别机制是 repeatable read
SHOW VARIABLES LIKE '%ISOLATION%';
-- 建议不要修改。
-- 目前学习 会修改机制 演示对数据造成的不同的影响。
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;