数据库笔记

Mysql数据库

Mysql数据库简介

MySQL 是一款开源的关系型数据库管理系统,即:

  1. 关系型: 数据以表的形式存储,表与表之间可以通过字段建立关联。

  2. 开源:核心版本免费使用,这也是它普及的关键原因。

  3. 跨平台:支持 Windows、Linux、macOS 等主流操作系统,适配性极强。

MySQL 的核心特点:

  • 轻量高效:安装包小、资源占用低,启动快,适合从小型应用到大型系统的各种场景。

  • 易用性强:SQL 语法标准且简单,新手容易上手,社区文档和教程丰富。

  • 高可靠性:支持事务(ACID 特性)、备份恢复、主从复制(读写分离),保障数据安全和服务稳定。

  • 兼容性好:支持多种编程语言(Python、Java、PHP、C# 等),几乎所有主流开发框架都能无缝对接。

  • 生态完善:有大量配套工具(如 phpMyAdmin、Navicat、MySQL Workbench),且被 Oracle 官方维护,更新迭代稳定。

MySQL 与其他数据库的简单对比:

数据库 特点 适用场景
MySQL 开源免费、轻量高效 中小型应用、网站、一般企业系统
Oracle 商用、功能强、高并发 大型金融、政企核心系统
SQL Server 微软出品、适配 Windows .NET 开发、Windows 服务器环境
SQLite 嵌入式、无服务器 移动端 APP、本地小型应用

Mysql数据库的安装

下载安装包

  1. 首先去官网下载Mysql的安装包,官网链接:https://www.mysql.com/cn/downloads/

  2. 点击下列红色链接进去:

  3. 找到MySQL Installer for Windows并点击,如下所示:

  4. 进入下一个页面后,我们可以选择下载最新的版本,当然也可以点击Archives 选择其它版本进行下载。这里我们下载5.7版本,点击下列第二个Download 即可,如下所示:

至此,我们的安装白已经下载完成,下面进行安装。

安装配置

  1. 双击下载的文件启动安装流程。

  2. 进入下列页面后,选择"自定义安装"

  3. 选择与我们下载的数据库

  4. 左边显示灰色,右边显示黑色时即可,如下:

  5. 完上一步操作之后,会出现一个箭头所指的按钮,点击可切换MySQL的安装位置,如图所示:

  6. 切换好位置之后,点击Execute执行安装即可,如下:

  7. 安装好后点击Next,如下即可:

  8. 接下来开始配置端口号,如果之前安装过其他版本的MySQL或者MariaDB,3306端口可能会被占用,我们可以设置其他的端口号,但这里建议端口号设置3306,如下所示:

  9. 如下,开始设置MySQL的登录密码。(建议密码设置简单一点,后面使用都会用到)

  10. 后面基本都是点击下一步,如下:





    至此,MySQL5.7已经安装完毕。下面我们可以验证一下。

最后,使用刚刚安装时设置的密码登录,登陆后显示如下即登录成功!

注意:如果一直卡在starting the server这个地方,大概率是由于你的路径中包含中文名字。因为我们安装时没有勾选show Advanced Options,即没有更改日志的文件,因此在安装过程中会自动生成包含计算机名称的日志文件,如果恰好计算机名称中包含中文,则是不行的。所以,我们要卸载并重新安装,勾选show Advanced Options选项,在接下来弹出的Advanced Options页面更改你的路径。,如下所示。

自此,整个mysql的安装教材完成。

注意:由于navicate的下载过于简单,这里我将不再讲解navicate的下载教程,如有不会的读者,请网上参考其他笔记。

Mysql数据库学习

命令行链接数据库

cmd后进入命令行,输入mysql -u root -p连接数据库运行

sql 复制代码
mysql -u root -p   --连接数据库

show databases; --查看所有数据库

use school   --切换某个数据库  use  数据库名

show tables   --显示某个数据库中所有的表

describe student1;  --查看数据库中所有表的信息

create database demo01;  --创建一个名为demo01的数据库,create database 数据库名称

exit   --退出连接命令


--为单行注释(SQL 的本来的注释)
/*hello
world
*/    sql的多行注释

数据库xxx语言

DDL 定义

DML 操作语言

DQL 查询语言

DCL 控制语言

操作数据库

操作数据库 > 操作数据库中的表 > 操作数据库中表的数据

mysql关键字不区分大小写

  1. 创建数据库
    手动创建数据时如下:
sql 复制代码
crate Database if not exists demo02 
  1. 删除数据库

    sql 复制代码
    Drop database if exists demo02
  2. 使用数据库

    sql 复制代码
    use `school`
  3. 查看数据库

    sql 复制代码
    show databases; --查看所有数据库

学习思路:

  • 对照navicat可视化历史记录查看sql
  • 固定的语法和关键字必须要记住!

数据库的数据类型

1.数值类型

类型 字节 用途 & 典型场景
TINYINT 1 小整数(范围 - 128~127),适合状态值(0/1)、年龄、性别标识等
SMALLINT 2 较小整数(-32768~32767),适合少量数据的计数(如商品库存、评论数)
mediumint 3
INT 4 常用整数(-21 亿~21 亿),适合用户 ID、订单编号、自增主键等核心标识
BIGINT 8 大整数(-9e18~9e18),适合海量数据的 ID(如大数据量的订单、日志主键)
FLOAT 4 单精度浮点数(精度约 6-7 位),适合非精准计算(如温度、评分)
DOUBLE 8 双精度浮点数(精度约 15 位),适合普通小数计算(如身高、体重)
DECIMAL(M,D) 可变 定点数(精准),M = 总长度,D = 小数位数,适合金额、税率(如 DECIMAL (10,2) 存价格)

2.字符串类型

类型 特点 & 字节 用途 & 典型场景
CHAR(n) 定长 n 为固定长度(1~255),占用 n 字节,适合固定长度文本(手机号、身份证号、邮编)
VARCHAR(n) 变长 n 为最大长度(1~65535),仅占实际字符 + 1/2 字节,适合可变长度文本(姓名、地址)
TINYTEXT 最大 255 字符 短文本,适合简短备注、标签
TEXT 最大 65535 字符 普通长文本,适合文章内容、商品描述
MEDIUMTEXT 最大 16M 字符 中等长度文本,适合长文、日志内容
LONGTEXT 最大 4G 字符 超长文本,适合超大内容(如备份数据、大型文档)
ENUM 1/2 字节 枚举类型(只能选其一),适合性别(男 / 女)、订单状态(待付款 / 已发货)
SET 1-8 字节 集合类型(可多选),适合用户兴趣(阅读 / 运动 / 音乐)、商品标签

3.时间日期

类型 字节 格式 & 范围 用途 & 典型场景
DATE 3 YYYY-MM-DD(1000~9999) 仅存日期,适合生日、订单日期、注册日期
TIME 3 HH:MM:SS(-838:59:59~838:59:59) 仅存时间,适合打卡时间、活动时长
DATETIME 8 YYYY-MM-DD HH:MM:SS 日期 + 时间,适合创建时间、更新时间(无时区影响)
TIMESTAMP 4 1970~至今的毫秒数(秒级时间戳) 自动更新时间(如数据修改时间),支持时区转换
YEAR 1 YYYY(1901~2155) 仅存年份,适合年份统计、毕业年份

4.null类型

没有值、未知,但要注意不要使用null进行计算,即使进行了计算结果也为null。

数据库的字段属性

Unsigned:

  • 无符号整数

  • 声明了该列不能为负数

zerofill:

  • 0填充的

  • 不足的位数,前边使用0来填充,如 int(3), 1-->003

自增:

  • 通常理解为自增,自动在上一条记录的基础上+1(默认)

  • 通常用来设计唯一的主键 ~index,必须是整数类型

  • 可以自定义设计主键自增的起始值和步长

非空 Null not null

  • 假设设置为not null ,如果不给它赋值,就会报错!

  • Null,如果不填写值,默认就是null!

创建数据库表

sql 复制代码
-- 学号int 登录密码varchar(20) 姓名,性别varchar(2),出生日期(datatime),家庭住址,email

-- 注意点,使用英文(),表的名称 和 字段 尽量使用  ``括起来

-- AUTO_INCREMENT 自增

--字符串使用单引号括起来!

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

create TABLE if not EXISTS `student`(
    `id` int(4)  not null AUto_increment COMMENT '学号',
    `name` VARCHAR(30) not null DEFAULT '匿名' COMMENT '姓名',
    `pwd` VARCHAR(20) not null DEFAULT '123456' COMMENT '密码',
    `sex` VARCHAR(50) 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

格式

复制代码
 create table [if not exits] `表名`(
     '字段名' 列类型 [属性]  [索引] [注释],
     '字段名' 列类型 [属性]  [索引] [注释],
     ....
     '字段名' 列类型 [属性]  [索引] [注释],
 )[表类型][字符集设置][注释]

排错方式:一行一行排

常用命令

复制代码
SHOW CREATE DATABASE school  --查看创建数据库的语句

SHOW CREATE TABLE student  --查看student 数据表的定义语句

DESC    student  --显示表的结构

数据表的类型

存储引擎 核心特点 适用场景 关键注意点
InnoDB 1. 支持事务(ACID)、行级锁、外键约束 2. 崩溃恢复能力强,数据安全性高 3. 读写性能均衡,适合高并发 绝大多数业务场景: 用户表、订单表、支付表、财务表等核心业务表 1. MySQL 5.5+ 默认引擎 2. 占用磁盘空间略大 3. 需合理设置索引提升性能
MyISAM 1. 不支持事务、外键,仅表级锁 2. 查询速度极快,插入 / 更新效率低 3. 占用空间小,支持全文索引 只读 / 少写的场景: 日志表、统计报表、静态数据字典、博客文章表 1. 崩溃后数据易损坏,无恢复能力 2. 不适合高并发写入场景
MEMORY 1. 数据存储在内存中,读写速度极快 2. 重启 MySQL 后数据全部丢失 3. 支持哈希索引,仅表级锁 临时数据 / 缓存场景: 临时计算结果、会话数据、高频访问的临时表 1. 受内存大小限制 2. 不支持 BLOB/TEXT 类型
CSV 1. 数据以 CSV 文件形式存储,可直接用 Excel 打开 2. 不支持索引、事务,仅适合简单读写 数据导入 / 导出场景: 批量数据迁移、报表导出、与其他系统交互 1. 性能极低,仅用于小众场景 2. 每行数据对应 CSV 文件一行

适用场景 :

  • 适用 MyISAM : 节约空间及相应速度
  • 适用 InnoDB : 安全性高 , 事务处理及多用户操作数据表,多表多用户操作

数据表的存储位置

所有的数据库文件都存在 data目录下,因此数据库的存储本质还是文件的存储!

MySQL 引擎在物理文件上的区别:

  • InnoDB类型在数据库表中只有一个 *.frm文件 , 以及上一级目录的ibdata1文件

  • MyISAM类型数据表对应三个文件 :

设置数据库表的字符集编码

sql 复制代码
charset=utf8

注意,不设置的话,会使用MySQL的默认字符集编码(不支持中文!)

也可以更改my.ini中的配置默认的编码(不建议)

复制代码
charset-set-server = utf8

修改删除表

修改表

sql 复制代码
--修改表名 ALTER TABLE 旧表名 rename AS 新表名 
ALTER TABLE student rename AS student1 
--增加表的字段

ALTER TABLE    student1 add age INT(11)

--修改表的字段(两种:重命名,修改约束!)
ALTER    TABLE student1 MODIFY age VARCHAR(11) --修改约束
ALTER    TABLE student1 CHANGE age age1 int(11)  --字段重命名 

--删除表的字段

ALTER TABLE    student1 DROP    age1

删除表

sql 复制代码
--删除表
DROP TABLE IF EXISTS student1

所有的创建和删除操作尽量加上判断,以免出现报错!

注意点:

  • `` 字段名 使用这个包裹!
  • 注释 - - /**/
  • sql 关键字大小写不敏感,建议大家写小写
  • 所有的符号全部用英文!

Mysql的数据管理

外键

如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。由此可见,外键表示了两个关系之间的相关联系。以另一个关系的外键作主关键字的表被称为主表 ,具有此外键的表被称为主表的从表

外键作用

保持数据一致性完整性 ,主要目的是控制存储在外键表中的数据,约束。使两张表形成关联,外键只能引用外表中的列的值或使用空值。

创建外键表

sql 复制代码
--创建年级表

CREATE TABLE `grade`(
    `gradeid` INT(10) NOT NULL auto_increment COMMENT '年纪id',
    `gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
    PRIMARY KEY(`gradeid`)
)ENGINE =INNODB DEFAULT CHARSET=utf8

--学生表的gradeid字段要去引用年纪表的gradeid
--定义外键key
--给这个外键添加约束(执行引用) REFERENCES引用

create TABLE if not EXISTS `student`(
    `id` int(4)  not null AUto_increment COMMENT '学号',
    `name` VARCHAR(30) not null DEFAULT '匿名' COMMENT '姓名',
    `pwd` VARCHAR(20) not null DEFAULT '123456' COMMENT '密码',
    `sex` VARCHAR(50) not NULL DEFAULT '女' COMMENT '名别',
    `birthday` datetime DEFAULT NULL    COMMENT    '出生日期',
    `gradeid` INT(10) not NULL COMMENT '学生年纪',
    `address` VARCHAR(100) DEFAULT NULL COMMENT    '家庭地址',
    `email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',

    PRIMARY KEY(`id`),
    key `FK_gradeid`(`gradeid`),
    CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`) 

)ENGINE =INNODB DEFAULT CHARSET=utf8

创建外键方式二 : 创建子表完毕后,修改子表添加外键

sql 复制代码
--创建表时没有外键关系

ALTER table `student`
add CONSTRAINT    `Fk_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`)

--公式: ALTER table `表` add CONSTRAINT  `约束名` FOREIGN KEY(`作为外键的列`) REFERENCES `参考的表`(`表中哪个字段`)

以上的操作都是物理外键,数据库级别的外键,不建议使用,因为过于繁琐,操作表时关联性过大! (避免数据库过多造成困扰)

最佳实践

  • 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)

  • 我们想使用多张表的娄收据,想使用外键(程序去实现)

DML语言

DML语言包括:

Insert添加语句

语法:INSERT INTO 表名 ([字段1,字段2,字段3]) values('值1'(,('值2'), ('值3'),(...)

注意事项:

  1. 字段和字段之间需要用逗号隔开

  2. 字段是可以省略的,但是后边的值必须是一一对应,不能省略

  3. 可以同事插入多条数据

sql 复制代码
--插入语句
--INSERT INTO 表名 ([字段1,字段2,字段3]) values('值1'(,('值2'), ('值3'),(...)

USE school1
INSERT    INTO `grade`(`gradename`) VALUES('大一')

--由于主键自增我们可以省略(如果不写字段,默认会一一匹配),一般写字段要将字段和数据一一对应
INSERT INTO `grade` VALUES ('大二')
--插入多个字段,注意如果其它数据库中有grade这个表时要加上(use 数据库名)
USE school1
INSERT INTO `grade`(`gradename`) VALUES ('大二'), ('大三')

--插入多条数据
USE school1
INSERT    INTO `student1`(`name`,`pwd`,`sex`)
VALUES ('张三', 'aaaaaa','男'),
('李四', 'bbbbbb','男')

Update修改语句

语法:--UPDATE 表名 SET 列名1='值1',列名2 = '值2' WHERE [条件]

sql 复制代码
--修改语句

--修改学员名字

UPDATE `student1` SET `name` = '小明' WHERE id BETWEEN 2 AND 5

--修改多个属性,逗号隔开
UPDATE `student1` SET `name` = '小红', `email` = '12345678@qq.com' WHERE id=2

--不指定条件的情况下将会更改所有表

--语法
--UPDATE 表名  SET COLUMN_name=VALUE  WHERE  [条件]

--通过多个条件定位数据

UPDATE `student1` SET `name`='长江七号' WHERE `name`='小明'and`sex` = '男'

注意事项:

  • 字段尽量带上票

  • where筛选的条件如果没有指定,则会修改所有的列

  • 值是一个具体的值,也可以是一个变量

delete修改语句

truncate命令与delete的区别:

  • 相同点:都能删除数据且不会删除表结构

  • 不同:

    • truncate 重新设置 自增列 计数器会归零

    • truncate 不会影响事务

sql 复制代码
--删除数据

--删除所有数据
delete FROM `student1`

--清空某个表
TRUNCATE `student`

--测试delete和truncate的区别
CREATE TABLE `test`(
    `id` INT(4) not NULL auto_increment,
    `coll` VARCHAR(20) not NULL,
    PRIMARY KEY(`id`)
)ENGINE= INNODB CHARSET=utf8

INSERT INTO `test`(`coll`) VALUES('1'),('2'),('3') 

DELETE FROM `test` --不会影响自增
TRUNCATE TABLE `test`  --自增会归0

注意:delete 删除的问题,重启数据库现象

  • InnoDB 自增列会从1开始(是存储在内存中的,断电即失)

  • MyISAM 继续从上一个自增量开始(存储在文件中的,不会丢失)

select查询语句

DQL数据查询语言:所有的查询操作都用该语言,使用频率最高的语言,数据库中最核心的语言

创建数据库:

sql 复制代码
CREATE DATABASE IF NOT EXISTS `school`;
-- 创建一个school数据库
USE `school`;-- 创建学生表
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`(
    `studentno` INT(4) NOT NULL COMMENT '学号',
    `loginpwd` VARCHAR(20) DEFAULT NULL,
    `studentname` VARCHAR(20) DEFAULT NULL COMMENT '学生姓名',
    `sex` TINYINT(1) DEFAULT NULL COMMENT '性别,0或1',
    `gradeid` INT(11) DEFAULT NULL COMMENT '年级编号',
    `phone` VARCHAR(50) NOT NULL COMMENT '联系电话,允许为空',
    `address` VARCHAR(255) NOT NULL COMMENT '地址,允许为空',
    `borndate` DATETIME DEFAULT NULL COMMENT '出生时间',
    `email` VARCHAR (50) NOT NULL COMMENT '邮箱账号允许为空',
    `identitycard` VARCHAR(18) DEFAULT NULL COMMENT '身份证号',
    PRIMARY KEY (`studentno`),
    UNIQUE KEY `identitycard`(`identitycard`),
    KEY `email` (`email`)
)ENGINE=MYISAM DEFAULT CHARSET=utf8;

-- 创建年级表
DROP TABLE IF EXISTS `grade`;
CREATE TABLE `grade`(
    `gradeid` INT(11) NOT NULL AUTO_INCREMENT COMMENT '年级编号',
  `gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
    PRIMARY KEY (`gradeid`)
) ENGINE=INNODB AUTO_INCREMENT = 6 DEFAULT CHARSET = utf8;

-- 创建科目表
DROP TABLE IF EXISTS `subject`;
CREATE TABLE `subject`(
    `subjectno`INT(11) NOT NULL AUTO_INCREMENT COMMENT '课程编号',
    `subjectname` VARCHAR(50) DEFAULT NULL COMMENT '课程名称',
    `classhour` INT(4) DEFAULT NULL COMMENT '学时',
    `gradeid` INT(4) DEFAULT NULL COMMENT '年级编号',
    PRIMARY KEY (`subjectno`)
)ENGINE = INNODB AUTO_INCREMENT = 19 DEFAULT CHARSET = utf8;

-- 创建成绩表
DROP TABLE IF EXISTS `result`;
CREATE TABLE `result`(
    `studentno` INT(4) NOT NULL COMMENT '学号',
    `subjectno` INT(4) NOT NULL COMMENT '课程编号',
    `examdate` DATETIME NOT NULL COMMENT '考试日期',
    `studentresult` INT (4) NOT NULL COMMENT '考试成绩',
    KEY `subjectno` (`subjectno`)
)ENGINE = INNODB DEFAULT CHARSET = utf8;

-- 插入学生数据 其余自行添加 这里只添加了2行
INSERT INTO `student` (`studentno`,`loginpwd`,`studentname`,`sex`,`gradeid`,`phone`,`address`,`borndate`,`email`,`identitycard`)
VALUES
(1000,'123456','张伟',0,2,'13800001234','北京朝阳','1980-1-1','text123@qq.com','123456198001011234'),
(1001,'123456','赵强',1,3,'13800002222','广东深圳','1990-1-1','text111@qq.com','123456199001011233');

-- 插入成绩数据  这里仅插入了一组,其余自行添加
INSERT INTO `result`(`studentno`,`subjectno`,`examdate`,`studentresult`)
VALUES
(1000,1,'2013-11-11 16:00:00',85),
(1000,2,'2013-11-12 16:00:00',70),
(1000,3,'2013-11-11 09:00:00',68),
(1000,4,'2013-11-13 16:00:00',98),
(1000,5,'2013-11-14 16:00:00',58);

-- 插入年级数据
INSERT INTO `grade` (`gradeid`,`gradename`) VALUES(1,'大一'),(2,'大二'),(3,'大三'),(4,'大四'),(5,'预科班');

-- 插入科目数据
INSERT INTO `subject`(`subjectno`,`subjectname`,`classhour`,`gradeid`)VALUES
(1,'高等数学-1',110,1),
(2,'高等数学-2',110,2),
(3,'高等数学-3',100,3),
(4,'高等数学-4',130,4),
(5,'C语言-1',110,1),
(6,'C语言-2',110,2),
(7,'C语言-3',100,3),
(8,'C语言-4',130,4),
(9,'Java程序设计-1',110,1),
(10,'Java程序设计-2',110,2),
(11,'Java程序设计-3',100,3),
(12,'Java程序设计-4',130,4),
(13,'数据库结构-1',110,1),
(14,'数据库结构-2',110,2),
(15,'数据库结构-3',100,3),
(16,'数据库结构-4',130,4),
(17,'C#基础',130,1);

select的语法:

复制代码
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}];
   -- 指定查询的记录从哪条至哪条

查询简单练习:

sql 复制代码
--查询所有学生,SELECT 字段 FROM 表

SELECT * FROM student

--查询指定字段

SELECT `StudentNo`,`StudentName` from student

--别名,给结果起一个名字 用AS 也可以给字段起别名,也可以给表起别名

SELECT `StudentNo`AS 学号,`StudentName` AS 学生姓名 from student as s

 --函数concat(a,b)
 SELECT CONCAT('姓名',StudentName)AS 新名字 FROM student

去重

sql 复制代码
 --去重

 --查询有哪些学生参加了考试,成绩
 SELECT * FROM result --查询全部的考试成绩
 SELECT `StudentNo` FROM result --查询有哪些同学参加了考试
 SELECT DISTINCT `StudentNo` FROM result  --发现重复数据,去重

 SELECT VERSION() --查询系统版本号
 SELECT 100*3 - AS 计算结果

 --学员考试成绩+1分查看

 SELECT `StudentNo`,`StudentREsult`+1 AS `提分后` FROM result

where条件子句

作用:检索数据中符合条件的值

逻辑运算符如下:

sql 复制代码
--WHERE条件子句

 SELECT `StudentNo`,`StudentResult` FROM result
 WHERE studentresult>=95 AND studentresult<=100

  --and ==&&

 SELECT `StudentNo`,`StudentResult` FROM result
 WHERE studentresult>=95 && studentresult<=100

    --模糊查询
     --WHERE条件子句

 SELECT `StudentNo`,`StudentResult` FROM result
 WHERE studentresult BETWEEN 95 AND 100

模糊查询:本质是比较运算符

示例练习

sql 复制代码
    --模糊查询
     --WHERE条件子句

 SELECT `StudentNo`,`StudentResult` FROM result
 WHERE studentresult BETWEEN 95 AND 100


 --模糊查询

 --查询姓刘的同学
 --LIKE结合  %(代表0到任意个字符) ,_(代表一个字符)
 SELECT `studentno` ,`studentname` FROM `student`
 WHERE studentname LIKE '刘%'

 --查询姓刘的同学,名字只有一个字的
  SELECT `studentno` ,`studentname` FROM `student`
 WHERE studentname LIKE '刘_'

 --查询姓刘的同学,名字只有两个字的
   SELECT `studentno` ,`studentname` FROM `student`
 WHERE studentname LIKE '刘__'

 --查询名字有嘉字的同学
    SELECT `studentno` ,`studentname` FROM `student`
 WHERE studentname LIKE '%嘉%'

 --IN,具体的一个或多个值
 --查询1001,1002,1003号学员
  SELECT `studentno` ,`studentname` FROM `student`
    WHERE studentno IN(1001,1002,1003)

    --查询在北京的学生

SELECT `studentno` ,`studentname` FROM `student`
WHERE `address` in ('北京')


--查询地址为空的学生
SELECT `studentno` ,`studentname` FROM `student`
WHERE address=''  or address is NULL 

--查询有出生日期的学生
SELECT `studentno` ,`studentname` FROM `student`
WHERE borndate is NOT NULL 

联表查询

代码练习

sql 复制代码
--====联表查询====

--查询参加考试的同学(学号,姓名,科目编号,分数)

/*
思路:
1.分析需求,分析查询的字段来自那些表
2.确定使用哪种连接查询?7种
    确定交叉点(这两个表中的那个数据是相同的)
    判断条件:学生表中的studentno=成绩表studentno    
*/
--INNER JOIN练习
SELECT s.studentno,studentname subjectno,studentresult
FROM student AS s
INNER JOIN result AS r
WHERE s.studentno =r.studentno


--RIGHT JOIN使用
SELECT s.studentno,studentname subjectno,studentresult
FROM student AS s
RIGHT JOIN result AS r
ON s.studentno =r.studentno


--ELFT JOIN使用
SELECT s.studentno,studentname subjectno,studentresult
FROM student AS s
RIGHT JOIN result AS r
ON s.studentno =r.studentno


--查询缺考的同学
SELECT s.studentno,studentname subjectno,studentresult
FROM student AS s
RIGHT JOIN result AS r
ON s.studentno =r.studentno
WHERE studentresult IS NULL

--查询参加考试的同学信息(学号,姓名,科目名,分数)

/*
思路:
1.分析需求,分析查询的字段来自那些表,student,result,`subject`(连接查询)
2.确定使用哪种连接查询?7种
    确定交叉点(这两个表中的那个数据是相同的)
    判断条件:学生表中的studentno=成绩表studentno    
*/

SELECT s.studentno, studentname,subjectname,studentresult
FROM student s
RIGHT JOIN result r
ON s.studentno =r.studentno 
INNER JOIN `subject`sub
ON r.subjectno = sub.subjectno

--思路:
1.要查询那些数据 SELECT
2.从哪几个表中查 FROM 表 xxx JOIN 连接的表 ON 交叉条件
3.假设存在一种多张表查询,先查询两张表,然后再慢慢增加

自连接

自己的表和自己的表连接,核心:一张表拆为两张一样的表即可

操作:查询父类对应的字类关系

sql 复制代码
--===================自连接==============
/*
自连接
   数据表与自身进行连接

需求:从一个包含栏目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 studentno,studentname,`gradename`
FROM student s
INNER JOIN `grade` g
WHERE s.`gradeid`=g.`gradeid`

-- 思考题:查询参加了考试的同学信息(学号,学生姓名,科目名,分数)
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 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'

排序和分页

排序

sql 复制代码
--===== 分页 LIMIT  和排序 order by=====

--排序:升序 ASC,降序DESC
--查询的结果根据成绩降序排列
-- ORDER BY 通过哪个字段进行排序
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 ASC

分页

语法:LIMIT 起始值,页面

sql 复制代码
--为什么要分页?
--缓解数据库压力,给人的体验更好,瀑布流
-- 分页,煤业只显示五条数据
--语法:LIMIT 起始值,页面的大小
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 ASC
LIMIT 0,5

嵌套子查询

什么是子查询?

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

sql 复制代码
--子查询和嵌套查询
--思考:
--查询java第一学年课程成绩排名前十的学生并且分数要大于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='数据库结构-1' 
ORDER BY StudentResult DESC
LIMIT 0,10

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

--方式二:使用子查询(由里及外)
SELECT studentno,`subjectno`,StudentResult
FROM result
WHERE studentno=(
SELECT `subjectno` FROM `subject` WHERE subjectname = '数据库结构-1'
)

--分数不小于80分的学生的学号和姓名
SELECT DISTINCT s.`studentname`,`studentname`
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
WHERE `studentresult` >=80

--在上面这个基础上增加一个科目,高等数学-2

SELECT DISTINCT s.`studentname`,`studentname`
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
WHERE `studentresult` >=80 AND `subjectno`=
(SELECT subjectNO FROM `subject`WHERE
`subjectname` = '高等数学-2')

--查询课程为高等数学-2 且分数不小于80分的同学的学号和姓名

SELECT DISTINCT s.`studentno`,`studentname`
FROM student s
INNER JOIN result r
ON s.studentno =r.studentno
INNER JOIN `subject` sub
on r.`subjectno`=sub.`subjectno`
WHERE `subjectname` = '高等数学-2' AND studentresult>=80

--方式三
SELECT studentno,studentname FROM student WHERE studentno IN(
   SELECT studentno FROM result WHERE StudentResult>=80 AND subjectno=(
       SELECT subjectno FROM `subject` WHERE subjectname = '高等数学-2'
  )
)

MySQL的常用函数

常用函数

sql 复制代码
--常用函数

--数学运算

SELECT ABS(-8) --绝对值
SELECT CEILING(9.4) --向上取整
SELECT FLOOR(9.4) --向下取整

SELECT RAND() -- 返回一个0·1之间的随机数
SELECT SIGN(10) --判断一个数的符号0-0 负数返回-1.正数返回1

--字符串函数
SELECT CHAR_LENGTH('你好世界QQQ') --字符串长度

SELECT CONCAT('我','爱','你') --拼接字符串

SELECT INSERT ('我爱编程helloworld',1,2,'超级喜欢') --查询,替换

SELECT LOWER('HELLO') --转小写
SELECT UPPER('hello') --转大写
SELECT INSTR('hello','h') --返回第一次出现的字串的索引
SELECT REPLACE('坚持就能成功','坚持','努力') --替换出现的指定字符串
SELECT SUBSTR('坚持就能成功',4,2)  -返回指定的子字符串(源字符串,截取的位置,截取的长度)
SELECT REVERSE('坚持就能成功')  --反转字符串

--查询姓周的同学
SELECT REPLACE(studentname,'周','邹') FROM student
WHERE studentname LIKE '周%'

--时间和日期函数

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()) 

--系统

SELECT SYSTEM_USER()
SELECT USER()
SELECT VERSION()

聚合函数

sql 复制代码
--聚合函数
--都能进行统计表中的数据(想查询一个表中有多少个记录,就使用这个count())
SELECT count(studentname) FROM student --count(指定列),会忽略所有的null值
SELECT count(*) FROM student --count(指定列)  --count(*),不会忽略null值,本质计算行数
SELECT count(1) FROM student --count(指定列)  --count(*),不会忽略所有的null值,本质计算列数

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),min(studentresult)
FROM result r
INNER JOIN `subject` sub
ON r.`subjectno` = sub.`subjectno`
GROUP BY r.`subjectno`  --通过该字段进行分组
HAVING '平均分'>80  --having是分组后进行过滤

数据库级别的MD5加密

什么是MD5?

信息摘要算法,不可逆,简单说,就是把任意长度的文本 / 数据,通过固定算法转换成一个128 位的二进制串 ,通常表现为32 位的十六进制字符串

sql 复制代码
--测试md5加密

 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,'张三','123456'),(2,'李四','456789'),(3,'王五','891230')
--加密
UPDATE testmd SET pwd = MD5(pwd) WHERE id=1
UPDATE testmd SET pwd = MD5(pwd) --加密全部密码

--插入的时候加密
INSERT INTO testmd5 VALUES(4,'小明',MD5('123456'))

--如何校验:将用户传递进来的密码。进行md5加密,然后比对加密后的值

SELECT * FROM testmd5 WHERE `name`='小明' AND pwd=MD5('123456')

小结:

sql 复制代码
 -- ================ 内置函数 ================
 -- 数值函数
 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();

事务

什么是事务?

本质是一组不可分割的数据库操作集合 ------ 这组操作要么全部成功执行 ,要么全部失败回滚,就像 "一荣俱荣,一损俱损",保证数据在多步操作下的一致性。

核心特性(ACID原则)

特性 英文 通俗解释
原子性 Atomicity 事务是 "最小单位",要么全做,要么全不做(比如转账的两步操作不能只做一步)。
一致性 Consistency 事务执行前后,数据库的 "数据规则" 不变(比如转账前后,两人总余额不变,不是过程一致性)。
隔离性 Isolation 多个事务同时执行时,互相隔离、互不干扰(比如你转账的同时,朋友查余额不会看到 "只加了钱没扣钱" 的中间状态)。
持久性 Durability 事务一旦执行成功(提交),结果永久保存到数据库,即使数据库崩溃也不会丢失。

隔离性可能导致下列问题:

  • 脏读:一个事务读取到了另一个事务还未提交的修改数据,而这个数据最终可能会被回滚(撤销),相当于读到了 "脏数据"。

  • 不可重复读:在同一个事务 中,多次读取同一批数据,结果却不一致 ------ 因为期间有另一个事务提交了修改,导致前后读取结果不同。

基本语法:

sql 复制代码
---事务

--mysql是默认开启事务自动提交的

SET autocommit = 0 /*关闭*/
SET autocommit = 1 /*开启(默认)*/

--手动处理事务
SET autocommit = 0 /*关闭*/
--事务开启
START TRANSACTION  /*标记一个事务的开始,从这个之后的sql都在一个事务内*/

INSERT xxx
INSERT xxx
--提交:持久化(成功!)
COMMIT
--回滚:回到原来的样子(失败)
ROLLBACK

--事务结束
SET autocommit = 1 /*开启自动提交*/

--设置一个保存点
SAVEPOINT 保持点名字  --事务的保存点

ROLLBACK TO SAVEPOINT 保存点  --回滚到保存点

RELEASE SAVEPOINT 保存点 --删除保存点

测试

sql 复制代码
-- 事务测试
/*

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

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

CREATE DATABASE `shop`CHARACTER 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; -- 恢复自动提交

索引

索引(Index)是帮助MySQL高效获取数据的数据结构

索引的分类

在一个表中,主键索引只能有一个,唯一索引可以有多个

  • 主键索引

    • 唯一标识,主键不可重复,只能有一个列作为主键
  • 唯一索引

    • 避免重复 的列出现,可重复,多个列都可以标识唯一索引
  • 常规索引

    • 默认的,可通过index,key关键字来设置
  • 全文索引

sql 复制代码
-- 索引的使用
-- 在创建表的时候给字段增加索引或者创建完毕后,增加索引

-- 显示所有索引信息

SHOW INDEX FROM student

-- 增加一个全文索引,列名
ALTER TABLE student ADD FULLTEXT INDEX `studentname`(`studentname`)

-- EXPLAIN 分析sql的执行状况

EXPLAIN SELECT * FROM student --非全文索引

SELECT * FROM student WHERE MATCH(studentname)AGAINST('王')

索引测试

sql 复制代码
-- 测试索引
-- 创建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=utf8 COMMENT='app用户表'

--插入1000条数据
 -- 方式一
DROP FUNCTION IF EXISTS mock_data;
delimiter $$  -- 写函数之前必须加上,这是函数的标识

CREATE FUNCTION mock_data()
RETURNs INT

BEGIN
        DECLARE num INT DEFAULT 2000;
        DECLARE i INT DEFAULT 0;

        WHILE i<num DO
                INSERT INTO app_user(`name`,`email`,`phone`,`gender`,`PASSWORD`,`age`)
                VALUES(CONCAT('用户',i),'123456789@qq.com',CONCAT('18',FLOOR(RAND()*(999999999-100000000)+100000000)),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*10));
                SET i = i+1;
        END WHILE;
        RETURN i;
END;
-- 4. 恢复语句结束符为;
DELIMITER ;

-- ================

    -- 方式二
--插入1000条数据
-- 1. 先删除同名存储过程(避免重复创建报错)
DROP PROCEDURE IF EXISTS insert_batch_user;

-- 2. 创建存储过程
DELIMITER //  -- 临时修改语句结束符为//(避免和存储过程内的;冲突)
CREATE PROCEDURE insert_batch_user()
BEGIN
    DECLARE i INT DEFAULT 1;  -- 定义循环变量,初始值1
    WHILE i <= 100 DO  -- 循环100次
        INSERT INTO app_user(
            `name`,
            `email`,
            `phone`,
            `gender`,
            `PASSWORD`,
            `age`
        )
        VALUES(
            CONCAT('用户', i),
            CONCAT(FLOOR(RAND()*100000000), '@qq.com'),
            CONCAT('18', FLOOR(RAND()*900000000 + 100000000)),
            FLOOR(RAND()*2),
            MD5(UUID()),
            FLOOR(RAND()*50 + 18)
        );
        SET i = i + 1;  -- 变量自增
    END WHILE;
END //
DELIMITER ;  -- 恢复语句结束符为;
-- 3. 调用存储过程(执行批量插入)
CALL insert_batch_user();
-- 4. 验证结果(可选)
SELECT COUNT(*) FROM app_user;  -- 查看插入的总条数


--查询测试
SELECT * FROM app_user WHERE `name` = '用户9999'

--查询
SELECT * FROM app_user WHERE `name` = '用户9999'


SELECT * FROM student 

-- id------表名------字段名
CREATE INDEX id_app_user_name ON app_user(`name`)
SELECT * FROM app_user WHERE `name` = '用户9999'
EXPLAIN SELECT * FROM app_user WHERE `name` = '用户9999'

注意:索引在小数据量的时候,作用不大,但是在大数据的时候,区别十分明显。

索引原则

  • 索引不是越多越好

  • 不要对进程变动数据加索引

  • 小数据量的表不需要加索引

  • 索引一般加在常用来查询的字段上

用户管理

可视化管理

sql命令创建用户

sql 复制代码
-- 用户管理==============
-- sql命令创建用户
-- 创建用户
-- 语法:CREATE USER 用户名 IDENTIFIED by 密码
CREATE USER zhangsan IDENTIFIED by '123456'

-- 修改当前用户密码
SET PASSWORD('1111111')

--重命名  RENAME USER 原来的名字 to 新名字
RENAME USER zhangsan to zhangsan2

-- 用户权限 ,ALL PRIVILEGES除了给别人授权,其他都能做
 GRANT ALL PRIVILEGES ON *.* TO 'zhangsan2'

-- 查看权限
SHOW GRANT FOR zhangsan2 -- 查看指定用户的权限

-- 撤销权限 REVOKE 哪些权限,在哪个库撤销,给谁撤销
REVOKE ALL PRIVILEGES *.* FROM '张三'

Mysql备份

为什么要备份:

  • 保证重要的数据不丢失

  • 数据转移

MySQL数据库备份的方式

  • 直接拷贝物理文件

  • 通过可视化软件

  • 使用命令行导出:mysqldump 命令

    导出命令

    sql 复制代码
    -- 导出
    -- cdm中导出命令如下:mysqldump -h主机 -u用户名 -p密码 数据库 表名 >物理磁盘位置
    mysqldump -hlocalhost -uroot -p123456 school1 student >D:/a.sql
    --导出多张表:cdm中导出命令如下:mysqldump -h主机 -u用户名 -p密码 数据库 表1 表2 表三 >物理磁盘位置
    mysqldump -uroot -p123456 school student result >D:/a.sql
    
    -- 导入
    在登录mysql的情况下:-- source D:/a.sql
      source 备份文件
    在不登录的情况下
      mysql -u用户名 -p密码 库名 < 备份文件 

规范设计数据库

为什么需要设计?

当数据库比较复杂的时候,我们需要设计数据库

糟糕的数据库设计:

  • 数据冗余,浪费空间

  • 数据库插入和删除都会非常麻烦、异常

  • 程序的性能差

良好的数据库设计:

  • 节省内存空间

  • 保证数据库的完整性

  • 方便我们开发系统

软件开发中,关于数据库的设计

  • 分析需求:分析业务和需要处理的数据库的需求

  • 概要设计:设计关系E-R图

数据库的设计步骤

  1. 需求分析

  2. 概念设计

  3. 逻辑设计

  4. 物理设计

  5. 优化评审

三大范式

  • 第一范式:字段原子化,不可再分

    • 第一范式的目标是确保每列的原子性,如果每列都是不可再分的最小数据单元,则满足第一范式
  • 第二范式:满足第一范式的基础上,消除部分依赖,必须有主键

    • 在满足 1NF 的基础上,非主键字段必须完全依赖于主键,不能只依赖主键的一部分(仅针对 "复合主键" 生效)。
  • 第三范式:满足第二范式的基础上,消除传递依赖

    • 在满足 2NF 的基础上,非主键字段不能依赖于其他非主键字段

规范化和性能的关系(规范数据库的设计,成为相反关系)

  • 关联查询的表不得超过三张表

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

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

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

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

SQL注入问题

SQL注入是什么?

复制代码
    1.SQL 注入是**黑客通过构造恶意 SQL 语句,插入到应用程序的输入框 / 参数中**,让数据库执行非预期的 SQL 操作,从而窃取、篡改甚至删除数据库数据的攻击方式。

    2.SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

例如:登录时,正常业务逻辑是:用户输入账号 / 密码,程序拼接 SQL 查询

sql 复制代码
-- 预期的正常SQL(用户输入:账号=小明,密码=123456)
SELECT * FROM user WHERE username='小明' AND password='123456';

黑客恶意输入:在账号输入框填 小明' OR '1'='1,密码随便填,拼接后的 SQL 变成:

sql 复制代码
-- 恶意SQL(OR '1'='1'永远为真,绕过密码验证)
SELECT * FROM user WHERE username='小明' OR '1'='1' AND password='任意值';

结果是无需正确密码,直接可登录成功!

SQL注入的危害性:

  • 数据泄露:窃取用户手机号、密码、身份证、订单等敏感数据

  • 越权操作:绕过登录验证,登录管理员账号,篡改用户信息、订单状态;

  • 数据破坏:删除 / 修改数据库表、清空数据,导致业务无法运行;

  • 服务器控制:通过注入获取数据库服务器权限,进而控制整个服务器

如何防止SQL注入?

使用预编译语句:把 SQL 语句的 "结构" 和 "参数" 分开,参数部分由数据库自动转义,杜绝拼接风险。

例如在Java中

java 复制代码
// 错误写法(直接拼接,易注入)
String sql = "SELECT * FROM user WHERE username='" + username + "' AND password='" + password + "'";
Statement stmt = conn.createStatement();
stmt.executeQuery(sql);

// 正确写法(预编译,参数化)
String sql = "SELECT * FROM user WHERE username=? AND password=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);  // 参数1:用户名
pstmt.setString(2, password);  // 参数2:密码
  // 参数2:密码
pstmt.executeQuery();
相关推荐
m0_528749001 小时前
sql基础查询
android·数据库·sql
先做个垃圾出来………2 小时前
Django vs Flask 异步视图性能对比:数据驱动的深度分析
数据库·django·flask
今儿敲了吗2 小时前
27| 魔法封印
数据结构·c++·笔记·学习·算法
桂花很香,旭很美2 小时前
Anthropic Agent 工程实战笔记(四)长任务与多 Agent
笔记·架构·agent
今儿敲了吗2 小时前
30| 木材加工
数据结构·c++·笔记·学习·算法
土拨鼠烧电路2 小时前
笔记08:供应链的生命线:预测、库存与韧性
人工智能·笔记
xhyu612 小时前
【学习笔记】推荐系统 (3.召回:矩阵补充、线上服务、双塔模型)
笔记·学习·矩阵
wb1892 小时前
LVS各种调度以及Haproxy调度重习
笔记·云计算·lvs·haproxy
tryCbest2 小时前
Oracle恢复已损坏定时任务(Jobs)
数据库·oracle