banner
Hi my new friend!

MySql

Scroll down

创建,删除,查询数据库与表等基础语句(指令)

创建数据库

#演示数据库的操作

#启动和关闭数据库

net START mysql
net STOP mysql

#创建一个名为lby_db01的数据库。

#使用指令创建数据库

CREATE DATABASE lby_db01

#删除数据库

DROP DATABASE lby_db01

#创建一个使用utf8字符集的lby_db02数据库

CREATE DATABASE lby_db02 CHARACTER SET utf8

#创建一个使用utf8字符集,并带校对规则的lby_db03数据库

CREATE DATABASE lby_db03 CHARACTER SET utf8 COLLATE utf8_bin

#校对规则 utf8_bin 区分大小写 默认utf8_general_ci 不区分大小写

#下面是一条查询的sql,select 表示查询 * 表示所有字段 FROM表示从哪个表
#WHERE 表示从哪个字段 NAME = ‘tom’ 表示查询名字是tom

SELECT * FROM t1 WHERE NAME = 'tom'

查询数据库

#查看当前数据库服务器中的所有数据库

SHOW DATABASES

#查看前面创建的lby_db01数据库的定义信息

SHOW CREATE DATABASE lby_db01

#在创建数据库,表的时候,为了规避关键字,可以使用反引号解决

CREATE DATABASE `create`

#删除上面创建的create数据库

DROP DATABASE `create`

备份恢复数据库

#备份,要在Dos下执行mysqldump指令其实在mysql安装目录下\bin
#这个备份的文件,就是对应的sql语句

mysqldump -u root -p -B lby_db02 lby_db03 > C:\\bak.sql
DROP DATABASE lby_db03;

#恢复数据库(注意:进入Mysql命令行执行)

source C:\\bak.sql

#第二个恢复方法,直接将bak.sql的内容放到查询编辑器中,执行就可以了

#备份数据库的表

mysqldump -u root -p lby_db02 t1 t2 >C:\\bak02.sql

创建表

#指令创建表

CREATE TABLE `user` (
	id INT,
	`name` VARCHAR(255),
	`password` VARCHAR(255),
	birthday DATE)
	CHARACTER SET utf8 COLLATE utf8_bin ENGINE INNODB;

简单说明:utf8表示这个表的字符集utf8_bin表示这个表的校对规则innodb表示这个表的引擎

character set:指定表的字符集,若没有指定,则默认为所在数据库的字符集

collate:指定表的校对规则,若没有指定,则默认为所在数据库的校对规则

engine:指定表的引擎

练习:

CREATE TABLE t15 (
	id INT,
	`name` CHAR(32),
	sex CHAR(32),
	birthday DATE,
	entry_date DATETIME,
	job CHAR(32),
	Salary DOUBLE,
	RESUME TEXT) CHARSET utf8 COLLATE utf8_bin ENGINE INNODB;
SELECT * FROM t15;

– 添加一条

INSERT INTO t15 VALUES(100,'李白','2000-11-18','2018-11-18 11:11:11',
'写诗的',10000,'皇上叫我写诗','');

修改表

#添加列
– ALTER TABLE tablename
– ADD (column datatype [DEFAULT exper]
– [, column datatype]…);
员工表t15的基础上增加一个image列,char类型(要求加在resume后面)

ALTER TABLE t15
ADD	image CHAR(32) NOT NULL DEFAULT '' AFTER RESUME;
DESC employee

显示表结构,可以查看表的所有列

#修改列
修改job列,使其长度为60

ALTER TABLE t15
	MODIFY job VARCHAR(60) NOT NULL DEFAULT ' '

删除sec

ALTER TABLE t15
	DROP sex

表名改为employee

RENAME TABLE t15 TO employee

修改表的字符集为utf8

ALTER TABLE employee CHARACTER SET utf8

列名name修改为user_name

ALTER TABLE employee CHANGE NAME user_name VARCHAR(32) NOT NULL DEFAULT ' '
SELECT * FROM employee;

列类型

常用数据类型

image-20221201203136555

整型

#演示整数
#说明:表的字符集,校验规则,存储引擎,使用默认
#1.如果没有指定unsigned则TINYINT就是有符号的(-128~127),如果没有符号(0-255)
#2.如果指定unsigned则TINYINT就是无符号0-255

CREATE TABLE t3 (
	id TINYINT);
CREATE TABLE t4 (
	id TINYINT UNSIGNED);
INSERT INTO t3 VALUES(128);#这是非常简单的添加语句,添加失败,超过tinyint范围,因为这是带符号的

SELECT * FROM t3
INSERT INTO t4 VALUES(255);#添加成功
SELECT * FROM t4

bit

#演示bit类型使用
#说明
#1.bit(m) m在1-64
#2.添加数据 范围 按照你给的位数来确定,比如m=8表示一个字节 0~255
#3.显示按照bit
#4.查询时,仍然可以按照数来查询

CREATE TABLE t5 (num BIT(8));
INSERT INTO t5 VALUES(255);
SELECT * FROM t5
SELECT * FROM t5 WHERE num = 1;

小数型

#演示decimal类型,float,double使用(一般使用double或者decimal,因为其精度更高
#创建表

CREATE TABLE t6 (
	num1 FLOAT,
	num2 DOUBLE,
	num3 DECIMAL(30,20));

#decimal(m,n)如果没有给m,n赋值,那么会默认m为10,n为0
#添加数据

INSERT INTO t6 VALUES(88.12345678912345,88.12345678912345,88.12345678912345);
SELECT * FROM t6;

#decimal可以存放很大的数

CREATE TABLE t7 (
	num DECIMAL(65));
INSERT INTO t7 VALUES(899999999999999999999999999999999999999999999999999999999999999);
SELECT * FROM t7;
CREATE TABLE t8 (
	num BIGINT UNSIGNED);
INSERT INTO t8 VALUES(899999999999999999999999999999999999999999999999999999999999999);
SELECT * FROM t8;

image-20221201203217730

字符串

#演示字符串类型使用char varchar
#注释的快捷键 shift+ctrl+c,取消注释 shift+ctrl+r
– CHAR(size)
固定长度字符串 最大255字符
– VARCHAR(size) 0~65535(字节,而不是字符)
可变长度字符串 最大65532字节utf8编码最大21844字符 1-3个字节用于记录大小
– 如果表的编码是 utf8 varchar(size) size=(65535-3) / 3 = 21844
– 如果表的编码是 gbk varchar(size) size=(65535-3) / 2 = 32766

CREATE TABLE t9 (
	`name` CHAR(255));
CREATE TABLE t10 (
	`name` VARCHAR(32766) CHARACTER SET gbk);

#演示字符串类型的使用细节
#1.char(4) 和 varchar(4) 这个4表示的是字符,而不是字节,不区分字符是汉字还是字母
#2.char(4)是定长(固定的大小),就是说,即使你插入’aa’,也会占用分配的4个字节的空间
#3.varchar(4)是变长(变化的大小),就是说,如果你插入了’aa’,实际占用空间大小并不是4个字符
– 而是按照实际占用空间来分配
– varchar本身还需要1-3个字节来记录存放内容长度
L(实际数据大小)+(1-3)字节

CREATE TABLE t11 (
	`name` CHAR(4));
INSERT INTO t11 VALUES('abcd');

INSERT INTO t11 VALUES('白居易号');

SELECT * FROM t11;
CREATE TABLE t12 (
	`name` VARCHAR(4));
INSERT INTO t12 VALUES('abcd');

INSERT INTO t12 VALUES('白居易号');

INSERT INTO t12 VALUES('ab李白');

SELECT * FROM t12;

#4.什么时候使用char,什么时候使用varchar
– 如果数据定长,推荐使用char,比如md5的密码,邮编,手机号,身份证号码等.char(32)
– 如果一个字段的长度是不确定,我们使用varchar,比如留言,文章
查询速度:char>varchar

#5.在存放文本时,也可以使用Text数据类型
– 可以将Text列视为VARCHAR列,注意Text不能有默认值,大小0-2^16字节
– 如果希望存放更多字符,可以选择
– MEDIUMTEXT 0-2^24 或者 LONGTEXT 0~2^32

CREATE TABLE t13 (content TEXT, content2 MEDIUMTEXT, content3 LONGTEXT);
INSERT INTO t13 VALUES('李白是诗神','白居易是诗人','杜甫是散人~~');
SELECT * FROM t13;

日期类

#演示时间相关的类型
#创建一张表,date,datetime,timestamp

CREATE TABLE t14 (
	birthday DATE, -- 生日
	job_time DATETIME, -- 记录年月日 时分秒
	login_time TIMESTAMP
	 NOT NULL DEFAULT CURRENT_TIMESTAMP 
	 ON UPDATE CURRENT_TIMESTAMP); 

– 登录时间,如果希望login_time列自动更新,需要配置

SELECT * FROM t14;
	INSERT INTO t14(birthday,job_time)
	VALUES('2022-11-18','2022-11-18 20:41:10');

– 如果我们更新了t14表的某条记录,login_time列会自动的以当前时间进行更新

CRUD语句

insert

#练习insert语句
– 创建一张商品表goods (id int , goods_name , varchar(10) , price double);
– 添加两条记录

CREATE TABLE `goods` (
	id INT,
	goods_name VARCHAR(10),
	price DOUBLE);

– 添加数据

INSERT INTO `goods` (id,goods_name,price)
	VALUES(10,'华为手机',5000);
INSERT INTO `goods` (id,goods_name,price)
	VALUES(20,'苹果手机',9000);
SELECT * FROM `goods`;
CREATE TABLE `goods2` (
	id INT,
	goods_name VARCHAR(10),
	price DOUBLE NOT NULL DEFAULT 100);

#追加练习
– 使用insert语句向表employee中插入2个员工的信息

INSERT INTO employee (id,user_name,birthday,entry_date,job,Salary,`resume`)
	VALUES(101,'杜甫','1998-11-21','1998-11-28 21:00:00','写诗的',6000,'为百姓写诗');
INSERT INTO employee (id,user_name,birthday,entry_date,job,Salary,`resume`)
	VALUES(102,'白居易','2016-11-21','2016-11-28 21:00:00','写诗的',6000,'为历史写诗');
SELECT * FROM employee;

#说明insert语句的细节
– 1.插入的数据应与字段的数据类型相同
– 比如把’abc’添加到int类型会错误

INSERT INTO `goods` (id,goods_name,price)**
	VALUES('abc','小米手机',4000);#Incorrect integer value
INSERT INTO `goods` (id,goods_name,price)**
	VALUES('30','小米手机',4000);#success,底层会尝试转换

– 2.数据的长度应在列的规定范围内,例如:不能将一个长度为80的字符串加入到长度为40的列中

INSERT INTO `goods` (id,goods_name,price)
	VALUES(40,'vivovivovivovivovivovivo手机',3000);#Data too long for column

– 3.在values中列出的数据位置必须与被加入的列的排序位置相对应

INSERT INTO `goods` (id,goods_name,price)
	VALUES('vivo手机',40,3000);#Incorrect integer value
INSERT INTO `goods` (goods_name,id,price)
	VALUES('vivo手机',40,3000);#success

– 4.字符和日期型数据应包含在单引号中

INSERT INTO `goods` (id,goods_name,price)
	VALUES(40,vivo手机,3000);#Unknown column 应该'vivo手机'

– 5.**列可以插入空值[前提是该字段允许为空]**,insert into table_name values(null)

INSERT INTO `goods` (id,goods_name,price)
	VALUES(50,'oppo手机',NULL);#success 因为我们创建表的时候没设置不为空 即(not null)

– 6.insert into table_name (列名…) values (),(),() 形式添加多条记录

INSERT INTO `goods` (id,goods_name,price)
	VALUES(60,'三星手机',6000),(60,'海尔手机',7000);#success

– 7.如果是给表中的所有字段添加数据,可以不写前面的字段名称

INSERT INTO `goods` 
	VALUES(70,'IBM手机',5000);#success

– 8.默认值的使用,当不给某个字段值时,如果有默认值就会添加默认值,否则报错
如果某个列,没有指定not null,那么添加数据时,没有给定值,则会默认给null

INSERT INTO `goods2` (id,goods_name)
	VALUES(80,'格力手机');#success,并且自动给price添加默认值100
SELECT * FROM `goods2`;

update

#演示update语句
– 要求:在上面创建的employee表中修改表中的记录
– 1.将所有员工薪水修改为5000元.如果没有带where这个条件,会修改所有的记录,因此使用要小心

UPDATE employee SET Salary = 5000

– 2.将姓名为李白的员工薪水修改为8000元

UPDATE employee 
	SET salary = 3000 
	WHERE user_name = '李白';

– 3.将姓名为杜甫的员工在原有薪水基础上增加2000元

UPDATE employee
	SET salary = salary + 2000
	WHERE user_name = '杜甫';
	
SELECT * FROM employee;

#update语句使用细节
– 1.update语法可以用新值更新原有表行中的各列
– 2.set子句指示要修改哪些列和要给予哪些值
– 3.where子句指定应更新哪些行。如没有where子句,则更新所有的行(记录),因此使用时要小心
– 4.如果需要
修改多个字段
,可以通过set 字段1=值1,字段2=值2…..

delete

#delete语句演示
删除表中名称为’杜甫’的记录

DELETE FROM employee
	WHERE user_name = '杜甫';

– 删除表中所有记录
如不需要where子句,将删除表中所有数据

DELETE FROM employee;

#delete语句使用细节
delete语句不能删除某一列的值(可使用update 设为null或者’’)

UPDATE employee SET job = '' WHERE user_name='杜甫';

– 使用delete语句仅删除记录,不删除表本身。如要删除表,使用drop table语句
drop table 表名;

DROP TABLE employee;
SELECT * FROM employee;

select

1.0

– select 语句【重点 难点
格式:
– SELECT [distinct] * {column1,column2,column3..}
– FROM table_name;

CREATE TABLE student (
	id INT NOT NULL DEFAULT 1,
	`name` VARCHAR(20) NOT NULL DEFAULT '',
	chinese FLOAT NOT NULL DEFAULT 0.0,
	english FLOAT NOT NULL DEFAULT 0.0,
	math FLOAT NOT NULL DEFAULT 0.0);
INSERT INTO student 
	VALUES(1,'李白',100,90,80),(2,'杜甫',100,90,90),(3,'白居易',95,80,80),(4,'王维',95,80,80),
	(5,'赵云',82,84,67),(6,'关羽',88,98,90),(7,'张飞',67,98,56),(8,'李世民',100,90,95);
	
SELECT * FROM student;

– 查询表中所有学生的信息

SELECT * FROM student;

– 查询表中所有学生的姓名和对应的英语成绩

SELECT `name`,english FROM student;

过滤表中重复数据 distinct

SELECT DISTINCT english FROM student;

要查询的记录,每个字段都相同,才会去重

SELECT DISTINCT `name`,english FROM student;

2.0

#select语句的使用
– 使用表达式对查询的列进行运算
SELECT * |{column1|expression,column2|expression…}
FROM table_name;

– 在select语句中可使用as语句
SELECT column_name as 别名 from 表名;

统计每个学生的总分

SELECT `name`,(chinese+english+math) FROM student;

– 在所有学生总分加10分的情况

SELECT `name`,(chinese+english+math+10) FROM student;

使用别名表示学生分数

SELECT `name` AS '名字',(chinese+english+math+10) AS total_score FROM student;

3.0

#select语句
– 查询姓名为赵云的学生成绩

SELECT * FROM student WHERE `name`='赵云';

– 查询英语成绩大于90分的同学

SELECT * FROM student WHERE english>90;

– 查询总分大于200分的所有同学

SELECT * FROM student WHERE (chinese+english+math)>200;

– 查询math大于60并且(and)id大于4的学生成绩

SELECT * FROM student WHERE math>60 AND id>4;

– 查询英语成绩大于语文成绩的同学

SELECT * FROM student WHERE english>chinese;

– 查询总分大于200分并且数学成绩小于语文成绩的姓李的学生
李%表示名字以李开头的就可以

SELECT * FROM student WHERE
	(chinese+math+english)>200 AND math<chinese
	 AND `name` LIKE '李%';

– 查询英语成绩在80-90之间的同学

SELECT * FROM student WHERE english>=80 AND english<=90;

between..and…是一个闭区间

SELECT * FROM student WHERE english BETWEEN 80 AND 90;

– 查询数学分数为89,90,91的同学

SELECT * FROM student WHERE math BETWEEN 89 AND 91;
SELECT * FROM student WHERE math=89 OR math=90 OR math=91;
SELECT * FROM student WHERE math IN(89,90,91);

– 查询所有姓李的学生成绩(%表示任意多个字符)

SELECT * FROM student WHERE `name` LIKE '李%';

– 查询数学分>80,语文成绩>80的同学

SELECT * FROM student WHERE math>80 AND chinese>80;

函数

统计函数

#演示mysql统计函数的使用
count
– 统计一个班级****共有多少学生

SELECT COUNT(*) FROM student;

– 统计数学成绩大于90的有多少个

SELECT COUNT(*) FROM student WHERE math>90;

– 统计总分大于250的人数有多少

SELECT COUNT(*) FROM student WHERE (math+chinese+english)>250;

count(*)count(列)的区别
– 解释:
count(*)返回满足条件的记录的行数

count(列):统计满足条件的某列有多少个,但是会排除为null

CREATE TABLE t15 (
	`name` VARCHAR(20));
INSERT INTO t15 VALUES('tom');
INSERT INTO t15 VALUES('jack');
INSERT INTO t15 VALUES('mary');
INSERT INTO t15 VALUES(NULL);
SELECT * FROM t15;
SELECT COUNT(*) FROM t15;-- 4
SELECT COUNT(`name`) FROM t15;-- 3

sum
– 统计一个班级数学总成绩

SELECT SUM(math) FROM student;

– 统计一个班级语文,英语,数学各科的总成绩

SELECT SUM(math),SUM(english),SUM(chinese) FROM student;

– 统计一个班级语文,英语,数学的成绩总和

SELECT SUM(math+english+chinese) FROM student;

– 统计一个班级语文成绩平均分

SELECT SUM(chinese)/COUNT(*) FROM student;

avg
– 求一个班级数学平均分

SELECT AVG(math) FROM student;

– 求一个班级总分平均分

SELECT AVG(math+english+chinese) FROM student;

Max/min
– 求班级最高分和最低分

SELECT MAX(math+chinese+english) FROM student;
SELECT MIN(math+chinese+english) FROM student;

分组函数

#演示group by的使用

CREATE TABLE dept(/*部门表*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR(20)NOT NULL DEFAULT '' '',
1oc VARCHAR(13)NOT NULL DEFAULT '' '');
INSERT INTO dept VALUES(10,'ACCOUNTING','NEW YORK'),(20,'RESEARCH','DALLAS'),(30,'SALES','CHICAGO'),(40,'OPERATIONS','BOSTON');
SELECT * FROM dept;

#创建表EMP雇员

DROP TABLE emp;
CREATE TABLE emp
(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*编号*/
ename VARCHAR(20)NOT NULL DEFAULT '' '',/*名字*/
job VARCHAR(9)NOT NULL DEFAULT '' '',/*工作*/
mgr MEDIUMINT UNSIGNED,/*上级编号*/
hiredate DATE NOT NULL,/*入职时间*/
sa1 DECIMAL(7,2) NOT NULL,/*薪水*/
comm DECIMAL(7,2),/*红利*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0/*部门编号*/);

– 添加测试数据

INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1990-12-17',800.00,NULL,20),
(7499,'ALLEN','SALESMAN',7698,'1991-2-20',1600.00,300.00,30),
(7521,'WARD','SALESMAN',7698,'1991-2-22',1250.00,500.00,30),
(7566,'J0NES','MANAGER',7839,'1991-4-2',2975.00,NULL,20),
(7654,'MARTIN','SALESMAN',7698,'1991-9-28',1250.00,1400.00,30),
(7698,'BLAKE','MANAGER',7839,'1991-5-1',2850.00,NULL,30),
(7782,'CLARK','MANAGER',7839,'1991-6-9',2450.00,NULL,10),
(7788,'SC0TT','ANALYST',7566,'1997-4-19',3000.00,NULL,20),
(7839,'KING','PRESIDENT',NULL,'1991-11-17',5000.00,NULL,10),
(7844,'TURNER','SALESMAN',7698,'1991-9-8',1500.00,NULL,30),
(7900,'JAMES','CLERK',7698,'1991-12-3',950.00,NULL,30),
(7902,'FORD','ANALYST',7566,'1991-12-3',3000.00,NULL,20),
(7934,'MILLER','CLERK',7782,'1992-1-23',1300.00,NULL,10);

SELECT * FROM emp;

#工资级别表

CREATE TABLE salgrade(
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*工资级别*/
losal DECIMAL (17,2) NOT NULL,/*该级别的最低工资*/
hisal DECIMAL(17,2) NOT NULL /*该级别的最高工资*/
);
INSERT INTO salgrade VALUES(1,700,1200);
INSERT INTO salgrade VALUES(2,1201,1400);
INSERT INTO salgrade VALUES(3,1401,2000);
INSERT INTO salgrade VALUES(4,2001,3000);
INSERT INTO salgrade VALUES(5,3001,9999);

SELECT * FROM salgrade;

– 演示group by + having
having子句用于限制分组显示结果

– 如何显示每个部门的平均工资和最高工资
avg(sa1) max(sa1)
按照部门来分组查询

SELECT AVG(sa1),MAX(sa1),deptno 
	FROM emp GROUP BY deptno;

– 显示每个部门的每种岗位的平均工资和最低工资
avg(sa1) min(sa1)
按照部门来分组查询

SELECT AVG(sa1),MIN(sa1),deptno,job
	FROM emp GROUP BY deptno,job;

– 显示平均工资低于2000的部门号和它的平均工资
化繁为简,各个击破
– 1.显示各个部门的平均工资和部门号
– 2.在1的结果基础上,进行过滤,保留平均工资小于2000的

SELECT AVG(sa1),deptno 
		FROM emp GROUP BY deptno
		HAVING AVG(sa1)<2000;

使用别名

SELECT AVG(sa1) AS avg_sal,deptno 
		FROM emp GROUP BY deptno
		HAVING avg_sal<2000;

字符串函数

#字符串函数使用演示 使用emp表来演示
CHARSET(str) 返回字符串字符集

SELECT CHARSET(ename) FROM emp;

CONCAT (string2 […..]) 连接字符串,将多个列拼接成一列

SELECT CONCAT(ename,' job is ',job) FROM emp;

INSTR (string,substring) 返回substring在string中出现的位置,没有返回0
dual亚元表,系统表 可以作为测试表使用

SELECT INSTR('libai','li') FROM DUAL;

UCASE (string2) 转换为大写

SELECT UCASE(ename) FROM emp;

LCASE (string2) 转换为小写

SELECT LCASE(ename) FROM emp;

LEFT (string2,length) 从string2中的左边起取length个字符

SELECT LEFT(ename,2) FROM emp;

RIGHT (string2,length) 从string2中的右边起取length个字符

SELECT RIGHT(ename,2) FROM emp;

LENGTH (string) string长度[按照字节返回] 比如’李白’会返回6(utf8字符集)

SELECT LENGTH(ename) FROM emp;

REPLACE (str,search_str,replace_str)
在str中用replace_str替换search_str
– 如果是manager就替换成经理

SELECT ename ,REPLACE(job,'MANAGER','经理') FROM emp;

STRCMP (string1,string2) 逐字符比较两字符串大小

SELECT STRCMP('hsp','jsp') FROM DUAL;

SUBSTRING (str,position,[length])
从str的position开始【从1开始计算】,取length个字符

SELECT SUBSTRING(ename ,1,2) FROM emp;

LTRIM (string2) RTRIM (string2) 去除前端空格或者后端空格
TRIM(string) 去除前后端空格

SELECT LTRIM('      李白是诗人') FROM DUAL;
SELECT LTRIM('李白是诗人      ') FROM DUAL;
SELECT LTRIM('      李白是诗人       ') FROM DUAL;

以首字母小写的方式显示所有员工的姓名
– 方式1

SELECT CONCAT( LCASE(SUBSTRING(ename,1,1)) ,SUBSTRING(ename,2))
	FROM emp;

– 方式2

SELECT REPLACE(ename,SUBSTRING(ename,1,1),LCASE(SUBSTRING(ename,1,1)))
	FROM emp;

– 方式3

SELECT CONCAT( LCASE(LEFT(ename,1)) ,SUBSTRING(ename,2))
	FROM emp;

数学函数

#演示数学相关函数

ABS (num) 绝对值

SELECT ABS(-10) FROM DUAL;

BIN (decimal_number) 十进制转二进制

SELECT BIN(10) FROM DUAL;

CEILING (num2) 向上取整,得到比num2大的最小整数

SELECT CEILING(-1.1) FROM DUAL;

CONV(num2,from_base,to_base) 进制转换
– 下面的含义是 8是十进制的8,转成二进制输出

SELECT CONV(8,10,2) FROM DUAL;

– 下面的含义是 8是十六进制的8,转成二进制输出

SELECT CONV(8,16,2) FROM DUAL;

FLOOR (num2) 向下取整,得到比num2小的最大整数

SELECT FLOOR(-1.1) FROM DUAL;

FORMAT (num,decimal_places) 保留小数位数(四舍五入)

SELECT FORMAT(78.1254582,2) FROM DUAL;

HEX (DecimalNumber) 转十六进制

LEAST (num,num2,…) 求最小值

SELECT LEAST(0,1,-10,4) FROM DUAL;

MOD (numerator,denominator) 求余

SELECT MOD(10,3) FROM DUAL;

RAND ([seed]) RAND([seed]) 返回随机数 其范围为0<=v<=1.0
– 1.如果使用RAND()每次返回不同的随机数,在0<=v<=1.0之间
– 2.如果使用RAND(seed) 返回随机数,范围0<=v<=1.0如果seed不变,该随机数也不变了

SELECT RAND(6) FROM DUAL;

日期函数

#日期时间相关函数

CURRENT_DATE() 当前日期

SELECT CURRENT_DATE() FROM DUAL;

CURRENT_TIME() 当前时间

SELECT CURRENT_TIME() FROM DUAL;

CURRENT_TIMESTAMP() 当前时间戳

SELECT CURRENT_TIMESTAMP() FROM DUAL;

– 创建测试表 信息表

CREATE TABLE mes(
	id INT,
	content VARCHAR(32),
	send_time DATETIME);

– 添加一条记录

INSERT INTO mes VALUES(1,'北京新闻',CURRENT_TIMESTAMP());
INSERT INTO mes VALUES(2,'上海新闻',NOW());
INSERT INTO mes VALUES(3,'广州新闻',NOW());
SELECT * FROM mes;
SELECT NOW() FROM DUAL;

– 应用实例
显示所有新闻信息,发布日期只显示日期,不显示时间

SELECT id,content,DATE(send_time) FROM mes;

– 请查询在10分钟内发布的新闻

SELECT * FROM mes WHERE DATE_ADD(send_time,INTERVAL 10 MINUTE)>=NOW();
SELECT * FROM mes WHERE send_time>= DATE_SUB(NOW(),INTERVAL 10 MINUTE);

– 请在mysql的sql语句中求出2011-11-11和1990-1-1相差多少天

SELECT DATEDIFF('2011-11-11','1990-01-01') FROM DUAL;

– 请用mysql的sql语句求出你活了多少天?【练习】 2003-09-11 出生

SELECT DATEDIFF(NOW(),'2003-09-11') FROM DUAL;

– 如果你能活80岁,求出你还能活多少天? 【练习】 2003-09-11 出生
– 先求出活80岁时,是什么日期
– 然后在使用datediff(x,now());
– INTERVAL 80 YEAR:YEAR可以是替换成年月日,时分秒

SELECT DATEDIFF(DATE_ADD('2003-09-11',INTERVAL 80 YEAR),NOW()) FROM DUAL;

YEAR|MONTH|DAY| DATE (datetimee):(即返回年|月|日)

SELECT YEAR(NOW()) FROM DUAL;
SELECT MONTH(NOW()) FROM DUAL; 
SELECT DAY(NOW()) FROM DUAL;
SELECT MONTH('2003-11-10') FROM DUAL;

unix_timestamp():返回的是1970-01-01 到现在的秒数

SELECT UNIX_TIMESTAMP() FROM DUAL;

FROM_UNIXTIME():可以把一个unix_timestamp秒数,转成指定格式的日期

SELECT FROM_UNIXTIME(1669349758,'%Y-%m-%d') FROM DUAL;
SELECT FROM_UNIXTIME(1669349758,'%Y-%m-%d %H:%i:%s') FROM DUAL;

加密函数

#演示加密函数和系统函数
USER() 查询用户
– 可以查看登录到mysql的有哪些用户,以及登录的IP

SELECT USER() FROM DUAL; -- 用户@IP地址

DATABASE() 查询当前使用数据库名称

SELECT DATABASE();

MD5(str) 为字符串算出一个MD5 32位的字符串,常用(用户密码)加密
root 密码是lby->加密md5->在数据库中存放的是加密后的密码

SELECT MD5('lby') FROM DUAL;
SELECT LENGTH(MD5('lby')) FROM DUAL;

– 演示用户表,存放密码时,是md5

CREATE TABLE lby_user
	(id INT,
	`name` VARCHAR(32) NOT NULL DEFAULT ' ',
	pwd CHAR(32) NOT NULL DEFAULT ' ');
INSERT INTO lby_user
	VALUES(100,'李博扬',MD5('lby'));
SELECT * FROM lby_user;
SELECT * 
	FROM lby_user
	WHERE `name`='李博扬' AND pwd=MD5('lby');

PASSWORD(str) –加密函数,在MYSQL数据库的用户密码就是PASSWORD加密的

SELECT PASSWORD('lby') FROM DUAL;-- *2DE7B6C45E31629453E39499BDA8A5950CA05900

image-20221202152805385

select * from mysql.user \G 从原文密码str计算并返回密码字符串
通常用于对mysql数据库的用户密码加密
mysql.user 表示数据库.表

SELECT * FROM mysql.user;

流程控制函数

#演示流程控制语句
IF(expr1,expr2,expr3) 如果expr1为True,则返回expr2,否则返回expr3

SELECT IF(TRUE,'李白','杜甫') FROM DUAL;

IFNULL(expr1,expr2) 如果expr1不为NULL,则返回expr1,否则返回expr2

SELECT IFNULL(NULL,'李白') FROM DUAL;

SELECT CASE WHEN expr1 THEN expr2 WHEN expr3 THEN expr4 ELSE expr5 END;[类似多重分支]
如果expr1为TRUE,则返回expr2,如果expr3为TRUE,返回expr4,否则返回expr5

SELECT CASE
	WHEN TRUE THEN 'jack' -- jack
	WHEN FALSE THEN 'tom'
	ELSE 'mary' END

– 1.查询emp表,如果comm是null,则显示0.0
– 判断是否为null,要使用is null,判断不为空,使用is not null

SELECT ename,IF(comm IS NULL,0.0,comm) FROM emp;
SELECT ename,IFNULL(comm,0.0) FROM emp;

– 2.如果emp表的job是CLERK则显示职员,如果是MANAGER则显示经理
– 如果是SALESMAN则显示销售人员其它正常显示

SELECT ename,(SELECT CASE
		WHEN job='clerk' THEN '职员'
		WHEN job='manager' THEN '经理'
		WHEN job='salesman' THEN '销售人员'
		ELSE  job END) job
	FROM emp;

查询增强

#查询加强
– 使用where子句
– 如何查找1992.1.1后入职的员工
– 在mysql中,日期类型可以直接比较,需要注意格式

SELECT * FROM emp
	WHERE hiredate > '1992-1-1';

– 如何使用like操作符
%表示0到多个字符 _表示单个字符
– 如何显示首字符为S的员工姓名和工资

SELECT ename,sa1
	FROM emp
	WHERE ename LIKE 'S%';

– 如何显示第三个字符为大写O的所有员工的姓名和工资

SELECT ename,sa1 FROM emp
	WHERE ename LIKE '__0%';

– 如何显示没有上级的雇员的情况

SELECT * FROM emp
	WHERE mgr IS NULL;

– 查询表结构

DESC emp;

– 使用order by子句
– 如何按照工资从低到高的顺序[升序],显示雇员的信息

SELECT * FROM emp
	ORDER BY sa1;

– 按照部门号升序而雇员的工资降序排列,显示雇员信息

SELECT * FROM emp
	ORDER BY deptno ASC,sa1 DESC;

分页查询

#分页查询
按雇员的id号升序取出每页显示3条记录,请分别显示第1页,第2页,第2页
– 第1页

SELECT * FROM emp
	ORDER BY empno
	LIMIT 0,3;

– 第2页

SELECT * FROM emp
	ORDER BY empno
	LIMIT 3,3;

– 第3页

SELECT * FROM emp
	ORDER BY empno
	LIMIT 6,3;

– 推导一个公式

SELECT * FROM emp
	ORDER BY empno

LIMIT 每页显示记录数 * (第几页—1),每页显示记录数
– 练习

SELECT * FROM emp
	ORDER BY empno DESC
	LIMIT 20,5;

分组增强

#增强group by的使用

SELECT * FROM emp;

– 1.显示每种岗位的雇员总数,平均工资

SELECT COUNT(*),job,AVG(sa1) FROM emp
	GROUP BY job;

– 2.显示雇员总数,以及获得补助的雇员数
– 思路:获得补助的雇员数就是comm列为非null,就是count(),如果该列的值为null,是不会统计的

SELECT COUNT(*),COUNT(comm) 
	FROM emp;

– 扩展要求 统计没有获得补助的雇员数

SELECT COUNT(*),COUNT(IF(comm IS NULL,1,NULL))
	FROM emp;
SELECT COUNT(*),COUNT(*)-COUNT(comm)
	FROM emp;

– 3.显示管理者的总人数

SELECT COUNT(DISTINCT mgr)
	FROM emp;

– 4.显示雇员工资的最大差额

SELECT MAX(sa1)-MIN(sa1)
	FROM emp;

多表查询

笛卡儿集

#多表查询
– 显示雇员名,雇员工资及所在部门的名字[笛卡儿集]
/*
分析
1.雇员名,雇员工资来自emp表
2.部门的名字来自dept表
3.需求对emp和dept查询
*/

SELECT * FROM emp,dept;

– 在默认情况下,当两个表查询时,规则为
– 1.从第一张表中,取出一行第二张表的每一行进行组合
– 2.返回结果,一共返回的记录数第一张表的行数*第二张表的行数
– 3.这样多表查询默认处理返回的结果,称为笛卡尔表
– 4.解决这个多表的关键就是要写出正确的过滤条件where,需求程序员进行分析
– 5.当我们需要指定显示某个表的列是,需要 表.列

SELECT ename,sa1,dname FROM emp,dept
	WHERE emp.deptno=dept.deptno;
SELECT ename,sa1,emp.deptno FROM emp,dept
	WHERE emp.deptno=dept.deptno;

#注意事项:多表查询的条件不能少于表的个数-1,否则会出现笛卡儿集
– 如何显示部门号为10的部门名,员工名和工资

SELECT ename,sa1,dname,emp.deptno
	from emp,dept
	where emp.deptno=dept.deptno and emp.deptno=10;

– 显示各个员工的姓名,工资,及其工资的级别
– 思路:姓名,工资来自emp
– 工资级别来自salgrade

select ename,sa1,grade
	from emp,salgrade
	where sa1 between losal and hisal ;

自连接

#多表查询的自连接
– 思考:显示公司员工名字和他的上级的名字
– 分析:员工名字在emp,上级的名字在emp
– 员工与上级是通过emp表的mgr列关联

SELECT worker.ename,boss.ename
	FROM emp worker,emp boss
	WHERE worker.mgr=boss.empno;

自连接的特点
– 1.把同一张表当作两张表来使用
– 2.需要给表取别名
– 格式:表名 表别名
– 3.列名不明确,可以指定列的别名

多行子查询

#子查询的演示
– 请思考:如何显示与SMITH同一部门的所有员工?
/*
1.先查询到SMITH的部门号
2.把上面的select语句当作一个子查询来使用
*/

SELECT deptno
	FROM emp
	WHERE ename='SMITH'

单行子查询

SELECT *
	FROM emp
	WHERE deptno=(
		SELECT deptno
		FROM emp
		WHERE ename='SMITH'
		)

– 如何查询和部门号为10的工作相同的雇员的名字,岗位,工资,部门号。
– 但是不包含部门号为10的雇员
/*
1.先查询到10号部门有哪些工作
2.把上面查询的结果当作子查询使用
*/

SELECT DISTINCT job
	FROM emp
	WHERE deptno=10;
SELECT ename,job,sa1,deptno
	FROM emp
	WHERE job IN(
		SELECT DISTINCT job
		FROM emp
		WHERE deptno=10
		) AND deptno!=10;

多列子查询

#多列子查询
– 请思考如何查询与smith的部门和岗位完全相同的所有雇员(并且不包含smith本人)
(字段1,字段2…..) = (select 字段1,字段2 from……)

– 分析:
– 1.得到smith的部门号和岗位

SELECT deptno,job
	FROM emp
	WHERE ename='SMITH';

– 2.把上面查询结果当作子查询来使用,并且使用多列子查询的语法进行匹配

SELECT*
	FROM emp
	WHERE(deptno,job)=(
			SELECT deptno,job
			FROM emp
			WHERE ename='allen'
		) AND ename<>'allen';

<>表示不等于

#子查询练习
– 查找每个部门工资高于本部门平均工资的人的资料

SELECT *
	FROM emp,(
		SELECT deptno,AVG(sa1) avg_sa1
		FROM emp
		GROUP BY deptno
	)temp
	WHERE emp.deptno=temp.deptno AND emp.sa1>temp.avg_sa1

– 查找每个部门工资最高的人的详细资料

SELECT *
	FROM emp,(
		SELECT deptno,MAX(sa1) max_sa1
		FROM emp
		GROUP BY deptno
	)temp
	WHERE emp.deptno=temp.deptno AND emp.sa1=temp.max_sa1

– 查询每个部门的信息(包括:部门号,编号,地址)和人员数量
– 分析:
– 1.部门名,编号,地址来自dept表
– 2.各个部门的人员数量-》构建一个临时表

SELECT COUNT(*),deptno
	FROM emp
	GROUP BY deptno;	
SELECT dname,dept.deptno,1oc ,per_num
	FROM dept,(
		SELECT COUNT(*) per_num,deptno
		FROM emp
		GROUP BY deptno
	)temp
	WHERE temp.deptno=dept.deptno

– 还有一种写法,表.*表示将该表所有列都显示出来,可以简化sql语句
在多表查询中,当多个表的列不重复时,才可以直接写列名

SELECT temp.*,dname,1oc
	FROM dept,(
		SELECT COUNT(*) per_num,deptno
		FROM emp
		GROUP BY deptno
	)temp
	WHERE temp.deptno=dept.deptno

表复制和去重

#演示表的复制
– 为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据

CREATE TABLE my_tb01
	(id INT,
	`name` VARCHAR(32),
	sal DOUBLE,
	job VARCHAR(32),
	deptno INT);

– 演示如何自我复制
– 1.先把emp表的记录复制到my_tb01

INSERT INTO my_tb01
	(id,`name`,sal,job,deptno)
	SELECT empno,ename,sa1,job,deptno FROM emp;

– 2.自我复制

INSERT INTO my_tb01
	SELECT * FROM my_tb01;

– 如何删除掉一张表重复记录
– 1.先创建一张表my_tb02
– 2.让my_tb02有重复的记录

CREATE TABLE my_tb02 LIKE emp;

把emp表的结构(列),复制到my_tb02

INSERT INTO my_tb02
	SELECT * FROM emp;

– 3.考虑去重
– 分析
/*
1.先创建一张临时表my_tb,该表的结构与my_tb02一致
2.把my_tb02的记录通过distinct关键字处理后,把记录复制到my_tb
3.清除掉my_tb02记录
4.把my_tb表的记录复制到my_tb02
5.drop掉临时表my_tb
*/

CREATE TABLE my_tb LIKE my_tb02;

INSERT INTO my_tb
	SELECT DISTINCT * FROM my_tb02;

DELETE FROM my_tb02;

INSERT INTO my_tb02
	SELECT * FROM my_tb;
	
DROP TABLE my_tb;

合并查询

#演示合并查询

SELECT ename,sa1,job FROM emp WHERE sa1>2500;

SELECT ename,sa1,job FROM emp WHERE job='manager'

union all 就是将两个查询结果合并,不会去重

SELECT ename,sa1,job FROM emp WHERE sa1>2500
UNION ALL
SELECT ename,sa1,job FROM emp WHERE job='manager'

union 该操作赋与 union all相似,但是会自动去掉结果中重复的记录

SELECT ename,sa1,job FROM emp WHERE sa1>2500
UNION
SELECT ename,sa1,job FROM emp WHERE job='manager'

左外连接与右外连接

#演示外连接

– 比如:列出部门名称和这些部门的员工名称和工作,同时要求显示出那些没有员工的部门

– 使用我们学习过的多表查询的sql,看看效果如何

SELECT dname,ename,job
	FROM emp,dept
	WHERE emp.deptno=dept.deptno
	ORDER BY dname;

#外连接
– 1,左外连接 (如果左侧的表完全显示我们就说是左外连接)
– 1,右外连接 (如果右侧的表完全显示我们就说是右外连接)

– 创建stu

CREATE TABLE stu (
	id INT,
	`name` VARCHAR(32));
INSERT INTO stu VALUES(1,'jack'),(2,'tom'),(3,'kity'),(4,'noo');

– 创建表exam

CREATE TABLE exam (
	id INT,
	grade INT);
INSERT INTO exam VALUES(1,56),(2,76),(11,8);

– 使用左连接(显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)
/*
格式:select…from 表1 left join 表2 on 条件
*/

SELECT `name`,stu.id,grade
	FROM stu,exam
	WHERE stu.id=exam.id

– 改成左连接

SELECT `name`,stu.id ,grade
	FROM stu LEFT JOIN exam
	ON stu.id=exam.id

右外连接(显示所有成绩,如果没有名字匹配,显示空)

SELECT `name`,grade,exam.id
	FROM stu RIGHT JOIN exam
	ON stu.id=exam.id
SELECT dept.deptno,`ename`,job
	FROM emp RIGHT JOIN dept
	ON emp.deptno=dept.deptno
SELECT dept.deptno,`ename`,job
	FROM dept LEFT JOIN emp
	ON emp.deptno=dept.deptno

MySql约束

主键

#演示主键使用
– id name email

CREATE TABLE t17 (
	id INT PRIMARY KEY, -- 表示id列是主键
	`name` VARCHAR(32),
	email VARCHAR(32));

主键列的值是不可以重复的

INSERT INTO t17
	VALUES(1,'jack','jack@sohu.com'),(2,'tom','tom@sohu.com');
INSERT INTO t17 VALUES(1,'lvy','lvy@sohu.com'); 添加失败,主键重复

主键使用细节
primary key不能重复而且不能为null

INSERT INTO t17 VALUES(NULL,'gsp','gsp@sohu.com'); -- Column 'id' cannot be null

一张表最多只能有一个主键,但可以是复合主键

CREATE TABLE t18 (
	id INT PRIMARY KEY, 
	`name` VARCHAR(32) PRIMARY KEY,
	email VARCHAR(32)); -- Multiple primary key defined

演示复合主键使用(id和name做成复合主键,即id和name做为一个复合主键,而不是id是主键1,name是主键2)

CREATE TABLE t18 (
	id INT , 
	`name` VARCHAR(32),
	email VARCHAR(32),
	PRIMARY KEY(id,`name`));

INSERT INTO t18 VALUES(1,'gsp','gsp@sohu.com');
INSERT INTO t18 VALUES(1,'dsa','dsa@sohu.com');
INSERT INTO t18 VALUES(2,'dsa','dsa@sohu.com');
INSERT INTO t18 VALUES(1,'gsp','gsp@sohu.com'); -- Duplicate entry '1-gsp' for key 'PRIMARY'

– 主键的指定方式有两种
– 1.直接在字段名后指定:字段名 primary key
– 2.在表定义最后写 primary key(列名);
– 参考上面创建表的方式
– 使用desc表名,可以看到primary key的情况

DESC t18;
DESC t17;

实际开发中,每个表往往都会设计一个主键

unique

#演示unique使用

CREATE TABLE t19 (
	id INT UNIQUE,-- 表示id列是不可重复的,但可为null
	`name` VARCHAR(32),
	email VARCHAR(32));
	
INSERT INTO t19 VALUES(1,'jack','jack@sohu.com');-- Duplicate entry '1' for key 'id'
INSERT INTO t19 VALUES(1,'tom','tom@sohu.com');

unique使用细节
如果没有指定not null,则unique字段可以有多个null
如果一个列(字段)是unique not null,那么使用效果类似primary key

INSERT INTO t19 VALUES(NULL,'jack','jack@sohu.com');
SELECT * FROM t19;

一张表可以有多个unique字段

CREATE TABLE t20 (
	id INT UNIQUE,
	`name` VARCHAR(32) UNIQUE,
	email VARCHAR(32));

外键

#外键演示
– 创建主表 my_class

CREATE TABLE my_class (
	id INT PRIMARY KEY, -- 班级编号
	`name` VARCHAR(32) NOT NULL DEFAULT '');

– 创建从表 my_stu

CREATE TABLE my_stu (
	id INT PRIMARY KEY, -- 学生编号
	`name` VARCHAR(32) NOT NULL DEFAULT '',
	class_id INT, -- 学生所在班级的编号

– 下面指定外键关系

FOREIGN KEY(class_id) REFERENCES my_class(id));

– 测试数据

INSERT INTO my_class VALUES(100,'java'),(200,'web');
SELECT * FROM my_class;
INSERT INTO my_stu VALUES(1,'tom',100);
INSERT INTO my_stu VALUES(2,'jack',200);
INSERT INTO my_stu VALUES(3,'mary',300); -- 失败,因为300号班级不存在
INSERT INTO my_stu VALUES(4,'king',NULL); -- 可以,外键没有写not null

外键细节
– 1.外键指向的表的字段,要求是primary key或者是unique
– 2.表的存储引擎是innodb,这样的表才支持外键
– 3.外键字段的类型要和主键字段的类型一致(长度可以不同)
– 4.外键字段的值,必须在主键字段中出现过,或者为null(前提是外键字段允许为null)
– 5.一旦建立主外键的关系,数据不能随意删除了(需要先删除外键对应数据,才能删除主键对应数据)

check

#演示check使用
mysql5.7目前还不支持check,只做语法校验,但是不会生效
但在oracle,sql server这两个数据库中是真的生效

CREATE TABLE t21 (
	id INT PRIMARY KEY,
	`name` VARCHAR(32),
	sex VARCHAR(6) CHECK (sex IN('man','woman')),-- 即检查插入的记录是不是这两个字符串,如果是就成功,如果不是就插入失败
	sal DOUBLE CHECK (sal>1000 AND sal<2000));

添加数据

INSERT INTO t21 VALUES(1,'jack','mid',1)-- 添加失败(mid不在检查范围内并且sal小于1000)
SELECT * FROM t21;

自增长

#演示自增长的使用
– 创建表

CREATE TABLE t22 (
	id INT PRIMARY KEY AUTO_INCREMENT,
	email VARCHAR(32) NOT NULL DEFAULT '',
	`name` VARCHAR(32) NOT NULL DEFAULT '');
DESC t22;

– 测试自增长的使用

INSERT INTO t22 VALUES(NULL,'tom@sohu.com','tom');
INSERT INTO t22 (email,`name`) VALUES('lvy@sohu.com','lvy');
SELECT * FROM t22;

自增长使用细节
– 1.一般来说自增长是和primary key配合使用的
– 2.自增长也可以单独使用(但是需要配合一个unique)
– 3.自增长修饰的字段为整数型的(虽然小数也可以但是非常非常少这样使用)
– 4.自增长默认从1开始,你也可以通过如下命令修改
alter table 表名 auto_increment=xxx;

ALTER TABLE t22 AUTO_INCREMENT=10;
INSERT INTO t22 VALUES(NULL,'jack@sohu.com','jack');

– 5.如果你添加数据时,给自增长字段(列)指定的有值,则以指定的值为准
– 6.一般来说,如果指定了自增长,就按照自增长的规则来添加数据,不要自己指定数值
/* 同时自增长会从指定的值开始,
比如之前自增长到10,而你添加数据时,
指定了100给自增长字段,
那么自增长会从10直接跳到100重新开始自增长
*/

INSERT INTO t22 VALUES(100,'brck@sohu.com','brck');

MySql索引

索引优化速度及索引原理

索引的原理
没用索引为什么查询海量数据会?因为是全表扫描
使用索引为什么查询海量数据会?因为形成一个索引的数据结构,比如二叉树
使用索引的代价
– 1.磁盘占用空间变大
– 2.对dml(update,delete,insert)语句的执行效率产生影响,变慢

索引的类型

– 1.主键索引,主键自动的为主索引(类型Primary Key)
– 2.唯一索引(UNIQUE)
– 3.普通索引(INDEX)
– 4.全文索引(FULLTEXT)[适用于MylSAM]

mysql的索引的使用

创建索引

CREATE TABLE t23 (
	id INT,
	`name` VARCHAR(32));

查询表是否有索引

SHOW INDEXES FROM t23;

添加索引
– 添加唯一索引

CREATE UNIQUE INDEX id_index ON t23 (id);

– 添加普通索引方法1

CREATE INDEX id_index ON t23 (id);

– 添加普通索引方法2

ALTER TABLE t23 ADD INDEX id_index (id);

如何选择索引类型
如果某列的值,是不会重复的,则优先考虑使用unique索引,否则使用普通索引

添加主键索引

CREATE TABLE t24 (
	id INT,
	`name` VARCHAR(32));
ALTER TABLE t24 ADD PRIMARY KEY (id);
SHOW INDEX FROM t24;

删除索引

DROP INDEX id_index ON t23;

删除主键索引

ALTER TABLE t24 DROP PRIMARY KEY;

修改索引
先删除,在添加新的索引

查询索引
– 方式1
SHOW INDEX FROM t23;
– 方式2
SHOW INDEXES FROM t23;
– 方式3
SHOW KEYS FROM t23;
– 方式4
DESC t23

创建索引规则

哪些列适合使用索引
– 1.较频繁的作为查询条件字段应该创建索引
– 2.唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
– 3.更新非常频繁的字段不适合创建索引
– 4.不会出现在where子句中字段不该创建索引

MySql事务

什么是事务及事务操作?

事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败
– 演示mysql数据库控制台事务的几个重要操作
start transaction 开始一个事务
savepoint 设置保存点
rollback to 回退事务
rollback 回退全部事务
commit 提交事务,所有的操作生效,不能回退

– 1.创建一张表

CREATE TABLE t25 (
	id INT,
	`name` VARCHAR(32));

– 2.开始事务

START TRANSACTION

– 3.设置保存点

SAVEPOINT a

执行dml操作

INSERT INTO t25 VALUES(100,'tom');
SELECT * FROM t25;

– 4.设置保存点

SAVEPOINT b

执行dml操作

INSERT INTO t25 VALUES(200,'jack');

回退到b

ROLLBACK TO b

回退到a

ROLLBACK TO a

– 如果这样,表示直接回退到事务开始的状态

ROLLBACK

提交事务

COMMIT

事务注意细节

– 讨论 事务细节
– 1.如果不开始事务,在默认情况下,dml操作是自动提交的,不能回滚

INSERT INTO t25 VALUES(300,'mary');
SELECT * FROM t25;

– 2.如果开始一个事务,你没有创建保存点,你可以执行rollback
默认就是回退到事务开始的状态

START TRANSACTION
INSERT INTO t25 VALUES(400,'king');
INSERT INTO t25 VALUES(500,'scott');
ROLLBACK

– 3.你也可以在这个事务中(还没有提交时),创建多个保存点
– 4.你可以在事务没有提交前,选择回退到哪个保存点
– 5.InnoDB存储引擎支持事务,MyISAM不支持
– 6.开始一个事务 start transaction 或者 set autocommit=off;

MySql事务隔离级别

4种隔离级别

image-20221216153701612

image-20221216154020365

image-20221216154213855

设置隔离

#事务隔离级别介绍
– 1.多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作
– 以保证各个连接在获取数据时的准确性
– 2.如果不考虑隔离性,可能会引发如下问题:
– 脏读:当一个事务读取另一个事务尚未提交的修改时,产生脏读
– 不可重复读:同一查询在同一事务中多次进行,由于其他提交事务所做的
– 修改或删除,每次返回不同的结果集,此时发生不可重复读
– 幻读:同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作
– 每次返回不同的结果集,此时发生幻读

#演示mysql的事务隔离级别
– 1.开了两个mysql的控制台
– 2.查看当前mysql的隔离级别

SELECT @@tx_isolation;
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

– 3.把其中一个控制台的隔离级别设置 Read uncommitted

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

– 4.创建表

CREATE TABLE `account` (
	id INT,
	`name` VARCHAR(32),
	money INT);

查看当前会话隔离级别

SELECT @@tx_isolation;

查看系统当前隔离级别

SELECT @@global.tx_isolation;

设置当前会话隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

设置系统当前隔离级别

SET GLOBAL TRANSACTION ISOLATION LEVE

MySql表类型与存储引擎

表类型和存储引擎

image-20221216161340056

image-20221216161502993

image-20221216161558629

查看所有存储引擎

SHOW ENGINES

innodb 存储引擎
1.支持事务 2.支持外键 3.支持行级锁

myisam 存储引擎
1.添加数据快 2.不支持外键和事务 3.支持表级锁

CREATE TABLE t26 (
	id INT,
	`name` VARCHAR(32)) ENGINE MYISAM
START TRANSACTION
SAVEPOINT a
INSERT INTO t26 VALUES(1,'jack');
SELECT * FROM t26;
ROLLBACK TO a

memory 存储引擎
1.数据存储在内存中(关闭了MySql服务,数据丢失,但是表结构还在) 2.执行速度很快(没有IO读写) 3.默认支持索引(hash表)

CREATE TABLE t27 (
	id INT,
	`name` VARCHAR(32)) ENGINE MEMORY
INSERT INTO t27 VALUES(1,'jack'),(2,'tom'),(3,'mery');
SELECT * FROM t27;

指令修改存储引擎

ALTER TABLE `t27` ENGINE = INNODB;

如何选择表的存储引擎

image-20221216161721012

视图

视图原理

image-20221216162656363

image-20221216162602521

– 1.视图是根据基表(可以是多个基表)来创建的,视图是虚拟的表
– 2.视图也有列,数据来自基表
– 3.通过视图可以修改基表的数据
– 4.基表的改变,也会影响到视图的数据

视图的使用

– 创建一个视图emp_view01,只能查询emp表的(empno,ename,job和deptno)信息
创建视图

CREATE VIEW emp_view01
	AS
	SELECT empno,ename,job,deptno FROM emp;

查看视图

DESC emp_view01;
SELECT * FROM emp_view01;
SELECT empno,job FROM emp_view01;
SELECT sa1 FROM emp_view01; -- Unknown column 'sa1' in 'field list'

查看创建视图的指令

SHOW CREATE VIEW emp_view01;

删除视图

DROP VIEW emp_view01;

视图细节讨论
– 1.创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式:视图名.frm),不会有数据文件(视图名.ibd)
– 2.视图的数据变化会影响到基表,基表的数据变化也会影响到视图(insert,update,delete)
修改视图

UPDATE emp_view01
	SET job='MANAGER'
	WHERE empno=7369;
SELECT * FROM emp_view01; -- 查询视图
SELECT * FROM emp; -- 查询基表

修改基表,也会影响到视图

UPDATE emp
	SET job='SALESMAN'
	WHERE empno=7369;

– 3.视图中可以再使用视图,数据依然来自基表,比如从emp_view01这个视图中选出empno和ename做新视图

DESC emp_view01;

CREATE VIEW emp_view02
	AS
	SELECT empno,ename FROM emp_view01;
SELECT * FROM emp_view02;

视图练习
– 针对emp,dept和salgrade三张表,创建一个视图emp_view03
– 可以显示雇员编号,雇员名,雇员部门名称和薪水级别[即使用三张表,创建一个视图]
/*
分析:使用三表联合查询,得到结果
将得到的结果,构建成视图
*/

CREATE VIEW emp_view03
	AS
SELECT empno,ename,dname,grade
	FROM emp,dept,salgrade
	WHERE emp.deptno=dept.deptno AND 
	(sa1 BETWEEN losal AND hisal)
SELECT * FROM emp_view03

MySql管理

MySql用户管理

– MySql用户的管理
– 原因:当我们做项目开发时,可以根据不同的开发人员,赋给他相应的MySql操作权限
– 所以,MySql数据库管理人员(root),根据需要创建不同的用户,赋给相应的权限,供人员使用

– 1.创建新的用户
– 解读(1) ‘lby‘@’localhost’表示用户的完整信息,’lby’用户名,’localhost’登录的IP
– (2) 123456表示密码,但是注意,存放到mysql.user表时,是password(‘123456’)加密后的密码

CREATE USER 'lby'@'localhost' IDENTIFIED BY '123456'

– 2.删除用户

DROP USER 'lby'@'localhost'

– 3.修改自己的密码

SET PASSWORD=PASSWORD('abcdef')

– 4.修改其他人的密码,需要权限(root用户权限高,可以修改其他用户密码)

SET PASSWORD FOR 'lby'@'localhost'=PASSWORD('123456')

image-20221216163836385

MySql权限管理

image-20221216163721504

image-20221216163951055

演示用户权限的管理
– 1.创建用户 libai 密码 123,从本地登录

CREATE USER 'libai'@'localhost' IDENTIFIED BY '123'

使用root用户创建testdb,表news

CREATE DATABASE testdb
CREATE TABLE news (
	id INT,
	content VARCHAR(32));

添加一条测试数据

INSERT INTO news VALUES(100,'广州新闻')
SELECT * FROM news

给libai分配查看news表和添加news的权限

GRANT SELECT,INSERT
	ON testdb.news
	TO 'libai'@'localhost'

给libai增加权限

GRANT UPDATE
	ON testdb.news
	TO 'libai'@'localhost'

修改libai的密码为abc

SET PASSWORD FOR 'libai'@'localhost'=PASSWORD('abc')

回收libai用户在testdb.news表的所有权限

REVOKE SELECT,UPDATE,INSERT ON testdb.news FROM 'libai'@'localhost'
REVOKE ALL ON testdb.news FROM 'libai'@'localhost'

如果权限没有生效,可以执行下面的指令

FLUSH PRIVILEGES

MySql用户管理细节

#说明用户管理的细节
– 在创建用户的时候,如果不指定Host,则为%,%表示所有IP都有连接权限
create user xxx;

CREATE USER jack
SELECT `host`,`user` FROM mysql.user

– 你也可以这样子指定
– *create user ‘xxx‘@’192.168.1.%’表示xxx用户在192.168.1.的ip可以登录mysql

CREATE USER 'smith'@'192.168.1.%'

在删除用户时,如果host不是%,需要明确指定’用户‘@’host值’

DROP USER jack -- 默认就是drop user 'jack'@'%'
DROP USER 'smith'@'192.168.1.%'
Other Articles
cover
Java-3
  • 22/11/26
  • 13:00