零基础学MySQL

1. 零基础学MySQL

1.1 数据库简介

1.1.1 数据库三层结构

1. 所谓安装Mysql数据库,就是在主机安装一个数据库管理系统(DBMS),这个管理程序可以管理多个数据库。DBMS(database manage system)
2. 一个数据库中可以创建多个表,以保存数据(信息)。
3. 数据库管理系统(DBMS)、数据库和表的关系 如图所示:

1.1.2  数据在数据库中的存储方式

1.2 SQL语句分类

DDL: 数据定义语句 [create表,库...]
DML: 数据操作语句 [增加insert,修改update,删除delete]
DQL: 数据查询语句[select ]
DCL: 数据控制语句[管理数据库: 比如用户权限grant revoke ]

1.3 创建数据库

        1. CHARACTER SET:指定数据库采用的字符集,如果不指定字符集,默认utf8
        2. COLLATE:指定数据库字符集的校对规则(常用的utf8 bin[区分大小引]、utf8 _general_ci[不区分大小引]注意默认是utf8_general_ci)

案例练习:
1. 创建一个名称为zak_db01的数据库。
2. 创建一个使用utf8字符集的zak db02数据库
3. 创建一个使用utf8字符集,并带校对规则的zak db03数据库

#演示数据库的操作
#创建一个名称为zak_db01的数据库。#使用指令创建数据库CREATE DATABASE zak_db01;#删除数据库指令DROP DATABASE zak_db01#创建一个使用utf8字符集的hsp_db02数据库CREATE DATABASE zak_db02 CHARACTER SET utf8#创建一个使用utf8字符集,并带校对规则的hsp_db03数据库CREATE DATABASE zak_db03 CHARACTER SET utf8COLLATEutf8_bin#校对规则utf8_bin区分大小默认utf8_general_ci不区分大小写#下面是一条查询的sql,select查询*表示所有字段FROM从哪个
#WHERE从哪个字段NAME='tom'查询名字是tomSELECT *FROM t1WHERE NAME = 'tom'

1.4  查看、删除数据库

#显示数据库语句:SHOW DATABASES
#显示数据库创建语句:SHOW CREATE DATABASE db_name
#数据库删除语句[一定要慎用]:DROP DATABASE [IF EXISTS] db_name

案例练习:
1. 查看当前数据库服务器中的所有数据库
2. 查看前面创建的zak_db01数据库的定义信息
3. 删除前面创建的zak_db01数据库

#演示删除和查询数据库
#查看当前数据库服务器中的所有数据库SHOW DATABASES#查看前面创建的zak_db01数据库的定义信息SHOW CREATE DATABASE `zak_db01`#说明在创建数据库,表的时候,为了规避关键字,可以使用反引号解决
#删除前面创建的zak_db01数据库DROP DATABASE zak_db01

1.5 备份恢复数据库

备份数据库(注意:在DOS执行)命令行
        mysqldump -u用户名 -p -B 数据库1 数据库2 数据库n >文件名.sqI
恢复数据库(注意: 进入Mysql命令行再执行)
        Source文件名.sql
案例练习: database03.sql 备份 zak_db02 和 zak_db03库中的数据,并恢复

#备份, 要在Dos下执行mysqldump指令其实在mysql安装目录\bin#这个备份的文件,就是对应的sql语句mysqldump -u root -p -B zak_db02 zak_db03 > d:\\bak.sqlDROP DATABASE ecshop;#恢复数据库(注意:进入Mysql命令行再执行)source d:\\bak.sql#第二个恢复方法, 直接将 bak.sql 的内容放到查询编辑器中,执行

1.6 备份恢复数据库的表

#备份库的表
mysqldump -u 用户名 -p密码 数据库 表1 表2 表n > d:\\文件名.sql

1.7 安装 Ecshop 数据库

案例练习:

#这是一个ecshop 的数据库,包括 ecshop 所有的表,请导入到mysql数据库中[备份]#进入到mysql命令行:sourceecshop 备份文件路径
#再将ecshop 整个数据库备份到你的 d:\\ecshop.sql到dos 下 :mysqldump -u root -p -B ecshop > d:\\ecshop.sql
#将mysql 的ecshop 数据库删除, 并通过备份的d:\\ecshop.sql恢复
#进入mysql命令行source d:\\ecshop.sql

1.8 创建表(按课程大纲顺序)

案例:

 #指令创建表
#注意:zak_db02 创建表时,要根据需保存的数据创建相应的列,并根据数据的类型定义相应的列类型。例:user表#id         整形#name       字符串  #password   字符串#birthday   日期
CREATE TABLE `user` (id INT,`name` VARCHAR(255),`password` VARCHAR(255),`birthday` DATE)CHARACTER SET utf8 COLLATE utf8_bin ENGINE INNODB

1.9 Mysql 常用数据类型(列类型)

1.9.1 数值型(整数)的基本使用

1. 说明:使用规范: 在能够满足需求的情况下,尽量选择占用空间小的

案例:

#演示整型的是一个
#使用 tinyint 来演示范围 有符号 -128~127 如果没有符号 0-255#说明:表的字符集,校验规则,存储引擎,使用默认
#1. 如果没有指定 unsinged, 则 TINYINT 就是有符号
#2. 如果指定 unsinged, 则 TINYINT 就是无符号 0-255CREATE TABLE t3(id TINYINT);CREATE TABLE t4(id TINYINT UNSIGNED);INSERT INTO t3 VALUES(127); #这是非常简单的添加语句SELECT * FROM t3INSERT INTO t4 VALUES(255);SELECT * FROM t4;

1.9.2 如何定义一个无符号的整数

create table t10 (id tinyint ); #默认是有符号的
create table t11 (id tinyint unsigned ); #无符号的

1.9.3 数值型(bit)的使用

1. 基本使用
        mysql> create table t05 (num bit(8));
        mysql>insert into t05 (1,3);
        mysql> insert into t05 values(2,65);

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

1.9.4 数值型(小数)的基本使用

1. FLOAT/DOUBLE  [UNSIGNED]      Float单精度精度,Double双精度.
2. DECIMAL [M,D] [UNSIGNED]
        可以支持更加精确的小数位。M是小数位数(精度)的总数,D是小数点(标度)后面的位数。
        如果D是0,则值没有小数点或分数部分。M最大65。D最大是30。如果D被省略,默认是0。如果M被省略,默认是10。
        建议: 如果希望小数的精度高,推荐使用decimal
案例:

#演示decimal类型、float、double使用
#创建表CREATE TABLE t06 (num1 FLOAT,num2 DOUBLE,num3 DECIMAL(30,20));
#添加数据INSERT INTO t06 VALUES (88.12345678912345,88.12345678912345,88.12345678912345);SELECT * FROM t06;
#decimal可以存放很大的数CREATE TABLE t07 (num DECIMAL(65));INSERT INTO t07 VALUES (8999999933338388388383838838383009338388383838383838383);SELECT * FROM t07;CREATE TABLE t08 (num BIGINT UNSIGNED)INSERT INTO t08 VALUES(8999999933338388388383838838383009338388383838383838383);SELECT * FROM t08;

1.9.5 字符串的基本使用

#演示字符串类型使用char varchar
--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=32766CREATE TABLE t09 (`name` CHAR(255));
CREATE TABLE t10 (`name` VARCHAR(32766)) CHARSET gbk;DROP TABLE t10;

1.9.6 字符串使用细节

1. 细节1
  char(4) //这个4表示字符数(最大255),不是字节数,不管是中文还是字母都是放四个,按字符计算.
  varchar(4) //这个4表示字符数,不管是字母还是中文都以定义好的表的编码来存放数据
  不管是中文还是英文字母,都是最多存放4个,是按照字符来存放的.
2. 细节2
  char(4)是定长(固定的大小),就是说,即使你插入'aa',也会占用分配的4个字符的空间.
  varchar(4)是变长(变化的大小),就是说,如果你插入了'aa',实际占用空间大小并不是4个字符,而是按照实际占用空间来分配(说明: varchar本身还需要占用1-3个字节来记录存放内容长度)
        L(实际数据大小) + (1-3)字节
3. 细节3
        什么时候使用char,什么时候使用varchar
        1. 如果数据是定长,推荐使用char, 比如md5的密码,邮编,手机号,身份证号码等. char(32)
        2. 如果一个字段的长度是不确定,我们使用varchar,比如留言,文章
查询速度: char > varchar
4. 细节4
        在存放文本时,也可以使用Text 数据类型.可以将TEXT列视为VARCHAR列,注意Text不能有默认值.大小 0-2^16 字节
        如果希望存放更多字符,可以选择 MEDIUMTEXT 0 - 2^24 或者 LONGTEXT 0 ~ 2^32

#演示字符串类型的使用细节
#char(4)和varchar(4)这个4表示的是字符,而不是字节,不区分字符是汉字还是字母
CREATE TABLE t11(`name`CHAR(4));INSERT INTO t11 VALUES('zak');SELECT * FROM t11;CREATE TABLE t12(`name` VARCHAR(4));INSERT INTO t12 VALUES('zak');INSERT INTO t12 VALUES('ab北京');SELECT * FROM t12;
#如果varchar不够用,可以考试使用mediumtext或者longtext,
#如果想简单点,可以使用直接使用textCREATE TABLE t13(content TEXT,content2 MEDIUMTEXT,content3 LONGTEXT);INSERT INTO t13 VALUES('zak', 'zak123', 'zak123456');SELECT * FROM t13;

1.9.7 日期类型的基本使用

日期类型的细节说明
TimeStamp 在 Insert 和 update时,自动更新

#演示时间相关的类型
#创建一张表,date,datetime,timestampCREATE TABLE t14(birthday DATE,--生日job_time DATE TIME,--记录年月日时分秒login_time TIMESTAMPNOTNULL DEFAULT CURRENT_TIMESTAMPONUPDATE CURRENT_TIMESTAMP); --登录时间,如果希望login_time列自动更新,需要配置SELECT * FROM t14;
INSERT INTO t14 (birthday,job_time)VALUES ('2022-11-11','2022-11-1110:10:10');--如果我们更新 t14 表的某条记录,login_time 列会自动的以当前时间进行更新

1.10 创建表练习

创建一个员工表 emp 选用适当的数据类型

CREATE TABLE `emp`(id INT,`name` VARCHAR(32),sex CHAR(1),brithday DATE,entry_date DATETIME,job VARCHAR(32),salary DOUBLE,`resume` TEXT) CHARSET utf8 COLLATE utf8_bin ENGINE INNODB;
-- 添加一条
INSERTINTO `emp`VALUES(100, '小妖怪', '男', '2000-11-11', '2010-11-10 11:11:11', '巡山的', 3000, '大王叫我来巡山');SELECT * FROM `emp`;

1.11 修改表-基本介绍

#修改表的操作练习
--员工表 emp 的上增加一个 image 列,varchar 类型(要求在resume后面)。ALTER TABLE empADD image VARCHAR(32) NOT NULLDEFAULT ''AFTER RESUMEDESC employee --显示表结构,可以查看表的所有列
--修改 job 列,使其长度为60。ALTER TABLE empMODIFY job VARCHAR(60) NOT NULL DEFAULT''
--删除sex列。ALTER TABLE empDROP sex
--表名改为 employee。RENAME TABLE emp TO employee 
--修改表的字符集为utf8ALTER TABLE employee CHARACTER SET utf8
--列名name修改为user_nameALTER TABLE employeeCHANGE `name` `user_name` VARCHAR(64) NOT NULL DEFAULT''DESC employee

1.12 数据库C[create]R[read]U[update]D[delete]语句

1.13 Insert语句

1.13.1 使用 INSERT 语句向表中插入数据。

#练习insert语句
--创建一张商品表goods(id int,goods_name varchar(10),price double);
--添加2条记录
CREATE TABLE `goods`(id INT,goods_name VARCHAR(10), --长度10price DOUBLE NOT NULL DEFAULT100);
--添加数据
INSERT INTO `goods`(id,goods_name,price)VALUES (10, '华为手机',2000);
INSERT INTO `goods`(id,goods_name,price)VALUES (20, '苹果手机',3000);SELECT * FROM goods;CREATE TABLE `goods2`(id INT,goods_name VARCHAR (10), --长度10price DOUBLE NOT NULL DEFAULT 100);

1.14 update语句

1.14.1 使用update语句修改表中数据

1.14.2 基本使用

案例::在上面创建的employee表中修改表中的纪录
        1. 将所有员工薪水修改为5000元。
        2. 将姓名为小妖怪的员工薪水修改为3000元。
        3. 将老妖怪的薪水在原有基础上增加1000元。

--演示update语句
--要求: 在上面创建的employee表中修改表中的纪录
--1.将所有员工薪水修改为5000元。[如果没有带where条件,会修改所有的记录,因此要小心]UPDATE employee SET salary = 5000
--2.将姓名为小妖怪的员工薪水修改为3000元。UPDATE employeeSET salary = 3000WHERE user_name = '小妖怪'
--3.将老妖怪的薪水在原有基础上增加1000元INSERT INTO employeeVALUES (200, '老妖怪', '1990-11-11', '2000-11-1110:10:10', '捶背的',5000, '给大王捶背', 'd:\\a.jpg');UPDATE employeeSET salary = salary + 1000WHERE user_name = '老妖怪'
-- 可以修改多个列的值UPDATE employeeSET salary = salary + 1000 , job = '出主意的'WHERE user_name = '老妖怪'SELECT * FROM employee;

1.14.3 使用细节:

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

1.15 delete 语句

1.15.1 使用 delete 语句删除表中数据

delete from tbl_name[WHERE where_definition]

案例: 删除表中名称为’老妖怪’的记录。        删除表中所有记录。

-- delete 语句演示
-- 删除表中名称为’老妖怪’的记录。DELETE FROM employeeWHERE user_name = '老妖怪';
-- 删除表中所有记录, 提醒,一定要小心DELETE FROM employee;
-- Delete 语句不能删除某一列的值(可使用update 设为 null 或者 ")UPDATE employee SET job = ' WHERE user_name = '老妖怪';SELECT * FROM employee
-- 要删除这个表DROP TABLE employee;

1.15.2 使用细节

1. 如果不使用where子句,将删除表中所有数据。
2. Delete语句不能删除某一列的值(可使用update设为null或者' ')
3. 使用delete语句仅删除记录,不删除表本身。如要删除表,使用droptable语句。drop table 表名;

1.16 select 语句

1.16.1 基本语法

SELECT [DISTINCT] * | {column1, column2. column3. .}FROM table name;

1.16.2 注意事项

1. Select指定查询哪些列的数据。
2. column指定列名。
3. *号代表查询所有列。
4.  From指定查询哪张表。
5. DISTINCT 可选,指显示结果时,是否去掉重复数据
案例练习:
        1. 查询表中所有学生的信息。
        2. 查询表中所有学生的姓名和对应的英语成绩。
        3. 过滤表中重复数据distinct 。
        4. 要查询的记录,每个字段都相同,才会去重

--select语句【重点难点】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 (id, NAME, chinese, english, math) VALUES (1,'zak',89,78,90);INSERT INTO student (id ,NAME, chinese, english, math)VALUES (2,'张飞',67,98,56);INSERT INTO student (id, NAME, chinese, english, math)VALUES (3,'宋江',87,78,77);INSERT INTO student (id, NAME, chinese, english, math)VALUES (4,'关羽',88,98,90);INSERT INTO student (id, NAME, chinese, english, math)VALUES (5,'赵云',82,84,67);INSERT INTO student (id, NAME, chinese, english, math)VALUES (6,'欧阳锋',55,85,45);INSERT INTO student (id, NAME, chinese, english, math)VALUES (7,'黄蓉',75,65,30);INSERT INTO student (id, NAME, chinese, english, math)VALUES (8,'韩信',45,65,99);SELECT * FROM student;--查询表中所有学生的信息。SELECT  *FROM student;
--查询表中所有学生的姓名和对应的英语成绩。SELECT `name`, english FROM student;
--过滤表中重复数据distinct。SELECT DISTINCT english FROM student;
--要查询的记录,每个字段都相同,才会去重SELECT DISTINCT `name`, english FROM student;

1.16.3 使用表达式对查询的列进行运算

SELECT * | { column1 | expression, column2 | expression,..}FROM tablename;

1.16.4 在select语句中可使用as语句

SELECT column_name as 别名 from 表名;

案例: 1. 统计每个学生的总分   2. 在所有学生总分加10分的情况   3. 使用别名表示学生分数。

-- select 语句的使用
-- 统计每个学生的总分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_scoreFROM student;

1.16.5 在where子句中经常使用的运算符

1.16.6 使用where子句,进行过滤查询

案例:

-- select语句
-- 查询姓名为赵云的学生成绩SELECT * FROM studentWHERE `name` = '赵云'--查询英语成绩大于90分的同学SELECT * FROM studentWHERE english > 90-- 查询总分大于200分的所有同学SELECT  *FROM studentWHERE(chinese + english + math) > 200-- 查询math大于60 并且(and)id大于4的学生成绩SELECT * FROM studentWHERE math > 60 AND id > 4-- 查询英语成绩大于语文成绩的同学SELECT * FROM studentWHERE english > chinese-- 查询总分大于200分 并且 数学成绩小于语文成绩,的姓赵的学生.
-- 赵% 表示 名字以韩开头的就可以SELECT * FROM studentWHERE(chinese + english + math) > 200 ANDmath < chinese AND `name` LIKE '赵%'-- 查询英语分数在 80-90之间的同学。SELECT * FROM studentWHERE english >= 80 AND english <= 90;SELECT * FROM studentWHERE english BETWEEN 80 AND 90;
-- between .. and .. 是 闭区间-- 查询数学分数为 89,90,91的同学。SELECT * FROM studentWHERE math = 89 OR math = 90 OR math = 91;SELECT  *FROM studentWHERE math IN (89, 90, 91);-- 查询所有姓李的学生成绩。SELECT * FROM studentWHERE `name` LIKE '李%'

1.16.7 使用order by 子句排序查询结果

SELECT column1 , column2 . column3. .FROM table;order by column asc | desc, ...

1. Order by 指定排序的列,排序的列既可以是表中的列名,也可以是select语句后指定的列名。
2.  Asc升序[默认]、Desc降序
3. ORDER BY子句应位于SELECT语句的结尾。

-- 演示order by 使用
-- 对数学成绩排序后输出【升序】。SELECT * FROM studentORDER BY math;-- 对总分按从高到低的顺序输出 [降序]
-- 使用别名排序SELECT `name` , (chinese + english + math) AS total_score FROM studentORDER BY total_score DESC;-- 对姓李的学生成绩[总分]排序输出(升序) where+orderbySELECT `name`, (chinese + english + math)AS total_score FROM studentWHERE `name` LIKE '李%'ORDER BY total_score;

1.17 合计/统计函数

1.17.1 count

-- Count返回行的总数Select count(*) | count(列名) from table_name[WHERE where_definition]
-- 演示mysql 的统计函数的使用
-- 统计一个班级共有多少学生?SELECT COUNT(*) FROM student;-- 统计数学成绩大于90的学生有多少个?SELECT COUNT(*) FROM studentWHERE math>90-- 统计总分大于250的人数有多少?SELE CTCOUNT(*) FROM studentWHERE (math + english + chinese) > 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; -- 4SELECT COUNT(`name`) FROM t15; -- 3-- 演示sum函数的使用
-- 统计一个班级数学总成绩?SELECT SUM(math) FROM student;-- 统计一个班级语文、英语、数学各科的总成绩SELECT SUM(math) AS math_total_score, SUM(english), SUM(chinese) FROM student;--统计一个班级语文、英语、数学的成绩总和SELECT SUM(math + english + chinese)FROM student;--统计一个班级语文成绩平均分SELECT SUM(chinese)/COUNT(*) FROM student;SELECT SUM(`name`)FROM student;--演示avg的使用
--练习:
--求一个班级数学平均分?SELECT AVG (math)FROM student;--求一个班级总分平均分SELECT AVG(math + english + chinese) FROM student;--演示max和min的使用--求班级最高分和最低分(数值范围在统计中特别有用)SELECT MAX(math + english + chinese), MIN(math + english + chinese)FROM student;--求出班级数学最高分和最低分SELECT MAX(math) AS math_high_socre, MIN(math) AS math_low_socreFROM student;

1.17.2 sum

--Sum函数返回满足where条件的行的和 -一般使用在数值列select sum(列名) { , sum(列名)...} from tablename[WHERE where_definition]
--演示sum函数的使用
--统计一个班级数学总成绩?SELECT SUM(math)FROM student;--统计一个班级语文、英语、数学各科的总成绩SELECT SUM(math) AS math_total_score,SUM (english),SUM (chinese) FROM student;--统计一个班级语文、英语、数学的成绩总和SELECT SUM (math + english + chinese) FROM student;--统计一个班级语文成绩平均分SELECT SUM(chinese)/COUNT(*) FROM student;SELECT SUM(`name`) FROM student;

1.17.3 avg

-- AVG函数返回满足where条件的一列的平均值Select avg(列名) {,avg(列名)...} from tablename[WHERE where_definition]
-- 演示avg的使用
-- 练习:
-- 求一个班级数学平均分?SELECT AVG(math) FROM student;-- 求一个班级总分平均分SELECT AVG(math + english + chinese) FROM student;

1.17.4 max/min

-- Max/min函数返回满足where条件的一列的最大/最小值Select max(列名)from tablename[WHERE where_definition]        
-- 演示max 和 min的使用
-- 求班级最高分和最低分(数值范围在统计中特别有用)SELECT MAX (math + english + chinese), MIN(math + english + chineseFROMstudent;--求出班级数学最高分和最低分SELECT MAX(math) AS math_high_socre,MIN(math) AS math_low_socreFROM student;

1.17.5 使用groupby子句对列进行分组[先创建测试表]

SELECT column1, column2. column3.. FROM tablegroup by column

1.17.6 使用having子句对分组后的结果进行过滤

SELECT column1 , column2 . column3 ..FROM tablegroup by column having ...

group by 用于对查询的结果分组统计,
having 子句用于限制分组显示结果.
        ?如何显示每个部门的平均工资和最高工资
       ?显示每个部门的每种岗位的平均工资和最低工资
       ?显示平均工资低于2000的部门号和它的平均工资 //别名

CREATE TABLE dept(/*部门表*/deptno MEDIUMINT UNSIGNED NOTNULL DEFAULT0,dname VARCHAR(20) NOTNULL DEFAULT "",loc VARCHAR(13) NOT NULL DEFAULT "");INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEWYORK'),(20, 'RESEARCH', 'DALLAS'),(30, 'SALES', 'CHICAGO'),(40, 'OPERATIONS', 'BOSTON');SELECT * FROM dept;-- 员工表CREATE TABLE emp(empno MEDIUMINT UNSIGNED NOTNULL DEFAULT 0,/*编号*/ename VARCHAR(20) NOTNULL DEFAULT "", /*名字*/job VARCHAR(9) NOTNULL DEFAULT "",/*工作*/mgr MEDIUMINT UNSIGNED,/*上级编号*/hiredate DATE NOT NULL, /*入职时间*/sal DECIMAL(7,2) NOTNULL, /*薪水*/comm DECIMAL(7,2) ,/*红利 奖金*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0/*部门编号*/);-- 添加测试数据INSERTINTO empVALUES(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, 'JONES', '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, 'SCOTT','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;-- 工资级别
#工资级别表
CREATETABLE salgrade(grade MEDIUMINT UNSIGNED NOTNULL DEFAULT 0,/*工资级别*/losal DECIMAL(17,2) NOTNULL, /* 该级别的最低工资 */hisal DECIMAL(17,2) NOTNULL /* 该级别的最高工资*/);INSERTINTO salgrade VALUES (1,700,1200);INSERTINTO salgrade VALUES (2,1201,1400);INSERTINTO salgrade VALUES (3,1401,2000);INSERTINTO salgrade VALUES (4,2001,3000);INSERTINTO salgrade VALUES (5,3001,9999);SELECT * FROM salgrade;SELECT * FROM dept;SELECT * FROM emp;--演示groupby+having-- GROUPby用于对查询的结果分组统计,
-- having 子句用于限制分组显示结果.
-- ? 如何显示每个部门的平均工资和最高工资
-- 分析:avg(sal) max(sal)
-- 按照部分来分组查询SELECTAVG(sal), MAX(sal) , deptnoFROM emp GROUP BY deptno;
-- 使用数学方法,对小数点进行处理SELECT FORMAT(AVG(sal),2), MAX(sal) , deptnoFROM emp GROUP BY deptno;-- ?显示每个部门的每种岗位的平均工资和最低工资
-- 分析 1. 显示每个部门的平均工资和最低工资
--     2. 显示每个部门的每种岗位的平均工资和最低工资SELECT AVG(sal), MIN(sal) , deptno, jobFROM emp GROUP BY deptno,job;-- ?显示平均工资低于2000的部门号和它的平均工资 // 别名
-- 分析 [写sql语句的思路是化繁为简,各个击破]
-- 1. 显示各个部门的平均工资和部门号
-- 2. 在1的结果基础上,进行过滤,保留 AVG(sal)<2000
-- 3. 使用别名进行过SELECT AVG (sal), deptnoFROM emp GROUP BY deptnoHAVING AVG (sal) < 2000;
-- 使用别名SELECT AVG (sal) AS avg_sal, deptnoFROM emp GROUP BY deptnoHAVING avg_sal < 2000;

1.18 字符串相关函数

-- 演示字符串相关函数的使用 , 使用emp表来演示
-- CHARSET(str) 返回字串字符集SELECT CHARSET (ename) FROM emp;
-- CONCAT(string2 [,... ]) 连接字串, 将多个列拼接成一列SELECT CONCAT(ename, ' 工作是 ', job) FROM emp;-- INSTR (string ,substring ) 返回 substring 在 string 中出现的位置,没有返回 0
-- dual 亚元表, 系统表 可以作为测试表使用SELECT INSTR('zak', 'ke') FROM DUAL;-- UCASE (string2 ) 转换成大写SELECT UCASE(ename) FROM emp;-- LCASE (string2 ) 转换成小写SELECT LCASE(ename) FROM emp;
-- LEFT (string2 ,length )从 string2 中的左边起取 length 个字符
-- RIGHT (string2 ,length ) 从 string2 中的右边起取 length 个字符SELECT LEFT(ename, 2) FROM emp;-- LENGTH (string )string 长度[按照字节]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('zak', 'zak') FROM DUAL;
-- SUBSTRING (str , position [,length ])
-- 从str 的position 开始【从1开始计算】,取length个字符
-- 从ename 列的第一个位置开始取出2个字符SELECT SUBSTRING(ename, 1, 2) FROM emp;-- LTRIM (string2 ) RTRIM (string2 ) TRIM(string)
-- 去除前端空格或后端空格SELECTLTRIM('  zak')FROMDUAL;SELECTRTRIM('zak  ')FROMDUAL;SELECTTRIM('  zak  ')FROMDUAL;-- 练习: 以首字母小写的方式显示所有员工emp表的姓名
-- 方法1
-- 思路先取出ename 的第一个字符,转成小写的
-- 把他和后面的字符串进行拼接输出即可SELECT CONCAT (LCASE (SUBSTRING(ename,1,1)), SUBSTRING(ename,2)) AS new_name FROM emp;SELECT CONCAT(LCASE(LEFT(ename,1)), SUBSTRING(ename,2)) AS new_name  FROM emp;

1.19 数学相关函数

        rand(返回一个随机浮点值v.范围在0到1之间(即,其范围为0<= v <=1.0)。若已指定一个整数参数N, 则它被用作种子值,用来产生重复序列。

--演示数学相关函数
--ABS(num)绝对值SELECT ABS(-10) FROM DUAL;
--BIN(decimal_number)十进制转二进制SELECT BIN(10)FROM DUAL;
--CEILING(number2)向上取整,得到比num2大的最小整数SELECT CEILING (-1.1)FROM DUAL;--CONV(number2,from_base,to_base) 进制转换
--下面的含义是8是十进制的8,转成2进制输出SELECT CONV(8,10,2) FROM DUAL;
--下面的含义是8是16进制的8,转成2进制输出SELECT CONV(16,16,10) FROM DUAL;--FLOOR(number2)向下取整,得到比num2小的最大整数SELECT FLOOR(-1.1) FROM DUAL--FORMAT(number,decimal_places)    保留小数位数(四舍五入)SELECT FORM AT (78.125458,2) FROM DUAL;--HEX (DecimalNumber)转十六进制--LEAST(number,number2 [,..])求最小值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() FROM DUAL;SELECT CURRENT_TIMESTAMP() FROM DUAL;

1.20 时间日期相关函数

        在实际开发中,我们也经常使用 int 来保存一个unix时间戳,然后使用from_unixtime()进行转换,,还是非常有实用价值的

--日期时间相关函数--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(30),send_time DATETIME );-- 添加一条记录INSERTINTO mesVALUES(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 mesWHERE DATE_ADD(send_time, INTERVAL 10 MINUTE) >= NOW()SELECT * FROMmesWHERE send_time >= DATE_SUB(NOW(), INTERVAL10 MINUTE)-- 请在mysql 的sql语句中求出 2011-11-11 和 1990-1-1 相差多少天SELECT DATEDIFF('2011-11-11', '1990-01-01') FROM DUAL;
-- 请用mysql 的sql语句求出你活了多少天?[练习]1986-11-11 出生SELECT DATEDIFF(NOW(), '1986-11-11') FROM DUAL;
-- 如果你能活80岁,求出你还能活多少天.[练习]1986-11-11 出生
-- 先求出活80岁 时, 是什么日期 X
-- 然后在使用 datediff(x, now()); 1986-11-11->datetime
-- INTERVAL80YEAR : YEAR 可以是 年月日,时分秒
-- '1986-11-11' 可以 date,datetime timestampSELECT DATEDIFF (DATE_ADD('1986-11-11', INTERVAL 80 YEAR), NOW())FROM DUAL;SELECT TIMEDIFF('10:11:11', '06:10:10') FROM DUAL;-- YEAR|Month|DAY| DATE (datetime )SELECT YEAR(NOW()) FROM DUAL;SELECT MONTH(NOW()) FROMDUAL;SELECT DAY(NOW()) FROMDUAL;SELECT MONTH('2013-11-10') FROM DUAL;
-- unix_timestamp() : 返回的是 1970-1-1 到现在的秒数SELECT UNIX_TIMESTAMP() FROM DUAL;
-- FROM_UNIXTIME() : 可以把一个unix_timestamp 秒数[时间戳],转成指定格式的日期
-- %Y-%m-%d 格式是规定好的,表示年月日
-- 意义:在开发中,可以存放一个整数,然后表示时间,通过FROM_UNIXTIME转换SELECT FROM_UNIXTIME(1618483484, '%Y-%m-%d') FROM DUAL;SELECT FROM_UNIXTIME(1618483100, '%Y-%m-%d%H:%i:%s') FROM DUAL;SELECT * FROM mysql.user\G

1.21 加密和系统函数

--演示加密函数和系统函数--USER()查询用户
--可以查看登录到mysql的有哪些用户,以及登录的IPSELECT USER() FROM DUAL; --用户@IP地址
--DATABASE()查询当前使用数据库名称SELECT DATA BASE();--MD5(str)为字符串算出一个MD532的字符串,常用(用户密码)加密
--root密码是hsp->加密md5->在数据库中存放的是加密后的密码SELECT MD5('zak')FROM DUAL;SELECT LENGTH (MD5('zak')) FROM DUAL;-- 演示用户表,存放密码时,是md5CREATE TABLE zak_user(id INT ,`name` VARCHAR(32) NOT NULL DEFAULT ",pwd CHAR(32) NOTNULL DEFAULT ");INSERT INTO zak_userVALUES(100, '知昂可', MD5('zak'));SELECT * FROM zak_user;  -- csdnSELECT * FROM zak_user  -- SQL注入问题WHERE`name`='知昂可' AND pwd = MD5('zak')-- PASSWORD(str) -- 加密函数, MySQL 数据库的用户密码就是 PASSWORD函数加密SELECT PASSWORD('zak') FROM DUAL; -- select * from mysql.user \G    从原文密码str 计算并返回密码字符串
-- 通常用于对mysql数据库的用户密码加密
-- mysql.user 表示 数据库.表SELECT * FROM mysql.user

1.22 流程控制函数

#演示流程控制语句#IF(expr1,expr2,expr3)如果expr1为True,则返回expr2否则返回expr3SELECT IF (TRUE, '北京', '上海') FROM DUAL;
#IFNULL(expr1,expr2)如果expr1不为空NULL,则返回expr1,否则返回expr2SELECT IFNULL( NULL, '知昂可')FROMDUAL;
# SELE CTCASE WHEN expr1 THEN expr2 WHEN expr3 THEN expr4 ELSE expr5 END; [类似多重分支.]
# 如果expr1 为TRUE,则返回expr2,如果expr2 为t, 返回 expr4, 否则返回 expr5SELECT CASEWHEN TRUE THEN'jack' -- jackWHEN FALSE THEN'tom'ELSE 'mary' END-- 1. 查询emp 表, 如果 comm 是null, 则显示0.0
-- 说明,判断是否为null 要使用 is null, 判断不为空 使用 is notSELECT 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 CASEWHEN job='CLERK'THEN'职员'WHEN job='MANAGER'THEN'经理'WHEN job='SALESMAN'THEN'销售人员'ELSE job END)AS 'job'FROM emp;SELECT * FROM emp;SELECT * FROM dept;SELECT * FROM salgrade;

1.23 mysql表查询--加强

1.23.1 介绍

        在前面我们讲过mysql表的基本查询,但是都是对一张表进行的查询,这在实际的软件开发中,还远远的不够。   下面我们讲解的过程中,将使用前面创建三张表(emp,dept,salgrade)为大家演示如何进行多表查询
使用where子句
        ?如何查找1992.1.1后入职的员工
如何使用like操作符
        %:表示O到多个字符:表示单个字符
        ?如何显示首字符为S的员工姓名和工资
        ?如何显示第三个字符为大写O的所有员工的姓名和工资
如何显示没有上级的雇员的情况
使用order by子句
        ?如何按照工资的从低到高的顺序,显示雇员的信息
        ?按照部门号升序而雇员的工资降序排列,显示雇员信息

--查询加强
--使用where子句
-- ?如何查找1992.1.1后入职的员工
-- 说明:在mysql中,日期类型可以直接比较,需要注意格式SELECT * FROM empWHERE hiredate >'1992-01-01'--如何使用like操作符(模糊)
-- %: 表示0到多个任意字符 _: 表示单个任意字符
-- ?如何显示首字符为S的员工姓名和工资SELECT ename, sal FROM empWHERE ename LIKE 'S%-- ?如何显示第三个字符为大写O的所有员工的姓名和工资SELECT ename, sal FROM empWHERE ename LIKE '__O%'--如何显示没有上级的雇员的情况SELECT * FROM empWHERE mgr IS NULL;
-- 查询表结构DESC emp-- 使用order by 子句
-- ?如何按照工资的从低到高的顺序[升序],显示雇员的信息SELECT * FROM empORDER BY sal--?按照部门号升序而雇员的工资降序排列 , 显示雇员信息SELECT * FROM empORDER BY deptno ASC , sal DESC;

1.23.2 分页查询

--分页查询-
-按雇员的id号升序取出,每页显示3条记录,请分别显示第1页,第2页,第3页--第1页SELECT * FROM empORDER BY empnoLIMIT 0,3;
--第2页SELECT * FROM empORDER BY empnoLIMIT 3,3;
--第3页SELECT * FROM empORDER BY empnoLIMIT 6,3;
--推导一个公式SELECT * FROM empORDER BY empnoLIMIT  每页显示记录数 * (第几页-1),每页显示记录数
--测试SELECT job,COUNT(*)FROM emp GROUP BY job;
--显示雇员总数,以及获得补助的雇员数SELECT COUNT(*)FROM emp WHERE mgr IS NOT NULL;SELECT MAX(sal)-MIN(sal)FROM emp;

1.23.3 使用分组函数和分组子句groupby

--增强groupby的使用--(1)显示每种岗位的雇员总数、平均工资。SELECT COUNT(*),AVG(sal),jobFROM empGROUP BY job;
--(2)显示雇员总数,以及获得补助的雇员数。
--思路: 获得补助的雇员数 就是 comm 列为非null, 就是count(列),如果该列的值为null, 是不会统计 ,SQL 非常灵活,需要我们动脑筋.SELECT COUNT(*), COUNT(comm)FROM emp-- 老师的扩展要求:统计没有获得补助的雇员数SELECT COUNT(*), COUNT(IF(comm IS NULL, 1, NULL))FROM empSELECT COUNT(*), COUNT(*)- COUNT(comm)FROM emp
-- (3) 显示管理者的总人数。小技巧:尝试写->修改->尝试[正确的]SELECT COUNT (DISTINCT mgr)FROM emp;-- (4) 显示雇员工资的最大差额。
-- 思路: max(sal)-min(sal)SELECT MAX(sal)- MIN(sal)FROM emp;SELECT * FROM emp;select * from dept;-- 应用案例:请统计各个部门groupby 的平均工资 avg,
-- 并且是大于1000的 having,并且按照平均工资从高到低排序, orderby
-- 取出前两行记录 limit0,2SELECT deptno,AVG(sal) AS avg_salFROM empGROUP BY deptnoHAVING avg_sal > 1000ORDERBY avg_sal DESCLIMIT 0,2

1.23.4 数据分组的总结

SELECT column1 , column2 . column3. . FROM  tablegroup by columnhaving conditionorder by columnlimit start, rows ;

1.24 mysql 多表查询

1.24.1 说明

        多表查询是指基于两个和两个以上的表查询.在实际应用中,查询单个表可能不能满足你的需求,需要使用到(dept表和emp表)

1.24.2 多表查询练习

--多表查询
--?显示雇员名,雇员工资及所在部门的名字【笛卡尔集】
/*分析1.雇员名,雇员工资来自emp表2. 部门的名字 来自 dept表3. 需求对 emp 和 dept查询 ename,sal,dname,deptno4. 当我们需要指定显示某个表的列是,需要 表.列表
*/SELECT ename,sal,dname,emp.deptnoFROM emp,deptWHERE emp.deptno = dept.deptnoSELECT * FROM emp;SELECT * FROM dept;SELECT * FROM salgrade;
-- 小技巧:多表查询的条件不能少于 表的个数-1, 否则会出现笛卡尔集
-- ?如何显示部门号为10的部门名、员工名和工SELECT ename,sal,dname, emp.deptnoFROM emp, deptWHERE emp.deptno = dept.deptno AND emp.deptno = 10-- ?显示各个员工的姓名,工资,及其工资的级别-- 思路 姓名,工资 来自 emp13
-- 工资级别 salgrade5
-- 写sql , 先写一个简单,然后加入过滤条件...select ename, sal, gradefrom emp , salgradewhere sal between losal and hisal;

1.24.3 自连接

        自连接是指在同一张表的连接查询 [将同一张表看做两张表]。

--多表查询的自连接--思考题:显示公司员工名字和他的上级的名字--分析:员工名字在emp,上级的名字的名字emp
--员工和上级是通过emp表的mgr列关联
--小结:
--自连接的特点1.把同一张表当做两张表使用
--   2.需要给表取别名表名表别名
-- 3.列名不明确,可以指定列的别名列名as列的别名SELECT worker.ename AS '职员名' , boss.enameAS'上级名'FROM emp worker,emp bossWHERE worker.mgr = boss.empno;SELECT * FROM emp;

1.25 mysql表子查询

1.25.1 什么是子查询

子查询是指嵌入在其它sql语句中的select语句,也叫嵌套查询

1.25.2 单行子查询

单行子查询是指只返回一行数据的子查询语句

1.25.3 多行子查询

--子查询的演示
--请思考:如何显示与SMITH同一部门的所有员工?/*1.先查询到SMITH的部门号得到2.把上面的select语句当做一个子查询来使用
*/SELECT deptnoFROM empWHERE ename ='SMITH'--下面的答案.SELECT *FROM empWHERE deptno =(SELECT deptnoFROM empWHERE ename ='SMITH')
--课堂练习:如何查询和部门10的工作相同的雇员的
--名字、岗位、工资、部门号,但是不含10号部门自己的雇员./*1.查询到10号部门有哪些工作2.把上面查询的结果当做子查询使用
*/select distinct jobfrom empwhere deptno =10;--下面语句完整select ename,job,sal,deptnofrom empwhere job in(SELECT DISTINCT jobFROM empWHERE deptno = 10) and deptno <> 10

1.25.4 在多行子查询中使用all操作符

--all和any的使用--请思考:显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号SELECT ename,sal,deptnoFROM empWHERE sal > ALL(SELECT salFROM empWHERE deptno = 30)-- 可以这样写SELECT ename, sal, deptnoFROM empWHERE sal > (SELECT MAX(sal)FROM empWHERE deptno = 30)-- 请思考:如何显示工资比部门30的其中一个员工的工资高的员工的姓名、工资和部门号SELECT ename, sal, deptnoFROM empWHERE sal > any(SELECT salFROM empWHERE deptno = 30)SELECT ename, sal, deptnoFROM empWHERE sal > (SELECT min(sal)FROM empWHERE deptno = 30)-- 查询ecshop 中各个类别中,价格最高的商品-- 查询 商品表
-- 先得到 各个类别中,价格最高的商品 max + groupbycat_id, 当做临时表
-- 把子查询当做一张临时表可以解决很多很多复杂的查询select cat_id , max(shop_price)from ecs_goodsgroup by cat_id-- 这个最后答案select goods_id, ecs_goods.cat_id, goods_name, shop_pricefrom (SELECT cat_id , MAX(shop_price) as max_priceFROM ecs_goodsGROUP BY cat_id) temp , ecs_goodswhere temp.cat_id = ecs_goods.cat_idand temp.max_price = ecs_goods.shop_price

1.25.5 多列子查询

--多列子查询--请思考如何查询与allen的部门和岗位完全相同的所有雇员(并且不含allen本人)
--(字段1,字段2...)=(select字段1,字段2from。。。。)--分析:1.得到smith的部门和岗位SELECT deptno,jobFROM empWHERE ename = 'ALLEN'-- 分析:2 把上面的查询当做子查询来使用,并且使用多列子查询的语法进行匹配SELECT *FROM empWHERE(deptno , job) = (SELECT deptno , jobFROM empWHERE ename ='ALLEN') AND ename != 'ALLEN-- 请查询 和宋江数学,英语,语文
-- 成绩 完全相同的学生SELECT *FROM studentWHERE(math, english, chinese) = (SELECT math, english, chineseFROM studentWHERE`name` = '宋江')SELECT * FROM student;

1.25.6 在from子句中使用子查询

--子查询练习--请思考:查找每个部门工资高于本部门平均工资的人的资料
--这里要用到数据查询的小技巧,把一个子查询当作一个临时表使用--1.先得到每个部门的部门号和对应的平均工资SELECT deptno,AVG(sal) AS avg_salFROM emp GROUP BY deptno--2.把上面的结果当做子查询,和emp进行多表查询SELECT ename,sal,temp.avg_sal,emp.deptnoFROM emp,(SELECT deptno,AVG(sal) AS avg_salFROM empGROUP BY deptno) tempWHERE emp.deptno = temp.deptnoAND emp.sal > temp.avg_sal-- 查找每个部门工资最高的人的详细资料SELECT ename, sal, temp.max_sal, emp.deptnoFROM emp,(SELECT deptno, MAX(sal)AS max_salFROM empGROUP BY deptno) tempWHERE emp.deptno = temp.deptno AND emp.sal = temp.max_sal-- 查询每个部门的信息(包括:部门名,编号,地址)和人员数量,我们一起完成。- 1. 部门名,编号,地址 来自 dept表
-- 2. 各个部门的人员数量-》 构建一个临时表SELECT COUNT(*), deptnoFROM empGROUP BY deptno;SELECT dname,dept.deptno,loc,tmp.per_numAS'人数'FROM dept,(SELECT COUNT(*) AS per_num,deptnoFROM empGROUP BY deptno)tmpWHERE tmp.deptno = dept.deptno--还有一种写法表.*表示将该表所有列都显示出来,可以简化sql语句
--在多表查询中,当多个表的列不重复时,才可以直接写列名SELECT tmp.*, dname,locFROM dept,(SELECT COUNT(*) ASper_num,deptnoFROM empGROUP BY deptno) tmpWHERE tmp.deptno = dept.deptno

1.26 表复制

1.26.1 自我复制数据(蠕虫复制)

-- 表的复制
-- 为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据CREATE TABLE my_tab01( id INT,`name` VARCHAR(32),sal DOUBLE,job VARCHAR(32),deptno INT);DESC my_tab01SELECT * FROM my_tab01;-- 演示如何自我复制
-- 1. 先把emp 表的记录复制到 my_tab01INSERT INTO my_tab01(id, `name`, sal, job,deptno)SELECT empno, ename, sal, job, deptno FROM emp;-- 2. 自我复制INSERT INTO my_tab01SELECT * FROM my_tab01;SELECT COUNT(*) FROM my_tab01;-- 如何删除掉一张表重复记录
-- 1. 先创建一张表 my_tab02,
-- 2. 让 my_tab02 有重复的记CREATE TABLE my_tab02 LIKE emp;  -- 这个语句 把emp表的结构(列),复制到my_tab02DESCmy_tab02;INSERT INTO my_tab02SELECT * FROM emp;SELECT * FROM my_tab02;-- 3. 考虑去重 my_tab02的记录
/*思路(1) 先创建一张临时表 my_tmp, 该表的结构和 my_tab02一样(2) 把my_tmp 的记录 通过 distinct 关键字 处理后 把记录复制到 my_tmp(3) 清除掉 my_tab02 记录(4) 把 my_tmp 表的记录复制到 my_tab02(5) drop 掉 临时表my_tmp*/
-- (1) 先创建一张临时表 my_tmp, 该表的结构和 my_tab02一样create table my_tmp like my_tab02
-- (2) 把 my_tmp 的记录 通过 distinct 关键字 处理后 把记录复制到 my_tmpinsert into my_tmpselect distinct * from my_tab02;
-- (3) 清除掉 my_tab02 记录delete from my_tab02;
-- (4) 把 my_tmp 表的记录复制到 my_tab02insert into my_tab02select * from my_tmp;
-- (5) drop 掉 临时表my_tmpdrop table my_tmp;select * from my_tab02;

1.27 合并查询

1.27.1 介绍

-- 合并查询SELECT ename,sal,job FROM emp WHERE sal>2500  -- 5SELECT ename,sal,job FROM emp WHERE job='MANAGER'  -- 3-- union all 就是将两个查询结果合并,不会去重SELECT ename,sal,job FROM emp WHERE sal>2500  -- 5UNION ALLSELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3-- union 就是将两个查询结果合并,会去重SELECT ename,sal,job FROM emp WHERE sal>2500  -- 5UNIONSELECT ename,sal,job FROM emp WHERE job='MANAGER'  -- 3

1.28 mysql 表外连接

1.28.1 外连接

1. 左外连接(如果左侧的表完全显示我们就说是左外连接)
2. 右外连接(如果右侧的表完全显示我们就说是右外连接)。

-- 外连接--比如:列出部门名称和这些部门的员工名称和工作,
--同时要求显示出那些没有员工的部门--使用我们学习过的多表查询的SQL,看看效果如何?SELECT dname,ename,jobFROM emp,deptWHERE emp.deptno = dept.deptnoORDER BY dnameSELECT * FROM dept;SELECT * FROM emp;-- 创建 stu/*id name1 Jack2 Tom3 Kity4 nono*/CREATE TABLE stu(id INT,`name` VARCHAR(32));INSERT INTO stu VALUES(1, 'jack'),(2,'tom'),(3, 'kity'),(4, 'nono');SELECT * FROM stu;
-- 创建 exam
/*id  grade1   562   7611   8
*/CREATE TABLE exam(id INT,grade INT);INSERT INTO exam VALUES(1, 56),(2,76),(11, 8);SELECT * FROM exam;-- 使用左连接
-- (显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)SELECT `name`, stu.id, gradeFROM stu, examWHERE stu.id = exam.id;-- 改成左外连接
SELECT`name`, stu.id, gradeFROM stu LEFTJOIN examON stu.id = exam.id;-- 使用右外连接(显示所有成绩,如果没有名字匹配,显示空)
-- 即:右边的表(exam) 和左表没有匹配的记录,也会把右表的记录显示出来
SELECT`name`, stu.id, gradeFROM stu RIGHT JOIN examON stu.id = exam.id;-- 列出部门名称和这些部门的员工信息(名字和工作),
-- 同时列出那些没有员工的部门名。5min
-- 使用左外连接实现
SELECT dname, ename, jobFROM dept LEFTJOIN empON dept.deptno = emp.deptno-- 使用右外连接实现
SELECT dname, ename, jobFROM emp RIGHT JOIN deptON dept.deptno = emp.deptno

1.29 mysql 约束

1.29.1 基本介绍

        约束用于确保数据库的数据满足特定的商业规则。在mysql中,约束包括: not null、unique,primary key,foreign key,和check五种.

1.29.2 primarykey(主键)-基本使用

        字段名  字段类型  primary key
用于唯一的标示表行的数据,当定义主键约束后,该列不能重复

--主键使用--id name emailCREATE TABLE t17(id INT PRIMARY KEY,  --表示id列是主键`name` VARCHAR(32),email VARCHAR(32));-- 主键列的值是不可以重复INSERT INTO t17VALUES(1, 'jack', 'jack@sohu.com');INSERT INTO t17VALUES(2, 'tom', 'tom@sohu.com');INSER TINTO t17VALUES(1, 'hsp', 'zak@sohu.com');SELECT * FROM t17-- 主键使用的细节讨论
-- primary key 不能重复而且不能为 null。
INSERT INTO t17VALUES(NULL, 'zak', 'zak@sohu.com');
-- 一张表最多只能有一个主键, 但可以是复合主键(比如 id+name)CREATE TABLE t18(id INT PRIMARYKEY, -- 表示id列是主键`name` VARCHAR(32), PRIMARYKEY  -- 错误的email VARCHAR(32));
-- 演示复合主键 (id 和 name 做成复合主键)CREATE TABLE t18(id INT ,`name` VARCHAR(32),email VARCHAR(32),PRIMARY KEY(id, `name`) -- 这里就是复合主键);INSERT INTO t18VALUES(1, 'tom', 'tom@sohu.com');INSERT INTO t18VALUES(1, 'jack', 'jack@sohu.com');INSERT INTO t18VALUES(1, 'tom', 'xx@sohu.com'); -- 这里就违反了复合主键
SELECT * FROM t18;-- 主键的指定方式 有两种
-- 1. 直接在字段名后指定:字段名 primakry key
-- 2. 在表定义最后写 primary key(列名)
CREATE TABLE t19(id INT ,`name` VARCHAR(32) PRIMARY KEY,email VARCHAR(32));CREATE TABLE t20(id INT ,`name` VARCHAR(32) ,email VARCHAR(32),PRIMARY KEY(`name`)  -- 在表定义最后写 primary key(列名);--使用desc表名,可以看到primarykey的情况DESC t20 --查看t20表的结果,显示约束的情况
DESC t18

1.29.3 not null(非空)

如果在列上定义了not null,那么当插入数据时,必须为列提供数据。
        字段名  字段类型 not null

1.29.4 unique(唯一)

当定义了唯一约束后,该列值是不能重复的.。
         字段名  字段类型  unique
unique细节(注意): 
1. 如果没有指定not null,则unique字段可以有多个null        2. 一张表可以有多个unique字段

--unique的使用CREATE TABLE t21(id INT UNIQUE, --表示id列是不可以重复的.`name` VARCHAR(32),email VARCHAR(32));INSERT INTO t21VALUES(1, 'jack', 'jack@sohu.com');INSERT INTO t21VALUES(1, 'tom', 'tom@sohu.com');--unqiue使用细节
--1.如果没有指定notnull,则unique字段可以有多个null
--如果一个列(字段),是unique not null使用效果类似primary keyINSERT INTO t21VALUES (NULL, 'tom', 'tom@sohu.com');SELECT * FROM t21;
--2. 一张表可以有多个unique字段
CREATE TABLE t22(id INT UNIQUE, --表示id列是不可以重复的.`name` VARCHAR(32) UNIQUE, --表示name不可以重复email VARCHAR(32));DESC t22

1.29.5 foreignkey(外键)

        用于定义主表和从表之间的关系:外键约束要定义在从表上,主表则必须具有主键约束或是unique约束.  当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为null(学生/班级图示)

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

-- 外键演示-- 创建 主表 my_classCREATE TABLE my_class (id INT PRIMARYKEY,  -- 班级编号`name` VARCHAR(32) NOT NULL DEFAULT ');-- 创建 从表 my_stuCREATE TABLE my_stu (id INT PRIMARY KEY, -- 学生编号`name` VARCHAR(32) NOTNULLDEFAULT ',class_id INT ,-- 学生所在班级的编号
-- 下面指定外键关系FOREIGN KEY(class_id) REFERENCES my_class(id)) 
-- 测试数据
INSERT INTO my_classVALUES(100, 'java'), (200, 'web');
INSERT INTO my_classVALUES(300, 'php');SELECT * FROM my_class;
INSERT INTO my_stuVALUES(1, 'tom', 100);
INSERT INTO my_stuVALUES(2, 'jack', 200);
INSERT INTO my_stuVALUES(3, 'zak', 300);
INSERT INTO my_stuVALUES(4, 'mary', 400); -- 这里会失败...因为 400 班级不存在INSERT INTO my_stuVALUES(5, 'king', NULL);  -- 可以, 外键 没有写 not null
SELECT * FROM my_class;-- 一旦建立主外键的关系,数据不能随意删除了
DELETE FROM my_classWHERE id = 100;

1.29.6 check

        用于强制行数据必须满足的条件,假定在sal列上定义了check约束,并要求sal列值在1000 ~2000之间如果不再1000~2000之间就会提示出错。
提示: oracle和sql server均支持check ,但是mysql5.7目前还不支持check ,只做语法校验,但不会生效。

        在mysql中实现 check 的功能,一般是在程序中控制,或者通过触发器完成。

-- 演示check的使用
-- mysql5.7 目前还不支持check ,只做语法校验,但不会生效
-- 了解
-- 学习 oracle, sql server, 这两个数据库是真的生效-- 测试
CREATE TABLE t23 (id INT PRIMARY KEY,`name` VARCHAR(32) ,sex VARCHAR(6) CHECK (sex IN('man','woman')),sal DOUBLE CHECK( sal> 1000AND sal <2000));-- 添加数据
INSERT INTO t23VALUES(1, 'jack', 'mid', 1);SELECT * FROM t23;

1.29.7 商店售货系统表设计案例

-- 使用约束的练习CREATE DATABASE shop_db-- 现有一个商店的数据库shop_db,记录客户及其购物情况,由下面三个表组成:
-- 商品goods(商品号goods_id,商品名goods_name,单价unitprice,商品类别category,
-- 供应商provider);
-- 客户customer(客户号customer_id,姓名 name,住址address,电邮 email 性别 sex,身份证card_Id);
-- 购买purchase(购买订单号order_id,客户号customer_id,商品号goods_id,购买数量nums);
-- 1 建表,在定义中要求声明 [进行合理设计]:
-- (1)每个表的主外键;
-- (2)客户的姓名不能为空值;
-- (3)电邮不能够重复;
-- (4)客户的性别[男|女]check 枚举..
-- (5)单价 unitprice 在 1.0- 9999.99 之间 check-- 商品goodsCREATE TABLE goods (goods_id INT PRIMARY KEY,goods_name VARCHAR(64) NOT NULL DEFAULT ",unitprice DECIMAL(10,2) NOT NULL DEFAULT 0CHECK(unitprice >= 1.0AND unitprice <= 9999.99),category INT NOT NULL DEFAULT 0,provider VARCHAR(64) NOT NULL DEFAULT ");-- 客户customer(客户号customer_id,姓名 name,住址address,电邮 email 性别 sex,
--身份证card_Id);CREATE TABLE customer(customer_id CHAR(8) PRIMARY KEY, --程序员自己决定`name` VARCHAR(64) NOT NULL DEFAULT ",address VARCHAR(64) NOT NULL DEFAULT ",email VARCHAR(64) UNIQUE NOT NULL,sex ENUM('男','女') NOT NULL, --这里使用的枚举类型,card_Id CHAR(18));--购买purchase(购买订单号order_id,客户号customer_id,商品号goods_id,
--购买数量nums);
CREATE TABLE purchase(order_id INT UNSIGNED PRIMARY KEY,customer_id CHAR(8) NOT NULL DEFAULT ", --外键约束在后goods_id INT NOT NULL DEFAULT 0, --外键约束在后nums INT NOT NULL DEFAULT 0,FOREIGN KEY(customer_id) REFERENCES customer (customer_id),FOREIGN KEY (goods_id) REFERENCES goods(goods_id));DESC goods; DESC customer;DESC purchase;

1.30 自增长

        在某张表中,存在一个id列(整数),我们希望在添加记录的时候,该列从1开始,自动的增长,怎么处理?                 字段名  整型  primary  key auto_increment

1.30.1 自增长使用细节

1. 一般来说自增长是和primary key配合使用的
2. 自增长也可以单独使用[但是需要配合一个unique]
3. 自增长修饰的字段为整数型的(虽然小数也可以但是非常非常少这样使用)
4. 自增长默认从1开始,你也可以通过如下命令修改alter  table表名auto_increment = 新的开始值;
5. 如果你添加数据时,给自增长字段(列)指定的有值,则以指定的值为准,如果指定了自增长,一般来说,就按照自增长的规则来添加数据。

--演示自增长的使用--创建表
CREATE TABLE t24(id INT PRIMARY KEY AUTO_INCREMENT,email VARCHAR(32) NOT NULL DEFAULT ",`name` VARCHAR(32) NOT NULL DEFAULT ");DESC t24
--测试自增长的使用
INSERT INTO t24VALUES(NULL, 'tom@qq.com', 'tom');INSERT INTO t24(email, `name`) VALUES ('zak@sohu.com', 'zak');SELECT * FROM t24;-- 修改默认的自增长开始值
ALTER TABLE t25 AUTO_INCREMENT = 100
CREATE TABLE t25(id INT PRIMARY KEY AUTO_INCREMENT,email VARCHAR(32) NOT NULLDEFAULT ",`name` VARCHAR(32) NOT NULL DEFAULT ");
INSERT INTO t25VALUES(NULL, 'mary@qq.com', 'mary');
INSERT INTO t25VALUES(666, 'zak@qq.com', 'zak');
SELECT * FROM t25;CREATE DATABASE tmp;CREATE TABLE dept( /*部门表*/deptno MEDIUMINT UNSIGNED NOTNULL DEFAULT0,dname VARCHAR(20) NOTNULL DEFAULT "",loc VARCHAR(13) NOT NULL DEFAULT "") ;#创建表EMP雇员
CREATE TABLE emp(empno MEDIUMINT UNSIGNED NOTNULL DEFAULT0, /*编号*/ename VARCHAR(20) NOT NULL DEFAULT "",  /*名字*/job VARCHAR(9) NOT NULL DEFAULT "", /*工作*/mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*上级编号*/hiredate DATE NOT NULL,/*入职时间*/sal DECIMAL(7,2) NOT NULL, /*薪水*/comm DECIMAL(7,2) NOT NULL,/*红利*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/) ;#工资级别表
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);

1.31 mysql索引

1.31.1 索引快速入门

        说起提高数据库性能,索引是最物美价廉的东西了。不用加内存,不用改程序,不用调sql,查询速度就可能提高百倍干倍。

        是不是建立一个索引就能解决所有的问题?
        ename上没有建立索引会怎样?
        select * from emp where ename = 'axJxC' ;

--创建测试数据库 tmpCREATE DATABASE tmp;CREATE TABLE dept( /*部门表*/deptno MEDIUMINT UNSIGNED NOTNULL DEFAULT 0,dname VARCHAR(20) NOT NULL DEFAULT "",loc VARCHAR(13) NOT NULL DEFAULT "");#创建表EMP雇员
CREATE TABLE emp(empno MEDIUMINT UNSIGNED NOTNULL DEFAULT0,/*编号*/ename VARCHAR(20) NOT NULL DEFAULT "",/*名字*/job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/hiredate DATE NOT NULL,/*入职时间*/sal DECIMAL(7,2) NOT NULL,/*薪水*/comm DECIMAL(7,2) NOT NULL,/*红利*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0/*部门编号*/) ;#工资级别表
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);DELIMITER $$#创建一个函数,名字 rand_string,可以随机返回我指定的个数字符串
CREATE FUNCTION rand_string(n INT)
RETURNS VARCHAR(255)  #该函数会返回一个字符串
BEGIN#定义了一个变量 chars_str, 类型 varchar(100)#默认给 chars_str 初始值 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ'DECLARE chars_str VARCHAR(100) DEFAULT'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';DECLARE return_str VARCHAR(255) DEFAULT ";DECLARE i INT DEFAULT 0;WHILE i <nDO# concat 函数 : 连接函数mysql函数SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));SET i =i +1;END WHILE;RETURN return_str;END $$#这里我们又自定了一个函数,返回一个随机的部门号
CREATE FUNCTION rand_num( )RETURNS INT(5)BEGINDECLARE i INT DEFAULT 0;SET i = FLOOR(10+RAND()*500);RETURN i;END $$#创建一个存储过程, 可以添加雇员
CREATE PROCEDURE insert_emp(IN STARTINT(10),IN max_num INT(10))BEGINDECLARE i INT DEFAULT 0;#set autocommit =0 把 autocommit 设置成 0#autocommit = 0 含义: 不要自动提交
SET autocommit = 0; #默认不提交sql 语句
REPEATSET i =i +1;#通过前面写的函数随机产生字符串和部门编号,然后加入到emp表
INSERT INTO emp VALUES ((START+i) ,rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num());UNTIL i = max_numEND REPEAT;#commit 整体提交所有sql语句,提高效率
COMMIT;END $$#添加8000000 数据
CALL insert_emp(100001,8000000)$$#命令结束符,再重新设置为;DELIMITER ;SELECT COUNT(*) FROM emp;-- 在没有创建索引时,我们的查询一条记录SELECT *FROM empWHERE empno = 1234567
-- 使用索引来优化一下, 体验索引的牛-- 在没有创建索引前 ,emp.ibd 文件大小 是 524m
-- 创建索引后 emp.ibd 文件大小 是 655m[索引本身也会占用空间.]
-- 创建ename列索引,emp.ibd 文件大小 是 827m-- empno_index 索引名称
-- ON emp (empno) : 表示在 emp表的 empno列创建索引
CREATE INDEX empno_index ON emp (empno)-- 创建索引后, 查询的速度如何SELECT *FROM empWHERE empno = 1234578  -- 0.003s 原来是4.5s-- 创建索引后,只对创建了索引的列有效
SELECT *FROM empWHERE ename ='PjDlwy' -- 没有在ename创建索引时,时间4.7sCREATE INDEX ename_index ON emp (ename)  -- 在 ename 上创建索引

1.31.2 索引的类型

1. 主键索引,主键自动的为主索引(类型Primary key)
2. 唯一索引(UNIQUE)
3. 普通索引(INDEX)
4. 全文索引(FULLTEXT)[适用于MyISAM] 一般开发,不使用mysql自带的全文索引,而是使用:全文搜索Solr和 ElasticSearch (ES)

create table t1 (
id int primary key,--主键,同时也是索引,称为主键索引.name varchar(32));
create table t2(
id int unique, -- id是唯一的,同时也是索引,称为unique索引.

1.31.3 索引使用

--演示mysql的索引的使用--创建索引
CREATE TABLE t25(id INT,`name` VARCHAR(32));--查询表是否有索引
SHOW INDEXES FROM t25;--添加索引
--添加唯一索引
CREATE UNIQUE INDEXid_index ON t25(id);--添加普通索引方式1CREATE INDEX id_index ON t25(id);
--如何选择
-- 1. 如果某列的值,是不会重复的,则优先考虑使用unique索引, 否则使用普通索引
-- 添加普通索引方式2ALTER TABLE t25 ADD INDEXid_index (id)-- 添加主键索引
CREATE TABLE t26 (id INT ,`name` VARCHAR(32));ALTER TABLE t26 ADD PRIMARY KEY(id)SHOW INDEX FROM t25-- 删除索引
DROP INDEX id_index ON t25  
-- 删除主键索引
ALTER TABLE t26 DROP PRIMARY KEY-- 修改索引 , 先删除,在添加新的索引-- 查询索引
-- 1. 方式
SHOW INDEX FROM t25
-- 2. 方式
SHOW INDEXES FROM t25
-- 3. 方式
SHOW KEYS FROM t25
-- 4 方式
DESC t25

1.31.4  小结: 哪些列上适合使用索引

1.32 mysql 事务

1.32.1 什么是事务

        事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败。如:转账 就要用事务来处理,用以保证数据的一致性。

1.32.2 事务和锁

        当执行事务操作时(dml语句) ,mysql会在表上加锁,防止其它用户改表的数据.这对用户来讲是非常重要的

--事务的一个重要的概念和具体操作
--看一个图[看示意图]
--演示
--1.创建一张测试表
CREATE TABLE t27(id INT,`name` VARCHAR(32));--2.开始事务
START TRANSACTION--3.设置保存点
SAVEPOINT a
--执行dml操作
INSERT INTO t27 VALUES(100, 'tom');SELECT * FROM t27;SAVEPOINT b
--执行dml操作
INSERT INTO t27 VALUES(200, 'jack');-- 回退到 bROLLBACK TO b
-- 继续回退 aROLLBACK TO a
-- 如果这样, 表示直接回退到事务开始的状态.ROLLBACKCOMMIT

1.32.3 回退事务

        在介绍回退事务前,先介绍一下保存点(savepoint).保存点是事务中的点.用于取消部分事务,当结束事务时(commit),会自动的删除该事务所定义的所有保存点当执行回退事务时,通过指定保存点可以回退到指定的点,

1.32.4 提交事务

        使用commit语句可以提交事务.当执行了commit语句子后,会确认事务的变化、结束事务、删除保存点、释放锁,数据生效。当使用commit语句结束事务子后,其它会话[其他连接]将可以查看到事务变化后的新数据 [所有数据就正式生效.]

1.32.5 事务细节讨论

1. 如果不开始事务,默认情况下,dml操作是自动提交的,不能回滚
2. 如果开始一个事务,你没有创建保存点.你可以执行 rollback,默认就是回退到你事务开始的状态.
3. 你也可以在这个事务中(还没有提交时),创建多个保存点.比如: savepoint aaa;执行dml , savepoint bbb;
4. 你可以在事务没有提交前,选择回退到哪个保存点.
5. mysql的事务机制需要innodb的存储引擎才可以使用,myisam不好使.
6. 开始一个事务start  transaction,  set  autocommit = off;

-- 讨论 事务细节--1.如果不开始事务,默认情况下,dml操作是自动提交的,不能回滚
INSERT INTO t27 VALUES(300, 'milan');  --自动提交commitSELECT * FROM t27--2.如果开始一个事务,你没有创建保存点.你可以执行rollback,
--默认就是回退到你事务开始的状态START TRANSACTIONINSERT INTO t27 VALUES (400, 'king');INSERT INTO t27 VALUES(500, 'scott');ROLLBACK  --表示直接回退到事务开始的的状态COMMIT;--3.你也可以在这个事务中(还没有提交时),创建多个保存点.比如:savepoint aaa;
-- 执行dml,savepoint bbb--4. 你可以在事务没有提交前,选择回退到哪个保存点
--5. InnoDB 存储引擎支持事务, MyISAM 不支持
--6. 开始一个事务start transaction, set autocommit = off;

1.33 mysql事务隔离级别

1.33.1 事务隔离级别介绍

1. 多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个连接在获取数据时的准确性。(通俗解释)
2. 如果不考虑隔离性,可能会引发如下问题:         脏读        不可重复读        幻读

1.33.2 查看事务隔离级别

脏读(dirty read): 当一个事务读取另一个事务尚未提交的改变(update,insert,delete)时,产生脏读
不可重复读(nonrepeatable read): 同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生不可重复读。
幻读(phantom read): 同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻读。

1.33.3 事务隔离级别

1.33.4 设置事务隔离级别

1. 查看当前会话隔离级别        select @ @ tx isolation;
2. 查看系统当前隔离级别        select @ @global.tx_isolation;
3. 设置当前会话隔离级别
set session transaction isolation level repeatable read;
4. 设置系统当前隔离级别
set global transaction isolation level repeatable read;
5. mysql 默认的事务隔离级别是repeatable read,一般情况下,没有特殊要求,没有必要修改(因为该级别可以满足绝大部分项目需求)

-- 演示mysql 的事务隔离级别-- 1. 开了两个mysql的控制台
-- 2. 查看当前mysql的隔离级别
SELECT @@tx_isolation;-- mysql> SELECT @@tx_isolation;
-- +-----------------+
-- | @@tx_isolation |
-- +-----------------+
-- | REPEATABLE-READ |
-- +------------------- 3.把其中一个控制台的隔离级别设置 Read uncommitted
SET SESSION TRANSACTION ISOLATION LEVELREAD UNCOMMITTED-- 4. 创建表
CREATE TABLE `account`(id INT,`name` VARCHAR(32),money INT);-- 查看当前会话隔离级别
SELECT @@tx_isolation
-- 查看系统当前隔离级别
SELECT @@ global.tx_isolation
-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVELREADUNCOMMITTED
-- 设置系统当前隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL[你设置的级别]

1.34 mysql 事务 ACID

1.34.1 事务的acid 特性

1. 原子性(Atomicity)
        原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2. 一致性(Consistency)
        事务必须使数据库从一个一致性状态变换到另外一个一致性状态
3. 隔离性(lsolation)
        事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
4. 持久性(Durability)
        持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

1.35 mysql 表类型和存储引擎

1.35.1 基本介绍

1. MySQL的表类型由存储引擎(Storage Engines)决定,主要包括MylSAM 、innoDB、Memory等。
2. MySQL 数据表主要支持六种类型,分别是:CSV、Memory、ARCHIVE、MRG_MYISAM、MYISAM、InnoBDB。
3. 这六种又分为两类,一类是”事务安全型”(transaction-safe),比如: InnoDB; 其余都属于第二类,称为”非事务安全型”(non-transaction-safe)[mysiam和memory].

1.35.2 主要的存储引擎/表类型特点

1.35.3 细节说明

1. MylSAM不支持事务、也不支持外键,但其访问速度快,对事务完整性没有要求
2. InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起 MylSAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。
3. MEMORY存储引擎使用存在内存中的内容来创建表。每个MEMORY表只实际对应
个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。但是一旦MySQL服务关闭,表中的数据就会丢失掉,表的结构还在。

1.35.4 三种存储引擎表使用案例

--表类型和存储引擎--查看所有的存储引擎
SHOW ENGINES
--innodb存储引擎,是前面使用过.
--1.支持事务    2.支持外键    3.支持行级锁--myisam存储引擎
CREATE TABLE t28(id INT,`name` VARCHAR(32)) ENGINE MYISAM
-- 1.添加速度快    2.不支持外键和事务    3.支持表级锁START TRANSACTION;SAVEPOINT t1INSERT INTO t28 VALUES (1, 'jack');SELECT * FROM t28;ROLLBACK TO t1-- memory 存储引擎
-- 1. 数据存储在内存中[关闭了Mysql服务,数据丢失, 但是表结构还在]
-- 2. 执行速度很快(没有IO读写)3. 默认支持索引(hash表CREATE TABLE t29 (id INT,`name` VARCHAR(32)) ENGINE MEMORYDESC t29INSERTINTO t29VALUES(1,'tom'), (2,'jack'), (3, 'zak');SELECT * FROM t29-- 指令修改存储引擎
ALTER TABLE `t29` ENGINE = INNODB

1.35.5 如何选择表的存储引擎

1. 如果你的应用不需要事务,处理的只是基本的CRUD操作,那么MylSAM 是不二选择,速度快
2. 如果需要支持事务,选择lnnoDB。
3. Memory存储引擎就是将数据存储在内存中,由于没有磁盘I./O的等待,速度极快。但由于是内存存储引擎,所做的任何修改在服务器重启后都将消失。(经典用法: 用户的在线状态().)

1.35.6 修改存储引擎

        ALTER TABLE  '表名'  ENGINE = 储存引擎;

1.36 视图(view)

1.36.1 基本概念

1. 视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含列,其数据来自对应的真实表(基表)
2. 视图和基表关系的示意图

1.36.2 视图的基本使用

1. create view视图名as select语句
2. alter view视图名as select语句 --更新成新的视图
3. SHoW CREATE VIEW 视图名
4. drop view视图名1,视图名2

--视图的使用
--创建一个视图emp_view01,只能查询emp表的(empno、ename,job和deptno)信息--创建视图
CREATE VIEW emp_view01ASSELECTempno, ename, job, deptno FROM emp;-- 查看视图
DESC emp_view01SELECT * FROM emp_view01;SELECT empno, job FROM emp_view01;-- 查看创建视图的指令SHOW CREATE VIEW emp_view01
-- 删除视图DROP VIEW emp_view01;-- 视图的细节-- 1. 创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式: 视图名.frm)
-- 2. 视图的数据变化会影响到基表,基表的数据变化也会影响到视图[insert update delete]-- 修改视图 会影响到基表UPDATE emp_view01SET job = 'MANAGER'WHERE empno = 7369SELECT * FROM emp; -- 查询基表SELECT  *FROM emp_view01
--修改基本表,会影响到视图UPDATE empSET job ='SALESMAN'WHERE empno = 7369--3.视图中可以再使用视图,比如从emp_view01视图中,选出empno,和ename做出新视图
DESC emp_view01CREATE VIEW emp_view02ASSELECT empno,ename FROM emp_view01SELECT * FROM emp_view02

1.36.3 视图细节讨论

1. 创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式:视图名.frm)
2. 视图的数据变化会影响到基表,基表的数据变化也会影响到视图[insert update delete ]
---准针对前面的雇员管理系统-----
mysql> create view myview as select empno ,ename , job, comm from emp;
mysql> select * from myview;
mysql> update myview set comm=200 where empno=7369;//修改视图,对基表都有变化
mysql> update emp set comm=100 where empno=7369;//修改基表,对视频也有变化
3. 视图中可以再使用视图,数据仍然来自基表..

1.36.4 视图最佳实践

1. 安全。一些数据表有着重要的信息。有些字段是保密的,不能让用户直接看到。这时就可以创建一个视图,在这张视图中只保留一部分字段。这样,用户就可以查询自己需要的字段,不能查看保密的字段。
2. 性能。关系数据库的数据常常会分表存储,使用外键建立这些表的之间关系。这时,数据库查询通常会用到连接(JOIN)。这样做不但麻烦,效率相对也比较低。如果建立一个视图,将相关的表和字段组合在一起,就可以避免使用JOIN查询数据。
3. 灵活。如果系统中有一张旧的表,这张表由于设计的问题,即将被废弃。然而,很多应用都是基于这张表,不易修改。这时就可以建立一张视图,视图中的数据直接映射到新建的表。这样,就可以少做很多改动,也达到了升级数据表的目的。

-- 视图的课堂练习
-- 针对 emp ,dept, 和 salgrade 张三表.创建一个视图 emp_view03,
-- 可以显示雇员编号,雇员名,雇员部门名称和 薪水级别[即使用三张表,构建一个视图]/*分析: 使用三表联合查询,得到结果将得到的结果,构建成视图*/
CREATE VIEW emp_view03ASSELECT empno, ename, dname, gradeFROM emp,dept, salgradeWHERE emp.deptno = dept.deptno AND(sal BETWEEN losalAND hisal)DESC emp_view03SELECT * FROM emp_view03

1.37 Mysql 管理

1.37.1 Mysql 用户

        mysql 中的用户,都存储在系统数据库mysql中user表中

其中user表的重要字段说明:
1. host: 允许登录的“位置”,localhost表示该用户只允许本机登录,也可以指定ip地址,
        比如:192.168.1.100
2. user:    用户名;
3. authentication_string: 密码,是通过mysql的password()函数加密之后的密码。

1.37.2 创建用户

create user ‘用户名’ @’ 允许登录位置’ identified by ‘密码’
说明: 创建用户,同时指定密码

1.37.3 删除用户

        drop user ‘用户名’ @ ’允许登录位置’;

1.37.4 用户修改密码

修改自己的密码:
set password = password(密码');
修改他人的密码(需要有修改用户密码权限):
set password for '用户名'@'登录位置' = password('密码');

1.37.5 mysql 中的权限

1.37.6  给用户授权

1.37.7 回收用户授权

基本语法:
revoke 权限列表 on 库.对象名 from  '用户名" @ "登录位置';

1.37.8 权限生效指令

如果权限没有生效,可以执行下面命令.
基本语法:        FLUSH  PRIVILEGES;

1.37.9 练习

-- 演示 用户权限的管理-- 创建用户 zak 密码 123, 从本地登录
CREATE USER 'zak' @ 'localhost' IDENTIFIED BY '123'-- 使用root 用户创建 testdb ,表 newsCREATE DATABASE testdbCREATE TABLE news(id INT ,content VARCHAR(32));-- 添加一条测试数据
INSERT INTO news VALUES(100, '北京新闻');SELECT * FROM news;-- 给 zak 分配查看 news 表和 添加news的权限
GRANT SELECT,INSERTON testdb.newsTO 'zak' @ 'localhost'-- 可以增加update权限
GRANT UPDATEON testdb.newsTO 'zak' @ 'localhost'-- 修改 zak 的密码为 abc
SET PASSWORD FOR 'zak' @ 'localhost' = PASSWORD('abc');--回收 zak 用户在testdb.news表的所有权限
REVOKE SELECT,UPDATE,INSERT ON testdb.news FROM 'zak' @ 'localhost'REVOKE ALL ON testdb.news FROM 'zak' @ 'localhost'--删除 zak DROP USER 'zak' @ 'localhost'

1.37.10 细节说明

1. 在创建用户的时候,如果不指定Host,则为%,%表示表示所有IP都有连接权限create user xXx;
2. 你也可以这样指定
create user 'xxx' @ '192.168.1.%’ 表示Xxx用户在192.168.1.* 的 ip 可以登录mysql
3. 在删除用户的时候,如果 host 不是%,需要明确指定‘用户 '@' host 值'

--说明用户管理的细节
--在创建用户的时候,如果不指定Host,则为%,%表示表示所有IP都有连接权限
--create user xxx;CREATE USER jackSELECT `host` , `user` FROM mysql.user--你也可以这样指定
--create user 'xxx'@'192.168.1.%'  表示xxx用户在192.168.1.* 的ip可以登录mysqlCREATE USER 'smith' @ '192.168.1.%'
-- 在删除用户的时候,如果 host 不是 %, 需要明确指定 '用户'@'host值'DROP USER jack
-- 默认就是 DROP USER 'jack' @ '%'DROP USER 'smith' @ '192.168.1.%'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/10869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手写Windows文件路径获取小工具

手写Windows文件路径获取小工具 目的 给Windows右键增加功能&#xff0c;右键任何文件&#xff08;夹&#xff09;显示复制文件路径的扩展。 效果展示 实现思路 右键调用&#xff0c;自身会把文件路径传递给被调用文件&#xff0c;被调用文件内只需将路径参数复制到剪贴板即…

个人微信api

简要描述&#xff1a; 退出群聊 请求URL&#xff1a; http://域名地址/quitChatRoom 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/json Authorization&#xff1a;login接口返回 参数&#xff1a; 参数名 必选 类型 …

中国当代最具影响力的人物颜廷利:死神(死亡)并不可怕,可怕的是…

中国当代最具影响力的人物颜廷利&#xff1a;死神&#xff08;死亡&#xff09;并不可怕&#xff0c;可怕的是… 在中国优秀传统文化之中&#xff0c;汉语‘巳’字与‘四’同音&#xff0c;在阿拉伯数字里面&#xff0c;通常用‘4’来表示&#xff1b; 作为汉语‘九’字&#x…

docker(二):Centos安装docker

文章目录 1、安装docker2、启动docker3、验证 官方文档&#xff1a;https://docs.docker.com/engine/install/centos/ 1、安装docker 下载依赖包 yum -y install gcc yum -y install gcc-c yum install -y yum-utils设置仓库 yum-config-manager --add-repo http://mirrors…

KAN 笔记

1 Title KAN: Kolmogorov–Arnold Networks&#xff08;Ziming Liu, Yixuan Wang, Sachin Vaidya, Fabian Ruehle, James Halverson, Marin Soljačić, Thomas Y. Hou, Max Tegmark&#xff09;【2024】 2 Conclusion Inspired by the Kolmogorov-Arnold representat…

5.10.3 使用 Transformer 进行端到端对象检测(DETR)

框架的主要成分称为 DEtection TRansformer 或 DETR&#xff0c;是基于集合的全局损失&#xff0c;它通过二分匹配强制进行独特的预测&#xff0c;以及 Transformer 编码器-解码器架构。 DETR 会推理对象与全局图像上下文的关系&#xff0c;以直接并行输出最终的预测集。 1. …

【Linux】-Linux的实用操作:快捷键与软件安装操作、构建软连接、日期时区的设置[4]

目录 一、各类小技巧&#xff08;快捷键&#xff09; 1、ctrl c 强制停止 2、ctrl d 退出或登出 3、历史命令搜索 4、光标移动快捷键 5、清屏 二、软件安装 1、yum命令 2、apt命令 - 扩展&#xff08;ubuntu&#xff09; 三、systemctl命令 四、软连接 1、ln命令…

【字符函数与字符串函数】

文章目录 一、strlen函数1.strlen函数的使用2.strlen函数的模拟实现(1)计算器办法(2)不创建临时变量计数器(3)指针 二、strcpy函数1、strcpy函数的使用2、strcpy函数的模拟实现 三、strcat函数1、strcat函数的使用2、strcat模拟实现3、字符串自己给自己追加&#xff1f; 四、st…

01-单片机商业项目编程,从零搭建低功耗系统设计

一、引言 这是关于《单片机商业编程之从零搭建低功耗系统》的第一篇章&#xff0c;个人善忘&#xff0c;平常项目设计当中的一些思路&#xff0c;以前年轻的时候习惯性的录制成视频&#xff0c;也算是当作是自己的笔记&#xff0c;无奈现在喉咙实在扛不住&#xff0c;因此先尝试…

德克萨斯大学奥斯汀分校自然语言处理硕士课程汉化版(第一周) - 自然语言处理介绍和线性分类

自然语言处理介绍和线性分类 1. 自然语言处理介绍2. 线性二分类3. 情感分析和基础特征提取 3.1. 情感分析3.2. 特征提取3.3. 文本预处理 4. 学习的基础-梯度下降算法5. 感知机6. 逻辑回归7. 情感分析8. 感知机和逻辑回归 1. 自然语言处理介绍 自然语言处理的目标是什么 能够解…

(2024,KAN,MLP,可训练激活函数,样条函数,分层函数)Kolmogorov–Arnold 网络

KAN: Kolmogorov–Arnold Networks 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 2. KAN 2.1 KA 表示定理 2.2 KAN 架构 2.3 KAN 的逼近能力和缩放定律 2.4 对于…

国产操作系统下使用dpkg命令管理软件包 _ 统信 _ 麒麟 _ 中科方德

往期好文&#xff1a;国产操作系统下Chrome的命令行使用 | 统信 | 麒麟 Hello&#xff0c;大家好啊&#xff01;在Linux系统中&#xff0c;dpkg是Debian包管理系统的基础命令工具&#xff0c;它允许用户安装、卸载、查询和管理软件包。在国产操作系统如统信UOS和麒麟KOS、中科方…

字节码基础

基本概念 java中的字节码&#xff0c;英文bytecode。是java代码编译后的中间代码格式。JVM需要读取并解析字节码才能执行相应的任务。java字节码是JVM的指令集。JVM加载字节码格式的class文件。校验之后通过JIT编译器转换成本机机器代码执行。 java字节码简介 1、java byteco…

阿里云部署ChatGLM-6B及ptuning微调教程

一、模型部署 1.进入阿里云人工智能平台PAI。 2.申请免费试用。 3.打开交互式建模 PAI-DSW。 4.新建实例。 5.填写配置。 6.实例准备完成后点击打开。 7.打开实例后点击Teminal。 8.在Teminal中依次输入以下命令并执行。 apt-get update apt-get install git-lfs git lfs ins…

SQLite利用事务实现批量插入(提升效率)

在尝试过SQLite批量插入一百万条记录&#xff0c;执行时长高达20多分钟后&#xff0c;就在想一个问题&#xff0c;这样的性能是不可能被广泛应用的&#xff0c;更不可能出现在真实的生产环境中&#xff0c;那么对此应该如何优化一下呢&#xff1f; 首先分析一下批量插入的逻辑 …

蓝桥杯-地宫取宝

X 国王有一个地宫宝库&#xff0c;是 nm 个格子的矩阵&#xff0c;每个格子放一件宝贝&#xff0c;每个宝贝贴着价值标签。 地宫的入口在左上角&#xff0c;出口在右下角。 小明被带到地宫的入口&#xff0c;国王要求他只能向右或向下行走。 走过某个格子时&#xff0c;如果那个…

网络工程师----第二十四天

计算机基础 第一章&#xff1a;概述 互联网的组成&#xff1a; &#xff08;1&#xff09;边缘部分&#xff1a;由所有连接在互联网上的主机组成。这部分是用户直接使用的&#xff0c;用来进行通信&#xff08;传送数据、音频或视频&#xff09;和资源共享。 &#xff08;2…

Python大数据分析——Logistic回归模型

Logistic回归模型 概念理论分析模型评估混淆矩阵ROC曲线KS曲线 函数示例 概念 之前的回归的变量是连续的数值变量&#xff1b;而Logistics回归是二元离散值&#xff0c;用来解决二分类问题。 理论分析 上式中的hβ(X)也被称为Loqistic回归模型&#xff0c;它是将线性回归模型…

2-1 EXTI外部中断(gd32)

中断的概念 中断硬件结构/软件结构 EXTI中断 EXTI硬件结构 注&#xff1a;EXTI线在同一时刻只能连接一个GPIO口&#xff0c;如果我们先连接了PA0,然后又连接了PB0那么此时PA0这个IO口就失去作用。 中断触发函数 中断优先级 中断优先级 数值越小优先级越高&#xff0c;抢占优先级…

247 基于matlab的梁的振型仿真

基于matlab的梁的振型仿真。利用有限元理论&#xff0c;求二维梁的固有频率和振型。短边固定&#xff0c;给定长度、横截面积&#xff0c;弹性模量及材料密度已知。并对比理论计算结果进行分析。各参数自己设定。程序已调通&#xff0c;可直接运行。 247 梁的振型仿真 固有频率…