【】一天速通_狠狠MySQL_20230801_实际用了三天

数据是信息的原料,那数据从哪里来?谁在生产数据?我拿出了镜子。20230801

【】一天速通_狠狠MySQL_20230801_实际用了三天_第1张图片

一天复习完_狠狠sql20230725

复习笔记。sql领进门,修行靠个人。
感谢遇见狂神说。
mark{ background: transparent; color: red;}

新建的就把这敲上去

1、初识MySQL

  • JavaEE : 企业级Java开发 Web
  • 前端 (页面:展示,数据!)
  • 后台(连接点:;连接数据库JDBC,链接前端 (控制,控制视图跳转,和给前端传递数据))
  • 数据库(存数据,Txt,Excel,word)
  • 只会写代码,学好数据库,基本混饭吃!
  • 操作系统,数据结构与算法! 当一个不错的程序猿!
  • 离散数学,数字电路,体系结构,编译原理。 + 实战经验,高级程序猿优秀的程序猿

去IOE:
是阿里巴巴造出的概念。其本意是,在阿里巴巴的IT架构中,去掉IBM的小型机、Oracle数据库、EMC存储设备,代之以自己在开源软件基础上开发的糸统。

1.1、为什么学习数据库

1、岗位需求
2、现在的世界,大数据时代~,得数据库者得天下
3、被迫需求: 存数据
数据库是所有软件体系中最核心的存在 DBA

1.2、什么是数据库

数据库 (database) 保存有组织的数据的容器(通常是一个文 件或一组文件)。

数据库(DB,DataBase)
概念:数据仓库,软件,安装在操作系统(window,linux, mac、…)之上! SQL,可以存储大量的数据。500万!
作用: 存储数据,管理数据

1.3、数据库分类

关系型数据库: (SQL)

MySQL,Oracle,Sql Server,DB2, SOLlite
通过表和表之间,行和列之间的关系进行数据的存储,
学员信息表,考勤表,…。

非关系型数据库:(NosQL) Not Only
Redis,MongDB
。非关系型数据库,对象存储,通过对象的自身的属性来决定

DBMS(数据库管理系统)

数据库的管理软件,科学有效的管理我们的数据,维护和获取数据
MySQL,数据库管理系统!
数据库软件应称为数据库管理系统 (或DBMS )。 数据库是通过DBMS创建和操纵的。数据库可以是保存在硬设 备上的文件,但也可以不是。在很大程度上说,数据库究竟 是文件还是别的什么东西并不重要,因为你并不直接访问数 6
据库; 你使用的是DBMS,它为你访问数据库

1.4、MySQL简介

MySQL是一个关系型数据库管理系统
前世: 瑞典MySQL AB 公司
今生: 属于 Oracle 旗下产品
MySQL是最好的 RDBMS(Relational Database Management System,关系数据库管理系统)应用软件之一。开软的数据库软件~
体积小、速度快、总体拥有成本低,招人成本比较低,所有人必须会中小型网站、或者大型网站,集群!
官网: https://www.mysql.com
5.7 稳
8.0

表 (table)某种特定类型数据的结构化清单。

表是 一种结构化的文件,可用 来存储某种特定类型的数据。表可以保存顾客清单、产品目录,或者其 他信息清单。表 (table)某种特定类型数据的结构化清单。
这里关键的 一点在于,存储在表中的数据是 一种类型的数据或一个 清单。

模式(schema) 关于数据库和表的布局及特性的信息。

列 (c o l o m n ) 表 中 的 一 个 字 段 。所 有 表 都 是 由 一 个 或 多 个 列 组 成的。

理解列的最好办法是将数据库表想象为 一个网格。网格中每一列存 储着一条特定的信息。例如,在顾客表中, 一个列存储着顾客编号,另 一个列存储着顾客名,而地址、城市、州以及邮政编码全都存储在各自 的列中。
//数据库是3D的,

分解数据

正确地将数据分解为多个列极为重要。例如,城市、 州、邮政编码应该总是独 立的列。通过把它分解 开,才有可能 利用特定的列对数据进行分类和过滤(如,找出特定州或特定 城市的所有顾客)。

数据类型 (datatype)

所容许的数据的类型。每个表列都有相 应的数据类型, 它限制 ( 或容许)该列中存储的数据。

数据类型兼容

数据类型及其名称是SQL不兼容的一个主要原因。虽然大多数数据类型得到一致的支持,但许多更为高 级的数据类型却不是这样。 更糟的是,我们偶然会发现相同的数据类型在不同的DBMS中具有不同的名称。

行 (r o w ) 表 中 的 一 个 记 录 。

行 表中的数据是按行存储的;所保存的每个记录存储在自己的行内。 如果将表想象为网格,网格中垂直的列为表列,水平行为表行。 例如,顾客表可以每行存储一个顾客。表中的行编号为记录的编号。

主 键 ( p r i m a r y k e y ) ! 一列 (或 一 组 列 ), 其 值 能 够 唯 一标 识 表 中 每个行。

主 键 表中每 一行都应该有可以唯一标识自己的一列(或一组列)。一个顾 客表可以将顾客ID编号用于此目的,而包含订单的表可以使用订单D 。雇 员表可以使用雇员ID或雇员社会保险号
唯一标识表中每行的这个列 (或这组列)称为主键。 主键用米表示 一个特定的行。没有主键,更新或删除表中特定行很困难,因为没有安 全的方法保证只涉及相关的行。

表中的任何列都可以作为主键,只要它满足以下条件(身份正号):
又 任意两行都不具有相同的 主键值;
又 每 个 行 都 必 须 具 有 一 个 主 键 值 ( 主键 列 不 允 许 N U L L 值 ) ;
又 主键列中的值不允许修改或更新;
又 主键值不能重用 (如果某行从表中删除,它的 主键不能赋给以后 的新行)。
还有 一种非常重要的键,称为外键。

什么是S QL

SQL ( 发音为字母S-Q-L或sequel ) 是结构化查询语言( Struc tured Query Language) 的 缩 写 。 S Q L 是 一种 专 门 用 来 与 数 据 库 通 信 的 语 言 。
设计SQL的目的是很好地完 成一项任务一—提供一种从数据库中读写数据的简单有效的方法。

SQL 有如 下的优点:

又SOL 不是某个特定数据库供应商专有的语言。几乎所有重要的 DBMS都支持sQL,所以,学习此语言使你几乎能与所有数据库 打交道。
又SQL 简单易学。它的语句全都是由有很强描述性的英语单词组成, 而且这些单词的数目不多。
又 S Q L 尽 管 看 上 去 很 简 单 , 但 它 实 际 上 是 一种 强 有 力 的 语 言 , 灵 活 使用其语言元素, 可以进行非常复杂和高级的数据库操作。

SQL的扩展

许多DBMS供应商通过增加语句或指令,对SQL 进行了扩展 。这种扩展的目的是提供执行特定採作的额外功能 或简化方法。 虽然这种扩展很有用,但 一般都是针对个别 DBMS的,很少有两个以上的供应商支持这种扩展。 标准SQL由ANSI标准委员会管理,从而称为ANSI SQL。所有主 要的DBMS ,即使有自己的扩展,但都支持ANSI SQL。各个实 现有自己的名称,如PL/ SQL、Transact-SQL•等。 本书讲投的SQL主要是ANSI SQL。在使用某种DBMS特定的 SQL时,将会进行说明。

样例表脚本

编写SQL 语句需要对基本的数据库设计:有良好的理解。不知道什么信 息存放在什么表中,表与表之间如何互相关联,以及行中数据如何分解, 要编写高效的SQL是不可能的。

表确实示范了现实世界中你将 遇到的各种数据的组织和关系。

1 目标任务:

又 管理供应商;
又 管理产品目录;
又 管理客户列表;
又 录入客户订单。
完成它们需要5个表 (它们作为一个关系数据库设计的组成部分紧密关联)。

表的描述
vendors 表

存储卖产品的供应商。每个供应商在这个表中有 一个记 录,供应商ID列(vend_id)用于产品与供应商的匹配。
表A-1 Vendors表的

说明
vend id 唯一的供应商ID
vend name 供应商名
vend_address 供应商的地址
vend_city 供应商的城市
vend_state 供应商的州
vend_z i p 供应商的邮政编码
vend_country 供应商的国家

又所有表都应该有主键。这个表应该用vend_id作为它的主键。

Products表

Products表包含产品目录,每行一个产品。每个产品有唯一的D (prod_id列),并且借助vend_id (供应商的唯一D)与供应商相关联。
表A-2 Products表的列

说明
prod_id 唯一的产品ID
vend_id|产品供应商ID(关联到Vendors表的vend_id)
prod_name|产品名
prod_price |产品价格
prod_desc| 产品描迏
又 所 有 表 都 应 该 有 主键 。 这 个 表 应 该 用 p r o d _ i d 作 为 它 的 主键 。
又 为实施引用完整性,应该在vend_id 上定义一个外键,关联它到 Vendors的vend_id列。
c u s t o me r s 表

customers 表存储所有客户信息。每个客户有唯一的ID (cust_id列)。
表A-3 customers表的列

说明
cust_id 唯 一的客户ID
cust_name 客户名
cust_address 客户的地址
cust_city
cust_state
cust_zip
cust_country
cust_contact
cust_email 客户的联系电子邮件地址

又 所 有 表 都 应 该 有 主键 。 这 个 表 应 该 用cust_id作 为 它 的 主键 。

orders表

orders 表存储客户订单(但不是订单细书)。每个订单唯一地进行编号(order_num列)。Orders表按cust_id列(关联到Customers表的 客户唯一ID )关联到相应的客户。

说明|
order num 唯一的订单号
order_date |订单日期
cust_id|订单客户ID 〈定义一个外 键,关联到Customers表的cust_i d )

又 所有表都应该有主键。这个表应该用order_num作为它的主键。
又 为 实 施 引 用 完 整 性 , 应 该 在 cust_id 上 定 义 一个 外 键 , 关 联 它 到Customers的cust_id

OrderItems 表

OrderItems表存储每个订单中的实际物品,每个订单的每个物品一行。对于 Orders表的每一行,在OrderItems表中有一行或多行。每个订单物品由订单号加订单物品(第一个物品、第二个物品等)唯 一标识。订单物品用Order_num列 (关 联 到orders表中订单的唯一ID) 与 其 相 应 的订单相关联。此外,每个订单物品包含该物品的产品D (把物品关联 到 P r o d u c t s表 )。

表A-5 OrderItems表的列

说明
order_num 订单号(关联到Orders表的order num)
order item 订单物品号(订单内的顺序)
prod id 产品ID(关联到Products表prod_id)
quantity 物品数量
item_price 物品价格

所有表都应该有主键。这个表应该用order_num和or der_item 作 为 它 的 主键 。
又为实施引用完整性,应该在order_num和prod_id上定义外键,关联order_num到orders的order_num列,关联prod_id到
products的prod_id列。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ik8TUj5-1690871892970)(media/16902699991057/16905223036572.jpg)]
数据库 xxx 语言 CRUD 增删改查!(业务!)CV 程序猿API程序猿CRUD 程序猿!
DDL 定义
DML 操作
DQL查询
DCL控制

2、操作数据库

2.1 操作数据库(了解)

contrl +R 执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-haN1BWsv-1690871892971)(media/16902699991057/16906099399829.jpg)]

2.2数据库的列类型

数值
整数
  • tinyint 十分小的数据 1个字节
  • smallint 较小的数据2个字节
  • mediumint 中等大小的数据 3个字节
  • int 标准的整数4个字节常用的
  • bigint 较大的数据 8个字节
浮点数

float 4个字节

double 浮点数 8个字节
(精度问题!)
decimal字符串形式的浮点数(金融计算 )

字符串
  • char 字符串固定大小的 0~255
  • varchar 可变字符串 0~65535
    常用的变量String
  • tinytext 微型文本
    2^8 -1
  • text 文本串 2^16-1保存大文本
时间日期

java.util.Date

  • dateYYYY-MM-DD,日期格式
  • timeHH: mm: ss 时间格式
  • datetime YYYY-MM-DD HH: mm: ss i最常用的时间格式
  • timestamp 时间戳, 1970.1.1 到现在的毫秒数!
  • year 年份表示
null

null
没有值,未知0
注意,不要使用NULL进行运算,结果为NULL

2.3数据库的字段属性

不能为负 无符号 unsigned

无符号的整数 不能为负的整数 如年龄
声明了该列不能声明为负数

自动递增/ 自增:
  • 通常理解为自增,自动在上一条记录的基础上 + 1 (默认)
  • 0通常用来设计唯一的主键~ index,必须是整数类型
  • 可以自定义设计主键自增的起始值和步长
非空 NUIl not null

假设设置为 not null ,如果不给它赋值,就会报错!o。NUII ,如果不填写值,默认就是null!

零填充 zerofill

0填充的
不足的位数,使用0来填充
int(3) ,5 —> 005

navicat里面没有填充0,但事实上已经填充了,可以在命令窗口查看【select * from 表名】

乐观锁

是通过不加锁的方式来处理资源,就是CAS,比较并替换

每一个表,都必须存在以下五个字段!
  • 主键id
  • 乐观锁versionis
  • 伪删除delete
  • 创建时间gmt creategmt
  • 修改时间update
`` 表示字符串,防止不小心表明与Mysql的关键字冲突

2.4创建数据库表(重点)

建一个schoo1数据库
创建学生表(列,字段)

使用sQL
创建学号int
登录密码varchar(20)
姓名,
性别varchar(2),
出生日期(datatime),
家庭住址,email

注意点,使用英文 ()括起来,表的名称 和_字段 尽量使用AUTO INCREMENT字符由使用 单引号括起来!

所有的语句后面加,(英文的),最后一个不用加PRIMARY KEY

CREATE TABLE IF NOT EXISTS `teacher`(
`id`   INT(4)  NOT NULL  comment '学号',
`name`  VARCHAR(30) NOT NULL DEFAULT '匿名' comment  '姓名' ,
`pwd`     VARCHAR(20)   NOT NULL DEFAULT  '12345'  comment '密码',
`sex`  VARCHAR(2)  NOT NULL DEFAULT '女 ' 	comment 	'性别',
`birthday`     DATETIME   DEFAULT NULL comment  
 '出生日期',
`address`  VARCHAR(100) DEFAULT  NULL comment 	'家庭住址',
`email`  VARCHAR(50) DEFAULT  NULL comment 	'邮箱',
PRIMARY KEY(`id`)
) engine=innodb default charset=utf8

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P1IW8IZU-1690871892971)(media/16902699991057/16906159288351.jpg)]

2.5 数据表的类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33iP1hK3-1690871892971)(media/16902699991057/16906169170457.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0k1T2S2c-1690871892972)(media/16902699991057/16906178620537.jpg)]

1 查看创建数据库的语句:

添加一个字段

SHOW TABLE STATUS LIKE 'class'
ALTER TABLE `class`
ADD COLUMN `gender`  varchar(30) BINARY CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'futa' AFTER `name`




mysql> show create database school;


CREATE DATABASE `school` 

/*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ 
2 查看创建数据表的定义语句:

show CREATE TABLE student;

3 显示表结构

DESC pet;

2.6 修改删除表 字段

添加一个字段:

1.传统派思想 反复造轮子
MySQL 除了允许在表的开头位置和末尾位置添加字段外,还允许在中间位置(指定的字段之后)添加字段,此时需要使用

AFTER 关键字,语法格式如下: ALTER TABLE <表名> ADD <新字段名> <数据类型> [约束条件] AFTER <已经存在的字段名>;

SHOW TABLE STATUS LIKE 'class'

--精准操作 
ALTER TABLE `class`
ADD COLUMN `gender`  varchar(30) BINARY CHARACTER 
SET utf8mb4 COLLATE utf8mb4_general_ci 
NULL DEFAULT 
 'futa' AFTER `name`


2、革新派 祖传的轮子
CREATE DATABASE SChoo1 --否看创建数据虚的语句SHOW TABLE student – 查看student数据表的定义语何SHOW CREATEstudent – 显示表的结构DESC

修改表结构
添加新列:
ALTER TABLE table_name
ADD column_name data_type;
修改列定义:
ALTER TABLE table_name
MODIFY column_name new_data_type;
修改列名称:
ALTER TABLE table_name
CHANGE old_column_name new_column_name data_type;
删除列:
ALTER TABLE table_name
DROP column_name;

-- 修改表名 ALTER TABLE 旧表名 RENAME AS 新表名ALTER TABLE teacher RENAME AS teacher1
-- 增加表的字段 ALTER TABLE 表名 ADD 字段名 列属性ALTER TABLE teacher1 ADD age INT(11)
修改表的字段 (重命名,修改约束!)修改约束ALTER TABLE teacherl MODIFY age VARCHAR(11)字段重名名TABLE teacher1 CHANGE age age1 INT(1)ALTER
删除表的字段
ALTER TABLE teacherl DROP age1
删除表如果表存在再删除)DROP TABLE IF EXISTS teacher1

3、MySQL数据管理

3.1 外键(了解即可)

工作中确实也不会使用外键。包括在阿里的JAVA规范中也有下面这 条
[强制]不得使用外键与级联,一切外键概念必须在应用层解决。
但是呢,询问他们原因,大多是这么回答的
每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便。

添加约束

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFIJ3drj-1690871892972)(media/16902699991057/16906196934321.jpg)]

--添加主键:
ALTER TABLE table_name
ADD PRIMARY KEY (column_name);
--添加外键:
ALTER TABLE table_name
ADD FOREIGN KEY (column_name) REFERENCES referenced_table(ref_column_name);
--
ALTER TABLE student
ADD CONSTRAINT FK_gradeid' FOREIGN KEY( gradeid") REFERENCES grade ( gradeid);

--添加唯一约束:
ALTER TABLE table_name
ADD CONSTRAINT constraint_name UNIQUE (column_name);

删除外键约束:keyName是外键别名
ALTER TABLE tableName DROP FOREIGN KEY keyName;

物理外键,数据库级别的外键,我们不建议使用!(避免数据库过多造成困扰)
**最佳实践:
**数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)

3.2 DML语言(全部记住)增删改

查DQL:data query language 数据查询语言

查询 从零开始

mysql> SELECT * FROM class LIMIT 0, 0;

Empty set

mysql> SELECT * FROM class LIMIT 0, 1;

1 row in set

INSERT INTO table_name ( field1, field2,...fieldN )
                       VALUES
                       ( value1, value2,...valueN );




3.3 添加

--插入语句(添加)
insert into 表名([字段名1,字段2,字段3])values('值1'),('值2'),('值3',...

INSERT INTO grade ( gradename') VALUES('大四')
-- 由于主键自增我们可以省略 (如果不写表的字段,他就会一一匹配)不为空的值,除非设定自增,否则 必须填写

INSERT INTO grade’VALUES('大三')
-- 一般写插入语句,我们一定要数据和字段一一对应!
-- 插入多个字段
INSERT INTO `grade` (`gradename `)VALUES('大二'),('大一');

INSERT INTO `student`(`name`) VALUES ('张三');

INSERT INTO `student`(`name`,`pwd`,`sex`) VALUES ('张三','aaaaaa','');

INSERT INTO `student`(`name`,`pwd`,`sex`) VALUES ('李四','aaaaaa',''),('王五','aaaaaa',"男');

语法insert into 表名([字段名1,字段2,字段3])values(值1),(“值2”),(值3’,…)

3.4 修改

MySQL UPDATE 更新
1.传统派 反复造轮子

--极简在表中的某个字段后面的位置,新插入一个字段
ALTER TABLE `class`
ADD COLUMN `email`  varchar(30)  
 AFTER `gender`;
 
 
--增加了很多约束情况 
SHOW TABLE STATUS LIKE 'class'

ALTER TABLE `class`
ADD COLUMN `gender`  varchar(30) BINARY CHARACTER 
SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'futa' AFTER `name`


UPDATE `class` SET `gender` = '女女女女' ; 
 

```sql
UPDATE `table_name` SET field1=new-value1, field2=new-value2
[WHERE id= 32 ]
--你可以同时更新一个或多个字段。
--你可以在 WHERE 子句中指定任何条件。
--你可以在一个单独表中同时更新数据。
--当你需要更新数据表中指定行的数据时 WHERE 子句是非常有用的。
-- 修改学员名字,带了简介
UPDATE student'SET name ='狂神'WHERE id = 1;
-- 不指定条件的情况下,会改动所有表!
UPDATE student'SETname'='长江7-- 修改多个属性,逗号隔开
UPDATE student'SET name'='野火烧不尽',email'='2443@qq.com' WHERE id = 1;
语法:


UPDATE `class` SET  	`name`='mawenjie'  WHERE  id = 32;

UPDATE 表名 set colnum_name = value,where [条件]
WHERE 子句

我们知道从 MySQL 表中使用 SQL SELECT 语句来读取数据。
如需有条件地从表中选取数据,可将 WHERE 子句添加到 SELECT 语句中。

where语法

查:
以下是 SQL SELECT 语句使用 WHERE 子句从数据表中读取数据的通用语法:
**SELECT field1, field2,…fieldN FROM table_name1, table_name2…
[WHERE condition1 [AND [OR]] condition2…
**查询语句中你可以使用一个或者多个表,表之间使用逗号, 分割,并使用WHERE语句来设定查询条件。

  • 可以在 WHERE 子句中指定任何条件。
  • 可以使用 AND 或者 OR 指定一个或多个条件。
    WHERE 子句也可以运用于 SQL 的 DELETE 或者 UPDATE 命令。
  • WHERE 子句类似于程序语言中的 if 条件,根据 MySQL 表中的字段值来读取指定的数据。
为操作符列表,可用于 WHERE 子句中。

下表中实例假定 A 为 10, B 为 20

between 2 and 5; [2,5]
AND

操作符 描述 实例
= 等号,检测两个值是否相等,如果相等返回true (A = B) 返回false。
<>, != 不等于,检测两个值是否相等,如果不相等返回true (A != B) 返回 true。
: > 大于号,检测左边的值是否大于右边的值, 如果左边的值大于右边的值返回true (A > B) 返回false。
< 小于号,检测左边的值是否小于右边的值, 如果左边的值小于右边的值返回true (A < B) 返回 true。
: >= 大于等于号,检测左边的值是否大于或等于右边的值, 如果左边的值大于或等于右边的值返回true (A >= B) 返回false。
<= 小于等于号,检测左边的值是否小于或等于右边的值, 如果左边的值小于或等于右边的值返回true (A <= B) 返回 true。

BETWEEN … and …|在某个范围内 [2,5]
AND |我和你 && 5>1 and 1>2

OR|我或你 5>1 or 1>2

false
true

--从命令提示符中读取数据
--我们将在SQL SELECT语句使用WHERE子句来读取MySQL数据表 runoob_tbl 中的数据:
--实例
--以下实例将读取 runoob_tbl 表中 runoob_author 字段值为 Sanjay 的所有记录:
SQL SELECT WHERE 子句
SELECT * from runoob_tbl WHERE runoob_author='教程';
输出结果:

-- MySQL 的 WHERE 子句的字符串比较是不区分大小写的。 你可以使用 BINARY 关键字来设定 WHERE 子句的字符串比较是区分大小写的。
-- 实例中使用了 BINARY 关键字,是区分大小写的,所以 runoob_author='runoob.com' 的查询条件是没有数据的。

-- 通过多个条件定位数据
UPDATE student'SET name'='长江7号'WHERE name='狂神44'AND sex='女
语法:
UPDATE 表名 set colnum name = value, [colnum name
where [条件]
注意:
colnum name 是数据库的列,尽量带上
。条件,筛选的条件,如果没有指定,则会修改所有的列
value,是一个具体的值,也可以是一个变量
。多个设置的属性之间,使用英文逗号隔开
1 UPDATE student’SET birthday'= CURRENT_TIME WHERE name'='长江7' AND sex='女'



3.5删除

3.5.1 MySQL 删除数据表
MySQL中删除数据表是非常容易操作的,但是你在进行删除表操作时要非常小心,因为执行删除命令后所有数据都会消失。
语法
以下为删除MySQL数据表的通用语法:
DROP TABLE table_name ;

在命令提示窗口中删除数据表
在mysql>命令提示窗口中删除数据表SQL语句为 DROP TABLE :
实例
以下实例删除了数据表runoob_tbl:
root@host# mysql -u root -p
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> DROP TABLE runoob_tbl;
Query OK, 0 rows affected (0.8 sec)
mysql>

3,5,2 删除表中的数据
MySQL DELETE 语句
你可以使用 SQLDELETE FROM 命令来删除 MySQL 数据表中的记录。
你可以在 mysql> 命令提示符或 PHP 脚本中执行该命令。
语法
以下是 SQL DELETE 语句从 MySQL 数据表中删除数据的
通用语法:

DELETE FROM table_name [WHERE Clause]
如果没有指定 WHERE 子句,MySQL 表中的所有记录将被删除。



你可以在 WHERE 子句中指定任何条件
您可以在单个表中一次性删除记录。
当你想删除数据表中指定的记录时 WHERE 子句是非常有用的。



从命令行中删除数据
这里我们将在 SQL DELETE 命令中使用 WHERE 子句来删除 MySQL 数据表 runoob_tbl 所选的数据。
实例
以下实例将删除 runoob_tbl 表中 runoob_id 为3 的记录:



DELETE 语句:
mysql> use RUNOOB;
Database changed
mysql> DELETE FROM runoob_tbl WHERE runoob_id=3;
Query OK, 1 row affected (0.23 sec)
delete 的 TRUNCATE
相同点:都能删除数据,都不会除表结构
不同:
  • TRUNCATE重新设置 自增列 计数器会归零。

  • TRUNCATE 不会影响事务

  • 测试delete 和 TRUNCATE 区别

CREATE TABLEtest (
id'INT(4) NOT NULL AUTO_INCREMENTCo11VARCHAR(20) NOT NULL,PRIMARY KEY Cid')
)ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO test'('co11) VALUES('1'),('2'),('3')
-- 不会影响自增DELETE FROM test’
-- 自增会归零TRUNCATE TABLE test

了解即可:
重启数据库,现象DELETE删除的问题
InnoDB自增列会重1开始(存在内存当中的,断电即失。MyISAM 继续从上一个自增量开始 (存在文件中的,不会丢失)

4、DQL查询数据(最重点)

4.1 DQL Data Query Language 数据查询语言

DQL( Data Query Language 数据查询语言 )

  • 查询数据库数据 , 如SELECT语句

  • 简单的单表查询或多表的复杂查询和嵌套查询

  • 是数据库语言中最核心,最重要的语句

  • 使用频率最高的语句

1 到目前为止SQL执行顺序:
where/group by/ having/order by/limit

使用DQL查询数据
DQL语言

2 select 完整的语法:
SELECT
[ALL | DISTINCT]
FROM
WHERE
GROUP BY
HAVING
ORDER BY
LIMIT {[offset,]row_count | row_countOFFSET offset}];
– 指定查询的记录从哪条至哪条
SELECT [ALL | DISTINCT]
{* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]}
FROM table_name [as table_alias]
  [left | right | inner join table_name2]  -- 联合查询
  [WHERE ...]  -- 指定结果需满足的条件
  [GROUP BY ...]  -- 指定结果按照哪几个字段来分组
  [HAVING]  -- 过滤分组的记录必须满足的次要条件
  [ORDER BY ...]  -- 指定查询记录按一个或多个条件排序
  [LIMIT {[offset,]row_count | row_countOFFSET offset}];
   -- 指定查询的记录从哪条至哪条
注意 : [ ] 括号代表可选的 , { }括号代表必选得


SELECT语法

4.2 指定查询字段/取别名/拼接字符串

1 AS 子句作为别名
-- 查询表中所有的数据列结果 , 采用 **" \* "** 符号; 但是效率低,不推荐 .

-- 查询所有学生信息
SELECT * FROM student;

-- 查询指定列(学号 , 姓名)
SELECT studentno,studentname FROM student;


SELECT student.studentno, student.studentname FROM student


AS 子句作为别名
作用:

可给数据列取一个新别名

可给表取一个新别名

可把经计算或总结的结果用另一个新名称来代替

-- 这里是为列取别名(当然as关键词可以省略)
SELECT studentno AS 学号,studentname AS 姓名 FROM student;

-- 使用as也可以为表取别名
SELECT studentno AS 学号,studentname AS 姓名 FROM student AS s;

-- 使用as,为查询结果取一个新名字
-- CONCAT()函数拼接字符串
SELECT CONCAT('姓名:',studentname) AS 新姓名 FROM student;

select CONCAT('亲爱的:',studentName,'桑') AS 
新名字 From student; 





2 DISTINCT关键字的使用

作用 : 去掉SELECT查询返回的记录结果中重复的记录 ( 返回所有列的值都相同 ) , 只返回一条

-- # 查看哪些同学参加了考试(学号) 去除重复项


SELECT * FROM result; -- 查看考试成绩
SELECT studentno FROM result; -- 查看哪些同学参加了考试
SELECT DISTINCT studentno FROM result; -- 了解:DISTINCT 去除重复项 , (默认是ALL)


-- selcet查询中可以使用表达式
SELECT @@auto_increment_increment; -- 查询自增步长
SELECT VERSION(); -- 查询版本号
SELECT 100*3-1 AS 计算结果; -- 表达式
3 使用 表达式的列 即可以使用数学表达式
数据库中的表达式 : 一般由文本值 , 列值 , NULL , 函数和操作符等组成

应用场景 :

SELECT语句返回结果列中使用

SELECT语句中的ORDER BY , HAVING等子句中使用

DML语句中的 where 条件语句中使用表达式



-- 学员考试成绩集体提分一分查看
SELECT studentno,StudentResult+1 AS '提分后' FROM result;
避免SQL返回结果中包含 ' . ' , ' * ' 和括号等干扰开发语言程序.


4.3where条件语句

作用:用于检索数据表中 符合条件 的记录
搜索条件可由一个或多个逻辑表达式组成 , 结果一般为布尔值:真或假.

1 逻辑操作符
运算符 语法 描述
and && a and b a&& b 逻辑与,两个都为真,结果为真
or || a or b a || b 逻辑或,其中一个为真,则结果为真
Not ! not a !a 逻辑非,真为假,假为真!

-- 满足条件的查询(where)
SELECT Studentno,StudentResult FROM result;

-- 查询考试成绩在95-100之间的
SELECT Studentno,StudentResult
FROM result
WHERE StudentResult>=95 AND StudentResult<=100;

-- AND也可以写成 &&
SELECT Studentno,StudentResult
FROM result
WHERE StudentResult>=95 && StudentResult<=100;

-- 模糊查询(对应的词:精确查询)
SELECT Studentno,StudentResult
FROM result
WHERE StudentResult BETWEEN 95 AND 100;

-- 除了1000号同学,要其他同学的成绩
SELECT studentno,studentresult
FROM result
WHERE studentno!=1000;

-- 使用NOT
SELECT Studentno,StudentResult FROM result
WHERE  Not studentresult BETWEEN 95 AND 100;


SELECT studentno,studentresult
FROM result
WHERE NOT studentno=1000;

模糊查询
1 比较操作符 _ %

注意:
数值数据类型的记录之间才能进行算术运算 ;

相同数据类型的数据之间才能进行比较 ;

测试:

-- 模糊查询 between and \ like \ in \ null

-- =============================================
-- LIKE
-- =============================================
-- 查询姓张的同学的学号及姓名
-- like结合使用的通配符 : % (代表0到任意个字符) _ (一个字符)
SELECT studentno,studentname FROM student
WHERE studentname LIKE '张%';



SELECT student.studentno, student.studentname  FROM `student`WHERE  student.studentname   LIKE '张%';


-- 查询姓张的同学,后面只有一个字的

select student.studentno,student.studentname  from student where student.studentname like '张_';

-- 查询姓张的同学,后面只有两个字的
SELECT studentno,studentname FROM student
WHERE studentname LIKE '张__';

-- 查询姓名中含有 嘉 字的同学的学生号码

SELECT studentno,studentname FROM student
WHERE studentname LIKE '%嘉%';

--任意字符 嘉 任意字符 

-- 查询仅名字中含有 嘉 字的同学的学生号码和性别 

--任意一位字符(默认姓为一位) 嘉 任意字符 


select student.studentno,student.sex,student.studentname FROM student WHERE studentname LIKE  '_%嘉%' ;


select student.studentno , student.studentname FROM student WHERE studentname LIKE  '%嘉%';





-- 查询姓名中含有特殊字符的需要使用转义符号 '\'
-- 自定义转义符关键字: ESCAPE ':'


2 IN 真实存在的、具体的一个或者多个值


-- IN 具体的一个或者多个值 
-- 查询学号为1000,1001,1002的学生姓名
SELECT studentno,studentname FROM student
WHERE studentno IN (1000,1001,1002);

-- 查询地址在北京,南京,河南洛阳的学生

SELECT studentno,studentname,address FROM student
WHERE address IN ('北京','南京','河南洛阳');


select * FROM student;
SELECT student.studentno,student.studentname from student where address IN ('北京朝阳');
3 NULL 空 查询出生日期没有填写的同学
-- 查询出生日期没有填写的同学
-- 不能直接写=NULL , 这是代表错误的 , 用 is null
SELECT studentname FROM student WHERE BornDate IS NULL;






4 查询有出生日期的同学 不为空
-- 查询出生日期填写的同学
SELECT studentname FROM student
WHERE BornDate IS NOT NULL;

-- 查询没有写家庭住址的同学(空字符串不等于null)

SELECT student.studentno,student.studentname from student where address ='';
SELECT student.studentno,student.studentname from student where address ='' OR address IS NULL; 
SELECT studentname FROM student
WHERE Address='' OR Address IS NULL;

4.4 联表查询 JOIN

1 连接查询

如需要多张数据表的数据进行查询,则可通过连接运算符实现多个查询

  • 内连接 inner join
    查询两个表中的结果集中的交集

  • 外连接 outer join

  • 左外连接 left join 左连接就是查询左表全部数据和右表的交集部分
    (以左表作为基准,右边表来一一匹配,匹配不上的,返回左表的记录,右表以NULL填充)
    就返回行会从左表中返回所有的值,即使右表中没有匹配

  • 右外连接 right join
    (以右表作为基准,左边表来一一匹配,匹配不上的,返回右表的记录,左表以NULL填充)
    会从右表中返回所有的值,即使左表中没有

思考题 (查询了参加考试的同学信息: 学号,学生姓名,科目名,分数)
思路

  • 1.分析需求,分析查询的字段来自哪些表,student、result、subject (连接查询)
  • 2.确定使用哪和连接否询?
  • 3。确定交叉点(这两个表中哪个数据是相同的)判断的条件 :学生表的中 studentNo = 成绩表 studentNo
    SEIECT s.studentNo,studentName,SubjectName,StudentResultFROM student sRIGHT JOIN result r
    ON r.studentNo = s.studentNo
    INNER JOIN*subjectsub
    ON r.SubjectNo = sub .SubjectNo
  • 我要查询哪些数据 select
  • 从那几个表中查 EROM 表xXX Join 连接的表 on 交叉条件
  • 假设存在一种多张表查询,慢慢来,先查询两张表然后再慢慢增加
    七种Join:

MySQL 连接的使用
在前几章节中,我们已经学会了如何在一张表中读取数据,这是相对简单的,但是在真正的应用中经常需要从多个数据表中读取数据。
本章节我们将向大家介绍如何使用 MySQL 的 JOIN 在两个或多个表中查询数据。

你可以在 SELECT, UPDATE 和 DELETE 语句中使用 Mysql 的 JOIN 来联合多表查询。
JOIN 按照功能大致分为如下三类:
INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。

  • 只要有公共数据(冗余数据)即可连表查询
  • 内连接;是共同相同的时候,链接显示
  • 左连接 是 左边完全返回,右边和他对应的放过法
  • 右连接 右边全部返回 左边相同的对应过去(左边没办法对应的为 NULL)
  • 全连接,左右两边都返回,且能一一对应的 直接连接,无法对应的部分设为空
  • 已经有了连接的值《有的为空)我就等着你需要select 即查询什么了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kxSPe5y9-1690871892972)(media/16902699991057/16907052613850.jpg)]

本章节使用的数据库结构及数据下载:runoob-mysql-join-test.sql。

在命令提示符中使用 INNER JOIN
我们在RUNOOB数据库中有两张表 tcount_tbl 和 runoob_tbl。两张数据表数据如下:

mysql> Database changed
mysql> SELECT * FROM tcount_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鸟教程  | 10           |
| RUNOOB.COM    | 20           |
| Google        | 22           |
+---------------+--------------+
3 rows in set (0.01 sec)
 
mysql> SELECT * from runoob_tbl;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title  | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 1         | 学习 PHP    | 菜鸟教程  | 2017-04-12      |
| 2         | 学习 MySQL  | 菜鸟教程  | 2017-04-12      |
| 3         | 学习 Java   | RUNOOB.COM    | 2015-05-01      |
| 4         | 学习 Python | RUNOOB.COM    | 2016-03-06      |
| 5         | 学习 C      | FK            | 2017-04-05      |
+-----------+---------------+---------------+-----------------+
5 rows in set (0.01 sec)


接下来我们就使用MySQL的INNER JOIN(也可以省略 INNER 使用 JOIN,效果一样)来连接以上两张表来读取runoob_tbl表中所有runoob_author字段在tcount_tbl表对应的runoob_count字段值:
INNER JOIN
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程    | 10             |
| 2           | 菜鸟教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
+-------------+-----------------+----------------+
4 rows in set (0.00 sec)
以上 SQL 语句等价于:
WHERE 子句
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a, tcount_tbl b WHERE a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程    | 10             |
| 2           | 菜鸟教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
+-------------+-----------------+----------------+
4 rows in set (0.01 sec)

MySQL LEFT JOIN
MySQL left joinjoin 有所不同。 MySQL LEFT JOIN 会读取左边数据表的全部数据,即使右边表无对应数据。
实例
尝试以下实例,以 runoob_tbl 为左表,tcount_tbl 为右表,理解 MySQL LEFT JOIN 的应用:
LEFT JOIN
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a LEFT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程         | 10             |
| 2           | 菜鸟教程         | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| 5           | FK              | NULL           |
+-------------+-----------------+----------------+
5 rows in set (0.01 sec)
以上实例中使用了 LEFT JOIN,该语句会读取左边的数据表 runoob_tbl 的所有选取的字段数据,即使在右侧表 tcount_tbl中 没有对应的 runoob_author 字段值。

MySQL RIGHT JOIN
MySQL RIGHT JOIN 会读取右边数据表的全部数据,即使左边边表无对应数据。
实例
尝试以下实例,以 runoob_tbl 为左表,tcount_tbl 为右表,理解MySQL RIGHT JOIN的应用:
RIGHT JOIN
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a RIGHT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程         | 10             |
| 2           | 菜鸟教程         | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| NULL        | NULL            | 22             |
+-------------+-----------------+----------------+
5 rows in set (0.01 sec)
以上实例中使用了 RIGHT JOIN,该语句会读取右边的数据表 tcount_tbl 的所有选取的字段数据,即使在左侧表 runoob_tbl 中没有对应的runoob_author 字段值。




2 连表查询 与聚合查询
* 到目前为止SQL执行顺序:
where/group by/ having/order by/limit
先 筛选 / 分组 /条件/排序/限制筛选

**where >=< 通配符 条件 like 筛选
group by 分组
having 对分组后的聚合条件 进行搜索
order by 结果排序
limit 得到想要的值 **

GROUP BY 语法:

SELECT column1, column2, …, aggregate_function(columnX)
FROM table_name
GROUP BY column1, column2, …;


SELECT age,COUNT(id) FROM info WHERE id > 2 GROUP BY age HAVING COUNT(id) > 1 ORDER BY age DESC LIMIT 1;
--要查询的表info
--条件 id>2
--根据age分组
--对分组后的数据再根据聚合条件过滤 count( id)>1
--根据age从大到小排序
--获取第1条


--把表2。runoob_tbl,根据字段 runoob_author进行分组,并数每一组的数量。


SELECT * FROM tcount_tbl;
--展示表1 
SELECT * from runoob_tbl;
--展示表2 count(聚合)
select  runoob_author,COUNT(runoob_author) from runoob_tbl  GROUP BY runoob_author;
--在表2中查询,根据 runoob_author 字段分组, 并数数,查询并展示不同组的runoob_author 和 分别有几个组员



--在表2中查询,根据 runoob_author 字段分组, 并数数,查询并展示不同组的runoob_author 和 分别有几个组员


mysql> select  runoob_author,COUNT(runoob_author)
from runoob_tbl  GROUP BY runoob_author HAVING count(runoob_author)<2 ;


--使用 HAVING 而非WHERE 因为 执行顺序不一样  先group by 分组 再 进行条件清洗。再进行排序 再进行 限制筛选 

 
+---------------+----------------------+
| runoob_author | COUNT(runoob_author) |
+---------------+----------------------+
| FK            |                    1 |
+---------------+----------------------+
1 row in set







+---------------+----------------------+
| runoob_author | COUNT(runoob_author) |
+---------------+----------------------+
| 菜鸟教程       |                    2 |
| RUNOOB.COM    |                    2 |
| FK            |                    1 |
+---------------+----------------------+

左外连接 右外连接 是否是主表影响
--tab2为主表 ,以tab2的数据为主,tab1的数据为辅,1来匹配2,2 无FK 则  2不认识1的FK 则给1个 NULL 。
select  tab2.runoob_author,tab2.runoob_id,tab2.runoob_title ,tab1.runoob_like
from tab2 LEFT OUTER JOIN tab1 ON tab2.runoob_author =tab1.runoob_author ;



+---------------+-----------+--------------+-------------+
| runoob_author | runoob_id | runoob_title | runoob_like |
+---------------+-----------+--------------+-------------+
| 菜鸟教程      |         1 | 学习 PHP     | 优先        |
| 菜鸟教程      |         2 | 学习 MySQL   | 优先        |
| RUNOOB.COM    |         3 | 学习 Java    | 不知道      |
| RUNOOB.COM    |         4 | 学习 Python  | 不知道      |
| FK            |         5 | 学习 C       | NULL        |
+---------------+-----------+--------------+-------------+


--tab1为主表 ,以tab1的数据为主,tab2的数据为辅,2来匹配1,1从2中得不到有效数据给FK  则 全部设置为 NULL 。

select  tab2.runoob_author,tab2.runoob_id,tab2.runoob_title ,tab1.runoob_like
from tab1 LEFT OUTER JOIN tab2 ON tab2.runoob_author =tab1.runoob_author ;

+---------------+-----------+--------------+-------------+
| runoob_author | runoob_id | runoob_title | runoob_like |
+---------------+-----------+--------------+-------------+
| 菜鸟教程      |         2 | 学习 MySQL   | 优先        |
| 菜鸟教程      |         1 | 学习 PHP     | 优先        |
| RUNOOB.COM    |         4 | 学习 Python  | 不知道      |
| RUNOOB.COM    |         3 | 学习 Java    | 不知道      |
| NULL          | NULL      | NULL         | 一般        |
+---------------+-----------+--------------+-------------+

3 连接

– 查询参加了考试的同学信息(学号,学生姓名,科目编号,分数)
SELECT * FROM student;
SELECT * FROM result;

/*思路:
(1):分析需求,确定查询的列来源于两个类,student result,连接查询
(2):确定使用哪种连接查询?(内连接)
*/

innerjoin :内链接 特定条件下的交集




```sql

SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
右连接(也可实现)
--AS 可以省略 
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
RIGHT JOIN result r
ON r.studentno = s.studentno

--  where 等值连接
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s , result r
WHERE r.studentno = s.studentno

-- on 左连接 (查询了所有同学,不考试的也会查出来)
--where 可以对on条件里面查询的内容再次进行过滤
--on用于批量 where用于单个
--on 不会筛选主表信息,where会筛选主表信息
--如果在left或right join后使用where条件子句,那么它的效果和inner就一样了,不再是left,right join  where再inner join中可以用,但不能用在left和right join

SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
LEFT JOIN result r
ON r.studentno = s.studentno

-- 查一下缺考的同学(左连接应用场景)
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
LEFT JOIN result r
ON r.studentno = s.studentno
WHERE StudentResult IS NULL

-- 思考题:查询参加了考试的同学信息(学号,学生姓名,科目名,分数)
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON sub.subjectno = r.subjectno

自连接

核心思想:把一张表看成两张一模一样的表,然后将这两张表连接查询(自连接)

/*
自连接
   数据表与自身进行连接

需求:从一个包含栏目ID , 栏目名称和父栏目ID的表中
    查询父栏目名称和其他子栏目名称
*/

-- 创建一个表
CREATE TABLE `category` (
`categoryid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主题id',
`pid` INT(10) NOT NULL COMMENT '父id',
`categoryName` VARCHAR(50) NOT NULL COMMENT '主题名字',
PRIMARY KEY (`categoryid`)
) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

-- 插入数据
INSERT INTO `category` (`categoryid`, `pid`, `categoryName`)
VALUES('2','1','信息技术'),
('3','1','软件开发'),
('4','3','数据库'),
('5','1','美术设计'),
('6','3','web开发'),
('7','5','ps技术'),
('8','2','办公信息');

-- 编写SQL语句,将栏目的父子关系呈现出来 (父栏目名称,子栏目名称)
-- 核心思想:把一张表看成两张一模一样的表,然后将这两张表连接查询(自连接)
SELECT a.categoryName AS '父栏目',b.categoryName AS '子栏目'
FROM category AS a,category AS b
WHERE a.`categoryid`=b.`pid`

-- 思考题:查询参加了考试的同学信息(学号,学生姓名,科目名,分数)
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON sub.subjectno = r.subjectno

-- 查询学员及所属的年级(学号,学生姓名,年级名)
SELECT studentno AS 学号,studentname AS 学生姓名,gradename AS 年级名称
FROM student s
INNER JOIN grade g
ON s.`GradeId` = g.`GradeID`

-- 查询科目及所属的年级(科目名称,年级名称)
SELECT subjectname AS 科目名称,gradename AS 年级名称
FROM SUBJECT sub
INNER JOIN grade g
ON sub.gradeid = g.gradeid

-- 查询 数据库结构-1 的所有考试结果(学号 学生姓名 科目名称 成绩)
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
WHERE subjectname='数据库结构-1'

4排序和分页 order by
测试

/*============== 排序 ================
语法 : ORDER BY
   ORDER BY 语句用于根据指定的列对结果集进行排序。
   ORDER BY 语句默认按照ASC升序对记录进行排序。
   如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。
   
*/

-- 查询 数据库结构-1 的所有考试结果(学号 学生姓名 科目名称 成绩)
-- 按成绩降序排序
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
WHERE subjectname='数据库结构-1'
ORDER BY StudentResult DESC
5 分页 limit

–数据库表中: 1000条数据
第一页: select * from info limit 10 offset 0;
第二页: select * from info limit 10 offset 10;
第二页:
select * from info limit 10 offset 20;
第二页: select * from info limit 10 offset 30;

select * from info limit 5;
-- 获取前5条数据

select * from info order by id desc limit 3;
-- 先排序,再获取前3条数据

select * from info where id > 4 order by id desc limit 3;
-- 先排序,再获取前3条数据
select *from info limit 3 offset 2;
-- 从位置2开始,向后获取前3数据

语法 : SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset

/*============== 分页 ================
语法 : SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
好处 : (用户体验,网络传输,查询压力)

推导:
   第一页 : limit 0,5
   第二页 : limit 5,5
   第三页 : limit 10,5
   ......
   第N页 : limit (pageNo-1)*pageSzie,pageSzie
   [pageNo:页码,pageSize:单页面显示条数]
   
*/

-- 每页显示5条数据
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
WHERE subjectname='数据库结构-1'
ORDER BY StudentResult DESC , studentno
LIMIT 0,5

-- 查询 JAVA第一学年 课程成绩前10名并且分数大于80的学生信息(学号,姓名,课程名,分数)
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
WHERE subjectname='JAVA第一学年'
ORDER BY StudentResult DESC
LIMIT 0,10


【6】子查询 WHERE条件句中嵌套了另一个查询

在查询语句中的WHERE条件子句中,又嵌套了另一个查询语句
嵌套查询可由多个子查询组成,求解的方式是由里及外;
子查询返回的结果一般都是集合,故而建议使用IN关键字;
*/

-- 查询 数据库结构-1 的所有考试结果(学号,科目编号,成绩),并且成绩降序排列
-- 方法一:使用连接查询
SELECT studentno,r.subjectno,StudentResult
FROM result r
INNER JOIN `subject` sub
ON r.`SubjectNo`=sub.`SubjectNo`
WHERE subjectname = '数据库结构-1'
ORDER BY studentresult DESC;

-- 方法二:使用子查询(执行顺序:由里及外)
SELECT studentno,subjectno,StudentResult
FROM result
WHERE subjectno=(
   SELECT subjectno FROM `subject`
   WHERE subjectname = '数据库结构-1'
)
ORDER BY studentresult DESC;

-- 查询课程为 高等数学-2 且分数不小于80分的学生的学号和姓名
-- 方法一:使用连接查询
SELECT s.studentno,studentname
FROM student s
INNER JOIN result r
ON s.`StudentNo` = r.`StudentNo`
INNER JOIN `subject` sub
ON sub.`SubjectNo` = r.`SubjectNo`
WHERE subjectname = '高等数学-2' AND StudentResult>=80

-- 方法二:使用连接查询+子查询
-- 分数不小于80分的学生的学号和姓名
SELECT r.studentno,studentname FROM student s
INNER JOIN result r ON s.`StudentNo`=r.`StudentNo`
WHERE StudentResult>=80

-- 在上面SQL基础上,添加需求:课程为 高等数学-2
SELECT r.studentno,studentname FROM student s
INNER JOIN result r ON s.`StudentNo`=r.`StudentNo`
WHERE StudentResult>=80 AND subjectno=(
   SELECT subjectno FROM `subject`
   WHERE subjectname = '高等数学-2'
)

-- 方法三:使用子查询
-- 分步写简单sql语句,然后将其嵌套起来
SELECT studentno,studentname FROM student WHERE studentno IN(
   SELECT studentno FROM result WHERE StudentResult>=80 AND subjectno=(
       SELECT subjectno FROM `subject` WHERE subjectname = '高等数学-2'
  )
)

/*
练习题目:
   查 C语言-1 的前5名学生的成绩信息(学号,姓名,分数)
   使用子查询,查询郭靖同学所在的年级名称
*/
图片

视频同步更新
如果觉得帮助到了您,不妨赞赏支持一下吧!
图片
图片

微信扫一扫
关注该公众号




```sql

这是一条SQL查询语句,它的目的是从名为 "teacher" 的数据库表中选择所有列,并按照 "start_date" 列的升序(ASC)进行排序,然后限制结果返回一行(LIMIT 1)。

请注意,这里的 "teacher" 是假设的表名,实际使用时需要根据数据库中的表名进行替换。此查询将返回 "teacher" 表中 "start_date" 最早的一行数据。




/*这条SQL查询语句的目的是从名为 "student" 的数据库表中选择所有列,但只返回满足条件的 "age" 列值为 17、18 或 19 的最多5行数据。

该查询使用了 WHERE 子句来指定筛选条件,并使用 IN 关键字来匹配 "age" 列中符合条件的值。IN 关键字用于指定一个值列表,如果列的值与列表中的任何值匹配,就会被包括在查询结果中。
*/

SELECT * FROM student WHERE age IN (17, 18, 19) LIMIT 5;




/*

student AS s 和 id_card AS ic 是为了给表起别名,简化查询语句。
JOIN 关键字用于联接两个表,将它们通过共同的 "card_id" 字段连接在一起。
ON s.card_id = ic.card_id 指定联接条件,它告诉数据库如何匹配 "student" 表中的 "card_id" 和 "id_card" 表中的 "card_id"。



 IN 关键字时,它用于指定一个值列表,用于在查询结果中筛选列值匹配该列表中的任何值的行。
 
 IN语法:

SELECT column1, column2, ...
FROM table_name
WHERE columnX IN (value1, value2, value3, ...);


WHERE ic.age IN (17, 18, 19) 用于筛选 "id_card" 表中 "age" 值为 17、18 或 19 的行。
SELECT s.* 表示选择 "student" 表中的所有列。
这样,查询将返回前5个年龄为17、18或19岁的学生信息。

*/


SELECT s.*
FROM student AS s
JOIN id_card AS ic          ON s.card_id = ic.card_id
WHERE ic.age IN (17, 18, 19)
LIMIT 5;

SELECT c.*, s.*, t.*, ss.*
FROM course c
JOIN student_score ss ON c.course_id = ss.course_id
JOIN student s ON ss.student_id = s.student_id
JOIN teacher t ON c.teacher_id = t.teacher_id;

SQL查询使用了多个表的连接(JOIN),将 course 表、student_score 表、student 表和 teacher 表连接在一起。这样可以获取到课程、学生成绩、学生和教师的相关信息。

在这个查询中,JOIN 关键字用于将表连接在一起,关联条件通过 ON 子句指定。这个查询使用了多个 JOIN,所以它将会返回四个表中相关联的数据。

假设您的数据库中的表结构如下:

course 表:存储课程信息,包括 course_id、teacher_id等字段。
student_score 表:存储学生成绩信息,包括 student_id、course_id、grade等字段。
student 表:存储学生信息,包括 student_id、name等字段。
teacher 表:存储教师信息,包括 teacher_id、name等字段。
以下是您的查询的结果列,它将返回所有课程、学生成绩、学生和教师的相关信息:

c.:返回课程表中的所有列。
s.
:返回学生表中的所有列。
t.:返回教师表中的所有列。
ss.
:返回学生成绩表中的所有列。

SELECT  card_id, name, address,
    CASE sex   WHEN 0 THEN '男'WHEN 1 THEN '女' else ''
    END AS 性别,
age
FROM  id_card;


SQL查询使用了 CASE 表达式,CASE 表达式是在SQL中用于根据条件返回不同值的功能。

CASE
    WHEN condition1 THEN result1
    WHEN condition2 THEN result2
    ...
    ELSE result_default
END

将性别字段的值转换为 “男” 和 “女”,并返回身份证表中的部分信息,包括 card_id、name、address、转换后的性别(使用中文“性别”),以及 age。

在您的查询中,CASE 表达式用于根据 sex 字段的值返回不同的性别信息。当 sex 为 0 时,返回 “男”,当 sex 为 1 时,返回 “女”,否则返回空字符串。查询结果中的性别列将被赋予中文“性别”作为列名。

这样,查询将返回身份证表中的指定字段,并且性别字段的值将被转换为 “男” 和 “女”,未知性别将显示为空字符串。

SELECT CONCAT(card_id, ' ', name, ' ', 
              CASE
                  WHEN sex = '0' THEN '男'
                  WHEN sex = '1' THEN '女'
                  ELSE '未知'
              END,
              ' ', age, ' ', address) AS ID_INFO
FROM id_card;

SQL查询使用了 CONCAT 函数和 CASE 表达式,将身份证表中的多个字段合并为一个包含所有信息的字符串,并且将性别字段的值转换为 “男” 和 “女”。

在您的查询中,CONCAT 函数用于将多个字段的值连接为一个字符串。CASE 表达式用于根据 sex 字段的值返回不同的性别信息,将 0 转换为 “男”,将 1 转换为 “女”,其他值返回 “未知”。

查询结果中的 ID_INFO 列将包含身份证的所有信息,包括空格分隔的 card_id、name、转换后的性别、age 和 address。

这样,查询将返回包含所有信息的身份证字符串,其中性别字段的值已经被转换为 “男” 和 “女”。

5 常用函数

5.1数据函数

SELECT ABS(-8); /绝对值/
SELECT CEILING(9.4); /向上取整/
SELECT FLOOR(9.4); /向下取整/
SELECT RAND(); /随机数,返回一个0-1之间的随机数/
SELECT SIGN(0); /符号函数: 负数返回-1,正数返回1,0返回0/

5.2 字符串函数

SELECT CHAR_LENGTH(‘狂神说坚持就能成功’); /返回字符串包含的字符数/
SELECT CONCAT(‘我’,‘爱’,‘程序’); /合并字符串,参数可以有多个/
SELECT INSERT(‘我爱编程helloworld’,1,2,‘超级热爱’); /替换字符串,从某个位置开始替换某个长度/
SELECT LOWER(‘KuangShen’); /小写/
SELECT UPPER(‘KuangShen’); /大写/
SELECT LEFT(‘hello,world’,5); /从左边截取/
SELECT RIGHT(‘hello,world’,5); /从右边截取/
SELECT REPLACE(‘狂神说坚持就能成功’,‘坚持’,‘努力’); /替换字符串/
SELECT SUBSTR(‘狂神说坚持就能成功’,4,6); /截取字符串,开始和长度/
SELECT REVERSE(‘狂神说坚持就能成功’); /*反转

– 查询姓周的同学,改成邹
SELECT REPLACE(studentname,‘周’,‘邹’) AS 新名字
FROM student WHERE studentname LIKE ‘周%’;

5.3 日期和时间函数

SELECT CURRENT_DATE(); /获取当前日期/
SELECT CURDATE(); /获取当前日期/
SELECT NOW(); /获取当前日期和时间/
SELECT LOCALTIME(); /获取当前日期和时间/
SELECT SYSDATE(); /获取当前日期和时间/

– 获取年月日,时分秒
SELECT YEAR(NOW());
SELECT MONTH(NOW());
SELECT DAY(NOW());
SELECT HOUR(NOW());
SELECT MINUTE(NOW());
SELECT SECOND(NOW());

5.4系统信息函数

SELECT VERSION(); /版本/
SELECT USER(); /用户/

5.5 聚合函数

函数名称 描述
COUNT() 返回满足Select条件的记录总和数,如 select count(*)
【不建议使用 *,效率低】
SUM() 返回数字字段或表达式列作统计,返回一列的总和。
AVG() 通常为数值字段或表达列作统计,返回一列的平均值
MAX() 可以为数值字段,字符字段或表达式列作统计,返回最大的值。
MIN() 可以为数值字段,字符字段或表达式列作统计,返回最小的值。

– 1 聚合函数

/COUNT:非空的/
SELECT COUNT(studentname) FROM student;
SELECT COUNT(*) FROM student;
SELECT COUNT(1) FROM student; /推荐/

– 从含义上讲,count(1) 与 count() 都表示对全部数据行的查询。
– count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。
– count(
) 包括了所有的列,相当于行数,在统计结果的时候,包含字段为null 的记录;
– count(1) 用1代表代码行,在统计结果的时候,包含字段为null 的记录 。
/*
很多人认为count(1)执行的效率会比count()高,原因是count()会存在全表扫描,而count(1)可以针对一个字段进行查询。其实不然,count(1)和count(*)都会对全表进行扫描,统计所有记录的条数,包括那些为null的记录,因此,它们的效率可以说是相差无几。而count(字段)则与前两者不同,它会统计该字段不为null的记录条数。

下面它们之间的一些对比:

1)在表没有主键时,count(1)比count()快
2)有主键时,主键作为计算条件,count(主键)效率最高;
3)若表格只有一个字段,则count(
)效率较高。
*/

SELECT SUM(StudentResult) AS 总和 FROM result;
SELECT AVG(StudentResult) AS 平均分 FROM result;
SELECT MAX(StudentResult) AS 最高分 FROM result;
SELECT MIN(StudentResult) AS 最低分 FROM result;
题目:

– 查询不同课程的平均分,最高分,最低分
– 前提:根据不同的课程进行分组

SELECT subjectname,AVG(studentresult) AS 平均分,MAX(StudentResult) AS 最高分,MIN(StudentResult) AS 最低分
FROM result AS r
INNER JOIN subject AS s
ON r.subjectno = s.subjectno
GROUP BY r.subjectno
HAVING 平均分>80;

/*
where写在group by前面.
要是放在分组后面的筛选
要使用HAVING…
因为having是从前面筛选的字段再筛选,而where是从数据表中的>字段直接进行的筛选的
*/

6 MD5 加密

一、MD5简介

MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。

二、实现数据加密

新建一个表 testmd5

CREATE TABLE testmd5 (
id INT(4) NOT NULL,
name VARCHAR(20) NOT NULL,
pwd VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8
插入一些数据

INSERT INTO testmd5 VALUES(1,‘kuangshen’,‘123456’),(2,‘qinjiang’,‘456789’)
如果我们要对pwd这一列数据进行加密,语法是:

update testmd5 set pwd = md5(pwd);
如果单独对某个用户(如kuangshen)的密码加密:

INSERT INTO testmd5 VALUES(3,‘kuangshen2’,‘123456’)
update testmd5 set pwd = md5(pwd) where name = ‘kuangshen2’;
插入新的数据自动加密

INSERT INTO testmd5 VALUES(4,‘kuangshen3’,md5(‘123456’));
查询登录用户信息(md5对比使用,查看用户输入加密后的密码进行比对)

SELECT * FROM testmd5 WHERE name=‘kuangshen’ AND pwd=MD5(‘123456’);

函数小结

– ================ 内置函数 ================
– 数值函数
abs(x) – 绝对值 abs(-10.9) = 10
format(x, d) – 格式化千分位数值 format(1234567.456, 2) = 1,234,567.46
ceil(x) – 向上取整 ceil(10.1) = 11
floor(x) – 向下取整 floor (10.1) = 10
round(x) – 四舍五入去整
mod(m, n) – m%n m mod n 求余 10%3=1
pi() – 获得圆周率
pow(m, n) – m^n
sqrt(x) – 算术平方根
rand() – 随机数
truncate(x, d) – 截取d位小数

– 时间日期函数
now(), current_timestamp(); – 当前日期时间
current_date(); – 当前日期
current_time(); – 当前时间
date(‘yyyy-mm-dd hh:ii:ss’); – 获取日期部分
time(‘yyyy-mm-dd hh:ii:ss’); – 获取时间部分
date_format(‘yyyy-mm-dd hh:ii:ss’, ‘%d %y %a %d %m %b %j’); – 格式化时间
unix_timestamp(); – 获得unix时间戳
from_unixtime(); – 从时间戳获得时间

– 字符串函数
length(string) – string长度,字节
char_length(string) – string的字符个数
substring(str, position [,length]) – 从str的position开始,取length个字符
replace(str ,search_str ,replace_str) – 在str中用replace_str替换search_str
instr(string ,substring) – 返回substring首次在string中出现的位置
concat(string [,…]) – 连接字串
charset(str) – 返回字串字符集
lcase(string) – 转换成小写
left(string, length) – 从string2中的左边起取length个字符
load_file(file_name) – 从文件读取内容
locate(substring, string [,start_position]) – 同instr,但可指定开始位置
lpad(string, length, pad) – 重复用pad加在string开头,直到字串长度为length
ltrim(string) – 去除前端空格
repeat(string, count) – 重复count次
rpad(string, length, pad) --在str后用pad补充,直到长度为length
rtrim(string) – 去除后端空格
strcmp(string1 ,string2) – 逐字符比较两字串大小

– 聚合函数
count()
sum();
max();
min();
avg();
group_concat()

– 其他常用函数
md5();
default();

6、事务和索引

事务

什么是事务

事务就是将一组SQL语句放在同一批次内去执行

如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行

MySQL事务处理只支持InnoDB和BDB数据表类型

事务的ACID原则:
原子性(Atomic)

整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(ROLLBACK)到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性(Consist)

一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性。

隔离性(Isolated)

隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。

持久性(Durable)

在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

基本语法
– 使用set语句来改变自动提交模式
SET autocommit = 0; /关闭/
SET autocommit = 1; /开启/

– 注意:
— 1.MySQL中默认是自动提交
— 2.使用事务时应先关闭自动提交

– 开始一个事务,标记事务的起始点
START TRANSACTION

– 提交一个事务给数据库
COMMIT

– 将事务回滚,数据回到本次事务的初始状态
ROLLBACK

– 还原MySQL数据库的自动提交
SET autocommit =1;

– 保存点
SAVEPOINT 保存点名称 – 设置一个事务保存点
ROLLBACK TO SAVEPOINT 保存点名称 – 回滚到保存点
RELEASE SAVEPOINT 保存点名称 – 删除保存点

测试

/*
课堂测试题目

A在线买一款价格为500元商品,网上银行转账.
A的银行卡余额为2000,然后给商家B支付500.
商家B一开始的银行卡余额为10000

创建数据库shop和创建表account并插入2条数据
*/

CREATE DATABASE shopCHARACTER SET utf8 COLLATE utf8_general_ci;
USE shop;

CREATE TABLE account (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL,
cash DECIMAL(9,2) NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO account (name,cash)
VALUES(‘A’,2000.00),(‘B’,10000.00)

– 转账实现
SET autocommit = 0; – 关闭自动提交
START TRANSACTION; – 开始一个事务,标记事务的起始点
UPDATE account SET cash=cash-500 WHERE name=‘A’;
UPDATE account SET cash=cash+500 WHERE name=‘B’;
COMMIT; – 提交事务

rollback;

SET autocommit = 1; – 恢复自动提交

索引
索引的作用

提高查询速度

确保数据的唯一性

可以加速表和表之间的连接 , 实现表与表之间的参照完整性

使用分组和排序子句进行数据检索时 , 可以显著减少分组和排序的时间

全文检索字段进行搜索优化.

分类

主键索引 (Primary Key)

唯一索引 (Unique)

常规索引 (Index)

全文索引 (FullText)

主键索引

主键 : 某一个属性组能唯一标识一条记录

特点 :

最常见的索引类型

确保数据记录的唯一性

确定特定数据记录在数据库中的位置

唯一索引

作用 : 避免同一个表中某数据列中的值重复

与主键索引的区别

主键索引只能有一个

唯一索引可能有多个

CREATE TABLE Grade(
GradeID INT(11) AUTO_INCREMENT PRIMARYKEY,
GradeName VARCHAR(32) NOT NULL UNIQUE
– 或 UNIQUE KEY GradeID (GradeID)
)
常规索引

作用 : 快速定位特定数据

注意 :

index 和 key 关键字都可以设置常规索引

应加在查询找条件的字段

不宜添加太多常规索引,影响数据的插入,删除和修改操作

CREATE TABLE result(
– 省略一些代码
INDEX/KEY ind (studentNo,subjectNo) – 创建表时添加
)
– 创建后添加
ALTER TABLE result ADD INDEX ind(studentNo,subjectNo);
全文索引

百度搜索:全文索引

作用 : 快速定位特定数据

注意 :

只能用于MyISAM类型的数据表

只能用于CHAR , VARCHAR , TEXT数据列类型

适合大型数据集

/*
#方法一:创建表时
  CREATE TABLE 表名 (
字段名1 数据类型 [完整性约束条件…],
字段名2 数据类型 [完整性约束条件…],
[UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY
[索引名] (字段名[(长度)] [ASC |DESC])
);

#方法二:CREATE在已存在的表上创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名
ON 表名 (字段名[(长度)] [ASC |DESC]) ;

#方法三:ALTER TABLE在已存在的表上创建索引
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX
索引名 (字段名[(长度)] [ASC |DESC]) ;

#删除索引:DROP INDEX 索引名 ON 表名字;
#删除主键索引: ALTER TABLE 表名 DROP PRIMARY KEY;

#显示索引信息: SHOW INDEX FROM student;
*/

/增加全文索引/
ALTER TABLE school.student ADD FULLTEXT INDEX studentname (StudentName);

/EXPLAIN : 分析SQL语句执行性能/
EXPLAIN SELECT * FROM student WHERE studentno=‘1000’;

/使用全文索引/
– 全文搜索通过 MATCH() 函数完成。
– 搜索字符串作为 against() 的参数被给定。搜索以忽略字母大小写的方式执行。对于表中的每个记录行,MATCH() 返回一个相关性值。即,在搜索字符串与记录行在 MATCH() 列表中指定的列的文本之间的相似性尺度。
EXPLAIN SELECT *FROM student WHERE MATCH(studentname) AGAINST(‘love’);

/*
开始之前,先说一下全文索引的版本、存储引擎、数据类型的支持情况

MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引;
MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;
只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。
测试或使用全文索引时,要先看一下自己的 MySQL 版本、存储引擎和数据类型是否支持全文索引。
*/
拓展:测试索引

建表app_user:

CREATE TABLE app_user (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
name varchar(50) DEFAULT ‘’ COMMENT ‘用户昵称’,
email varchar(50) NOT NULL COMMENT ‘用户邮箱’,
phone varchar(20) DEFAULT ‘’ COMMENT ‘手机号’,
gender tinyint(4) unsigned DEFAULT ‘0’ COMMENT ‘性别(0:男;1:女)’,
password varchar(100) NOT NULL COMMENT ‘密码’,
age tinyint(4) DEFAULT ‘0’ COMMENT ‘年龄’,
create_time datetime DEFAULT CURRENT_TIMESTAMP,
update_time timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘app用户表’
批量插入数据:100w

DROP FUNCTION IF EXISTS mock_data;
DELIMITER $$
CREATE FUNCTION mock_data()
RETURNS INT
BEGIN
DECLARE num INT DEFAULT 1000000;
DECLARE i INT DEFAULT 0;
WHILE i < num DO
INSERT INTO app_user(name, email, phone, gender, password, age)
VALUES(CONCAT(‘用户’, i), ‘[email protected]’, CONCAT(‘18’, FLOOR(RAND()*(999999999-100000000)+100000000)),FLOOR(RAND()*2),UUID(), FLOOR(RAND()*100));
SET i = i + 1;
END WHILE;
RETURN i;
END;
SELECT mock_data();
索引效率测试

无索引

SELECT * FROM app_user WHERE name = ‘用户9999’; – 查看耗时
SELECT * FROM app_user WHERE name = ‘用户9999’;
SELECT * FROM app_user WHERE name = ‘用户9999’;

mysql> EXPLAIN SELECT * FROM app_user WHERE name = ‘用户9999’\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: app_user
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 992759
filtered: 10.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
创建索引

CREATE INDEX idx_app_user_name ON app_user(name);
测试普通索引

mysql> EXPLAIN SELECT * FROM app_user WHERE name = ‘用户9999’\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: app_user
partitions: NULL
type: ref
possible_keys: idx_app_user_name
key: idx_app_user_name
key_len: 203
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

mysql> SELECT * FROM app_user WHERE name = ‘用户9999’;
1 row in set (0.00 sec)

mysql> SELECT * FROM app_user WHERE name = ‘用户9999’;
1 row in set (0.00 sec)

mysql> SELECT * FROM app_user WHERE name = ‘用户9999’;
1 row in set (0.00 sec)
索引准则

索引不是越多越好

不要对经常变动的数据加索引

小数据量的表建议不要加索引

索引一般应加在查找条件的字段

索引的数据结构

– 我们可以在创建上述索引的时候,为其指定索引类型,分两类
hash类型的索引:查询单条快,范围查询慢
btree类型的索引:b+树,层数越多,数据量指数级增长(我们就用它,因为innodb默认支持它)

– 不同的存储引擎支持的索引类型也不一样
InnoDB 支持事务,支持行级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
Memory 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;
NDB 支持事务,支持行级别锁定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;
Archive 不支持事务,支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引;
图片

7 权限及如何设计数据库

权限及设计数据库

用户管理
使用SQLyog 创建用户,并授予权限演示

图片

基本命令

/* 用户和权限管理 */ ------------------
用户信息表:mysql.user

– 刷新权限
FLUSH PRIVILEGES

– 增加用户 CREATE USER kuangshen IDENTIFIED BY ‘123456’
CREATE USER 用户名 IDENTIFIED BY [PASSWORD] 密码(字符串)

  • 必须拥有mysql数据库的全局CREATE USER权限,或拥有INSERT权限。
  • 只能创建用户,不能赋予权限。
  • 用户名,注意引号:如 ‘user_name’@‘192.168.1.1’
  • 密码也需引号,纯数字密码也要加引号
  • 要在纯文本中指定密码,需忽略PASSWORD关键词。要把密码指定为由PASSWORD()函数返回的混编值,需包含关键字PASSWORD

– 重命名用户 RENAME USER kuangshen TO kuangshen2
RENAME USER old_user TO new_user

– 设置密码
SET PASSWORD = PASSWORD(‘密码’) – 为当前用户设置密码
SET PASSWORD FOR 用户名 = PASSWORD(‘密码’) – 为指定用户设置密码

– 删除用户 DROP USER kuangshen2
DROP USER 用户名

– 分配权限/添加用户
GRANT 权限列表 ON 表名 TO 用户名 [IDENTIFIED BY [PASSWORD] ‘password’]

  • all privileges 表示所有权限
  • . 表示所有库的所有表
  • 库名.表名 表示某库下面的某表

– 查看权限 SHOW GRANTS FOR root@localhost;
SHOW GRANTS FOR 用户名
– 查看当前用户权限
SHOW GRANTS; 或 SHOW GRANTS FOR CURRENT_USER; 或 SHOW GRANTS FOR CURRENT_USER();

– 撤消权限
REVOKE 权限列表 ON 表名 FROM 用户名
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 用户名 – 撤销所有权限
权限解释

– 权限列表
ALL [PRIVILEGES] – 设置除GRANT OPTION之外的所有简单权限
ALTER – 允许使用ALTER TABLE
ALTER ROUTINE – 更改或取消已存储的子程序
CREATE – 允许使用CREATE TABLE
CREATE ROUTINE – 创建已存储的子程序
CREATE TEMPORARY TABLES – 允许使用CREATE TEMPORARY TABLE
CREATE USER – 允许使用CREATE USER, DROP USER, RENAME USER和REVOKE ALL PRIVILEGES。
CREATE VIEW – 允许使用CREATE VIEW
DELETE – 允许使用DELETE
DROP – 允许使用DROP TABLE
EXECUTE – 允许用户运行已存储的子程序
FILE – 允许使用SELECT…INTO OUTFILE和LOAD DATA INFILE
INDEX – 允许使用CREATE INDEX和DROP INDEX
INSERT – 允许使用INSERT
LOCK TABLES – 允许对您拥有SELECT权限的表使用LOCK TABLES
PROCESS – 允许使用SHOW FULL PROCESSLIST
REFERENCES – 未被实施
RELOAD – 允许使用FLUSH
REPLICATION CLIENT – 允许用户询问从属服务器或主服务器的地址
REPLICATION SLAVE – 用于复制型从属服务器(从主服务器中读取二进制日志事件)
SELECT – 允许使用SELECT
SHOW DATABASES – 显示所有数据库
SHOW VIEW – 允许使用SHOW CREATE VIEW
SHUTDOWN – 允许使用mysqladmin shutdown
SUPER – 允许使用CHANGE MASTER, KILL, PURGE MASTER LOGS和SET GLOBAL语句,mysqladmin debug命令;允许您连接(一次),即使已达到max_connections。
UPDATE – 允许使用UPDATE
USAGE – “无权限”的同义词
GRANT OPTION – 允许授予权限

/* 表维护 */

– 分析和存储表的关键字分布
ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE 表名 …
– 检查一个或多个表是否有错误
CHECK TABLE tbl_name [, tbl_name] … [option] …
option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
– 整理数据文件的碎片
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] …

MySQL备份
数据库备份必要性

保证重要数据不丢失

数据转移

MySQL数据库备份方法

mysqldump备份工具

数据库管理工具,如SQLyog

直接拷贝数据库文件和相关配置文件

mysqldump客户端

作用 :

转储数据库

搜集数据库进行备份

将数据转移到另一个SQL服务器,不一定是MySQL服务器

图片

– 导出

  1. 导出一张表 – mysqldump -uroot -p123456 school student >D:/a.sql
      mysqldump -u用户名 -p密码 库名 表名 > 文件名(D:/a.sql)
  2. 导出多张表 – mysqldump -uroot -p123456 school student result >D:/a.sql
      mysqldump -u用户名 -p密码 库名 表1 表2 表3 > 文件名(D:/a.sql)
  3. 导出所有表 – mysqldump -uroot -p123456 school >D:/a.sql
      mysqldump -u用户名 -p密码 库名 > 文件名(D:/a.sql)
  4. 导出一个库 – mysqldump -uroot -p123456 -B school >D:/a.sql
      mysqldump -u用户名 -p密码 -B 库名 > 文件名(D:/a.sql)

可以-w携带备份条件

– 导入

  1. 在登录mysql的情况下:-- source D:/a.sql
      source 备份文件
  2. 在不登录的情况下
      mysql -u用户名 -p密码 库名 < 备份文件

规范化数据库设计
为什么需要数据库设计
当数据库比较复杂时我们需要设计数据库

糟糕的数据库设计 :

数据冗余,存储空间浪费

数据更新和插入的异常

程序性能差

良好的数据库设计 :

节省数据的存储空间

能够保证数据的完整性

方便进行数据库应用系统的开发

软件项目开发周期中数据库设计 :

需求分析阶段: 分析客户的业务和数据处理需求

概要设计阶段:设计数据库的E-R模型图 , 确认需求信息的正确和完整.

设计数据库步骤

收集信息

与该系统有关人员进行交流 , 座谈 , 充分了解用户需求 , 理解数据库需要完成的任务.

标识实体[Entity]

标识数据库要管理的关键对象或实体,实体一般是名词

标识每个实体需要存储的详细信息[Attribute]

标识实体之间的关系[Relationship]

三大范式
问题 : 为什么需要数据规范化?

不合规范的表设计会导致的问题:

信息重复

更新异常

插入异常

无法正确表示信息

删除异常

丢失有效信息

三大范式

第一范式 (1st NF)

第一范式的目标是确保每列的原子性,如果每列都是不可再分的最小数据单元,则满足第一范式

第二范式(2nd NF)

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。

第二范式要求每个表只描述一件事情

第三范式(3rd NF)

如果一个关系满足第二范式,并且除了主键以外的其他列都不传递依赖于主键列,则满足第三范式.

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

规范化和性能的关系

为满足某种商业目标 , 数据库性能比规范化数据库更重要

在数据规范化的同时 , 要综合考虑数据库的性能

通过在给定的表中添加额外的字段,以大量减少需要从中搜索信息所需的时间

通过在给定的表中插入计算列,以方便查询

你可能感兴趣的:(mysql,数据库)