1、学数据库需要知道哪些东西
- 什么是数据库设计?
- 数据库设计的步骤
- 数据库概念模型
- 会画、会看E-R图
- 了解三大范式
- 数据库的一些操作( 普通程序员也就停留在这里,即:CRUD程序员[ 增删查改 ] )
- 1)、数据库设计
- 根据用户的需求,在具体的数据库管理系统上,设计数据结构和建立数据库的过程
-
2)、设计步骤
-
需求分析 ——> 概念结构设计 ——> 逻辑结构设计 ——> 数据库的实施 ——> 数据库的运行与维护( 升级 )
- 注:一般都是直接搞数据库实施了,但是数据库设计是一条路( 数据库架构师 ),就需要这么玩
-
需求分析 ——> 概念结构设计 ——> 逻辑结构设计 ——> 数据库的实施 ——> 数据库的运行与维护( 升级 )
-
3)、数据库概念模型
-
(1)、相关概念
- 数据:客观事物的描述 如:一个人有哪些? —— 姓名、年龄.....
- 数据库:长期保存到计算机中的有组织、可共享的数据集合
- 数据库管理工具( DBMS ):用来管理数据库的,负责建立数据库、使用、维护的软件,如:sqlyog、Navicat
-
(1)、相关概念
-
-
(2)、概念模型
-
基本
- 实体:客观存在并相互区分的事物。类似于java中的类
- 属性:实体具有的某一特征。和java中的属性一样
- 键:主键、外键
- 主键:标识事物的唯一性,就像身份证号一样
- 外键:是另一个事物的主键
- 实体型:具有相同的实体必有的特征
- 实体集:相同的实体类型的集合
-
联系:实体之间的关系
-
实体之间的关系:
- 一对一、一对多 / 多对一、多对多
- 一对一、一对多 / 多对一、多对多
-
实体之间的关系:
-
基本
-
(2)、概念模型
-
-
(3)、了解E-R图 —— 用来描述实体之间的关系。网上找图来看
- 长方形:实体
- 圆形:属性
- 菱形:关系
-
(3)、了解E-R图 —— 用来描述实体之间的关系。网上找图来看
-
-
(4)、三大范式
- ①、范式的作用
- 用来更好的设计数据库,专门用来让人遵循的规则,目的:减少数据冗余
-
具体的三大范式
- 第一范式:确保每一列的原子性( 原子性:即列的字段不可以再分出其他字段,如:学院,还可以分大数据与信息工程、文化与传媒学院... )
- 第二范式:在第一范式的前提下,确保每张表只做一件事
- 第三范式:在第一、第二范式的前提下,确保表中的每一列都与主键直接相关,而不是间接相关
-
(4)、三大范式
-
4)、数据库介绍
- 大型数据库:DB2、Oracle( 个人认为:DB2比Oracle更好 ) 一般是银行企业使用
- 中型数据库:sqlServer
- 小型数据库:mysql 一般是小型企业使用
-
详细区分:
- 关系型数据库
- MySQL、SqlServer、DB2
- 这种数据库是通过表与表之间、列与列之间进行数据的存储,如:学生表
-
非关系型数据库
- Redis、MongDB
- 这种数据库是通过对象的属性来进行存储数据
-
5)、学习数据库就用:mysql sql语句都是相通的,只是有细微的区别而已
-
(1)、为什么使用mysql?
- 易于学习和掌握
- 性能高,即:访问速度较快
- 最重要的一点:开源、免费
-
(1)、为什么使用mysql?
以上这些内容不明白的也没事儿,慢慢的就懂了
2、开始学习MySQL
- 1)、安装MySQL ( 个人建议最好下载5.7版的,也有人说5.5稳定,但是我个人认为:5.7更稳定,另外到了公司就需要根据公司要求来弄版本)
- MySQL官网:MySQL
- MySQL完整版学习手册:MySQL :: MySQL 5.7 Reference Manual
-
(1)、下载MySQL地址:MySQL :: Download MySQL Community Server
- 注意:我这种是解压方式安装MySQL,有人也会用 .exe的方式进行安装( 但是:个人建议别用 . exe的方式进行安装,因为卸载麻烦,需要删除注册表中的MySQL ,不然卸载不干净 )
- 然后:下载好之后,把压缩包解压到自己要放的盘符路径中即可
- 个人建议:最好单独建一个安装文件夹,然后安装一个程序 在里面新建一个文件夹,然后把路径选择进去
-
-
(2)、现在来正式进行安装
-
①、配置环境变量
-
找到刚刚解压的MySQL压缩包,然后进到bin目录下,把这个路径复制一下,如:我的
-
找到刚刚解压的MySQL压缩包,然后进到bin目录下,把这个路径复制一下,如:我的
-
①、配置环境变量
-
(2)、现在来正式进行安装
-
-
- ②、进到电脑的path目录中,然后把复制的路径加进去,最后保存( 怎么进到path中去,win10、win7的区别就不用说明了吧 )
-
③、再次回到刚刚的解压包那里,即:bin的上一级,然后建一个my.ini配置文件,如:我的
-
-
④、用记事本 / 自己配置的其他软件( 如:我是用notepad++ )打开这个文件夹,创建如下内容:
-
注意:盘符路径切换成自己的,即:D:............mysql-5.7.34的路径。另外:注意[ ] 是英文输入法下打出来的,这种已经不想再说明了,吐了,因为:javaSE的时候已经说明过N多次了
-
-
⑤、在自己的电脑上找到命令提示符,用管理员身份打开,切记:一定要用管理员身份打开,不然配置不成功
-
⑥、进到Dos窗口之后( 即:上面的命令提示符 ),把路径切换到自己刚刚解压的压缩包的bin目录下,然后输入 mysqld -install 这是在安装mysql。切记:-install前面有一个空格,注意看结果,success / OK,不然安没安装成功都进行下一步了。如下:
-
-
-
-
-
额外补充一下:这里使用mysql -install时,有可能自己的电脑会报:msvcr120.dll找不到,尝试重装程序可能得以解决
- 这种问题一是买电脑商家给你装系统时把你小小的坑了一下,没给你装这些系统程序( 一般都不会这样,在官铺买的电脑不会这么整人的啊 )
-
第二种情况就是最常见的情况:自己把系统进行升级了,这也是必经的一个过程 ( 就是自己的电脑买来的时候发现是家庭版的,然后自己把系统升级到专业版了 —— 注:如果自己的电脑是家庭版的,那么就自己去官网下载专业版,然后找别人 / 自己买一个专业版密钥,把自己的电脑重装系统,弄为专业版,然后通过密钥永久激活 。如果自己的电脑不是专业版的,那么现在玩玩没什么,但是到了后面玩分布式开发时,总会因为家庭版的原因发生各种各样的问题 )
- 回到正题:这种把系统升级之后,发生这种msvcr120.dll文件找不到是因为自己对系统进行升级时操作不当 / 下载的系统有问题,从而导致重装系统之后根本没有这个msvcr120.dll文件( 一般发生这种情况了,少的不止这一个文件,而是起码有近10个文件是缺失的 )
-
解决办法:下载修复工具,把缺失的文件补回来
- 下载地址:https://pan.baidu.com/s/1BjUSH94X7MpBEeIa0DET5w
- 提取码:nhlb
-
打开解压包,运行下面的程序,然后跟着步骤来就可以了
-
额外补充一下:这里使用mysql -install时,有可能自己的电脑会报:msvcr120.dll找不到,尝试重装程序可能得以解决
-
-
-
-
-
-
- 如果经过上面的方式都还没解决的话,那就问题更大了,自行百度找适合自己电脑的解决方案吧
-
-
-
-
-
-
⑦、上一步成功之后,然后再输入 mysqld --initialize-insecure --user=mysql 这是初始化数据文件( 即:在my.ini中datadir后面有一个data,这里就是初始化这个data,然后在目录中自动生成data文件夹 )
- 注意:--initialize前面是有一个空格 和 两个 - 。user前面也是一样的
-
成功之后,它会自动跳转到bin目录
-
⑦、上一步成功之后,然后再输入 mysqld --initialize-insecure --user=mysql 这是初始化数据文件( 即:在my.ini中datadir后面有一个data,这里就是初始化这个data,然后在目录中自动生成data文件夹 )
-
-
-
-
⑧、退出Dos窗口,重新进去( 不用管理员也可以 ),输入命令 mysql -uroot -p 回车,在输入password( 即:密码)时直接回车,因为在配置my.ini时有一个skip跳过密码登录的配置,成功进到sql之后,目录名字变了,成为了mysql,如下:
-
-
解决办法:我接下来的最后一步那里,开启mysql服务 使用命令开启 或 快捷键ctrl+alt+delete,选择任务管理器,选择服务,把mysql服务开启
-
-
⑧、退出Dos窗口,重新进去( 不用管理员也可以 ),输入命令 mysql -uroot -p 回车,在输入password( 即:密码)时直接回车,因为在配置my.ini时有一个skip跳过密码登录的配置,成功进到sql之后,目录名字变了,成为了mysql,如下:
-
-
-
-
⑨、进入到mysql之后,开始更改mysql的登录密码。输入 update mysql.user set authentication_string = password( '这里面就是自己要设置的mysql密码' ) where user = 'root' and Host = 'loaclhost';
-
注意事项:
- password里面就是以后登录数据库的密码,所以一定需要记住,不然很头疼
- 最重要的一点:上述语句是 ; 分号结尾的,千万别漏掉这个了
- 多提一嘴:上述的指令就是一个数据库的修改指令而已,数据库本质是文件,所以上述命令就是修改文件( 数据库中说的表 ) 的信息而已
-
⑨、进入到mysql之后,开始更改mysql的登录密码。输入 update mysql.user set authentication_string = password( '这里面就是自己要设置的mysql密码' ) where user = 'root' and Host = 'loaclhost';
-
-
-
-
⑩、刷新权限。上述的修改密码执行成功之后,接着输入 flush privileges;
-
注意事项:
- 还是记得 ; 分号结尾
-
在这一步可能会由于自己电脑的配置、性能等乱七八糟的原因导致在这里显示配置成功了,但是后面使用密码登录数据库时却发现登录不进去
- 因此建议:这里的刷新权限多执行几次
-
取消无密码登录数据库。回到my.ini文件中,把那个skip跳过密码登录语句注释掉( 在前面加一个 # 就搞定了 ),如下:
-
-
⑩、刷新权限。上述的修改密码执行成功之后,接着输入 flush privileges;
-
-
-
-
最后重启mysql服务,有两种方式
-
1)、使用命令关闭 / 开启
- 退出刚刚的Dos窗口,再重新进去( 记得以管理员身份进去 ) 输入 net stop mysql 这是关闭mysql服务,记得先关闭mysql服务,然后再开启,这样才可以让刚刚做的那些操作生效。
- 等成功关闭之后,接着输入 net start mysql 这是开启mysql服务
-
1)、使用命令关闭 / 开启
-
最后重启mysql服务,有两种方式
-
-
-
-
-
2)、手动开启 / 关闭mysql,直接按 ctrl + alt + delete , 选择任务管理器,选择服务,找到mysql,然后鼠标右键停止 / 开启
-
-
2)、手动开启 / 关闭mysql,直接按 ctrl + alt + delete , 选择任务管理器,选择服务,找到mysql,然后鼠标右键停止 / 开启
-
以防万一:还是测试一下吧,看看有没有配置成功
-
进到Dos窗口中( 不用管理员身份都行 ),即:win + r,然后输入cmd确认进去
-
-
进到Dos窗口中( 不用管理员身份都行 ),即:win + r,然后输入cmd确认进去
-
-
-
-
- 要卸载mysql就只需要:把解压的文件删除就行
- 注:需要彻底删除 即:选择文件夹 按shift+delete彻底删除( 回收站都找不到 )
-
-
- 附:安装教程链接
-
2)、数据库安装好了之后,数据库管理工具可以采用Navicat / sqlyog.... ——— 数据库管理工具就是一个连接数据库,然后方便人看的可视化工具( 不然在Dos窗口中做数据库不得麻烦死 )
- 注:Navicat使用注册机破解 / sqlyog注册码这些我不进行说明,留点空白,自行摸索。
- 另:我用的是sqlyog,所以我的示例是sqlyog写的,不过不影响,语法都一样,只是可视化界面不一样而已
-
3)、开始玩数据库
-
1、准备工作:基础知识
-
(1)、数据库的类型( 这是对于数据库本身而言的 )
-
①、数据库列字段的类型
-
壹、数值类型
- tinyint 十分小的数据 1字节
- smallint 较小的数据 2字节
- mediumint 中等大小的数据 3字节
- int 标准的整数 4字节( 常用 )
- bigint 较大的数据 8字节
- float 单精度浮点数 4字节
- double 双精度浮点数 8字节
- decimal 字符串形式的浮点数 一般金融相关会用这个decimal
-
壹、数值类型
-
①、数据库列字段的类型
-
(1)、数据库的类型( 这是对于数据库本身而言的 )
-
1、准备工作:基础知识
-
-
-
-
-
贰、字符串
- char 固定大小的字符串( 不可变长字符串 ) 取值是0 · 255
- varchar 可变字符串( 会随着内容的增加而自动增加长度 ) 取值0 · 65535 java中String类型,在数据库中就可以用这个来对应
- tinytext 微型文本串 取值2^8 - 1
- text 大文本 取值2^16 - 1 ( 就像写博客这种,就是需要很大的空间来装,就可以用text )
-
贰、字符串
-
-
-
-
-
-
-
-
叁、时间日期 ———— 和java中java.util.Data包下的这个data对应的日期差不多
- data 日期格式,如:YYYY-MM-DD
- time 时间格式,如:HH:mm:ss
- datetime 标准时间格式,如:YYYY-MM-DD HH:mm:ss ( 最常用 )
- timestamp 时间戳 1970.1.1开始 — 现在的毫秒数 ( 也常用 )
- year 表示年份
-
叁、时间日期 ———— 和java中java.util.Data包下的这个data对应的日期差不多
-
-
-
-
-
-
-
-
肆、null
- 没有值,未知
- 注意:别用null进行运算,最终的结果为:null
-
肆、null
-
-
-
-
-
-
-
②、数据库行字段的类型( 重点 )
- Unsigned 无符号整数 即:声明该列不能为负数
- zerofill 用o填充 即:数值的位数不够的时候 如:int(5) 输入的值是4 那么在存储的时候这个位数不够,则:就会用00004来保存
- auto_increment 自增( 通常是用来设置唯一的主键 ) 即:自动在上一条的基础上+1( 默认是这样 )
- 注意:这个必须是整型才可以,如:int,不然会报错
- 这个可以在后面自己添加自增的步长是多少
- not null 非空 即:必须填内容,不填就会报错
-
default 默认值 即:设置默认的值,在需要设置默认值的字段中使用default这个关键字,然后后面跟想要设置默认值即可( 注意:自己定义的字段的列类型啊
- 别搞个:字段的列类型是int , 然后用default '默认值',这样搞个字符串类型的默认值,这要不得啊
-
②、数据库行字段的类型( 重点 )
-
-
-
-
-
(2)、对于数据库里面 —— 即:对于表本身
-
①、数据库引擎( 详细的知识最好学完自行去百度一下,初学者会看不懂,留个印象,学完数据库的全部知识,再把这个引擎看一下,上档次的面试贼喜欢问 ,还有后面要玩的索引,数据库优化[ 最低要求答出7条以上 ] )
- MYISAM —— 这是早些年使用的
-
INNODB —— 后面出现的
-
由图来看:INNODB更好,但是:在某些时候,MYISAM更爽
-
-
①、数据库引擎( 详细的知识最好学完自行去百度一下,初学者会看不懂,留个印象,学完数据库的全部知识,再把这个引擎看一下,上档次的面试贼喜欢问 ,还有后面要玩的索引,数据库优化[ 最低要求答出7条以上 ] )
-
(2)、对于数据库里面 —— 即:对于表本身
-
-
-
-
-
- MYSIAM 节约空间 速度较快
- INNODB 安全性高 支持事务处理 多表多用户操作
-
-
-
-
-
-
-
②、数据库中表在物理空间的位置
-
都在自己安装的数据库目录中的data文件夹下,一个文件夹对应一个数据库,里面就有相应的表
-
对图中几个文件后缀的说明:
- INNODB引擎,在数据库表中只有一个*.frm的文件 和 上一级目录的ibd
-
MYISAM引擎:
- *.frm 表结构定义的文件
- *.myd 数据文件( data)
- *.myi 索引文件( index )
-
-
都在自己安装的数据库目录中的data文件夹下,一个文件夹对应一个数据库,里面就有相应的表
-
②、数据库中表在物理空间的位置
-
-
-
-
-
-
③、设置数据库表的默认编码 charset = utf8
-
直接打开my.ini,在里面配置如下:
-
- 不设置的话:表的默认编码是Latinl 这种编码不支持中文( 图中内容和我不一样的,这没影响的啊,因为那是我设置的默认时区 —— 这是后续使用IDEA链接数据库时的一个小bug )
-
直接打开my.ini,在里面配置如下:
-
③、设置数据库表的默认编码 charset = utf8
-
-
- 2)、开始玩sql语法
-
-
-
玩数据库玩的是什么?
- 数据库本身 > 数据库中的表 > 数据库表中的信息( 数据 )
- 数据库本身 > 数据库中的表 > 数据库表中的信息( 数据 )
-
玩数据库玩的是什么?
-
-
(1)、对于数据库本身 —— 创建、使用、删除、查看数据库
-
先讲一下数据库中的注释
- 行注释
- -- 注释内容
- 注意:--之后是空了一格的 这也是我在java基础篇中说 // 注释内容 空一格的原因,就是为了给这里养成习惯
-
多行注释
- /* 注释内容 */
-
先讲一下数据库中的注释
-
-
-
-
-
-- mysql中不区分大小写 数据库中的符号输入 和 java中一样 是英文输入法下打出的 -- 链接数据库在安装数据库时已经玩了 即:mysql -uroot -p 所以不再演示 -- 当然:后面这些都是通过语句来玩的,只要安装了数据库管理工具( 即:数据库的可视化软件 ) 是可以通过鼠标点击式玩的 -- 1、创建数据库 /* 语法: create database [ if not exists ] 要创建的数据库名; 注意:每一个sql语句结束,最好使用 ; 分号结尾 */ CREATE DATABASE IF NOT EXISTS `sqlstudy`;
-- 选择这一句运行就行了 后续的也是一样的 -- `sqlstudy` 外面的` ` 是tab按键上面 esc按键下面的那个按键( 即:在js中说的那个飘儿字符 ) -- 加这个飘儿字符的原因,为了解决字段与数据库中本身有的名字冲突的情形
—— 这个在数据库中解决字段冲突都通用 -- IF NOT EXISTS是为了判断要创建的数据库在数据库是否存在,如果不存在才创建 这也是为了严谨性 -- 所以创建时最好加上这个逻辑判断( 当然只要保证数据库中并没有要创建的这个数据库,则不要这句话也行的 )
-- 2、删除数据库 /* 语法: drop database [ if exists ] 要删除的数据库名 */ DROP DATABASE IF EXISTS `sqlstudy`; -- 这里最好也加上判断
-- 3、使用数据库 /* 语法: use 要使用的数据库名 */ USE `sqlstudy`;
-- 4、查看数据库 /* 语法: show database */ SHOW database; -- 这是查看所有的数据库
-
-
-
-
-
(2)、对于数据库中的表本身
-
-- 二、对于数据库中表本身 -- 1、创建表 /* 语法: create table ] if not exists ] `要创建的表名`( `字段名1· 数据类型( 空间大小 ) 其他的说明, `字段名2· 数据类型( 空间大小 ) 其他的说明, ......... `字段名3· 数据类型( 空间大小 ) 其他的说明 )[ 数据引擎类型 字符集编码 ]; 注意:每一行之间使用 , 逗号隔开 最后一个不用 */ CREATE TABLE IF NOT EXISTS `test`( -- 这里其实不用加 ·· 这个飘字符都可以 -- 因为这个test名字并没和数据库中原有的名字冲突 `id` INT AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT'编号', -- comment就是解释的意思,即:对改字段进行说明 -- primary key就是主键的意思 `name` VARCHAR(20) NOT NULL COMMENT'名字', `sex` CHAR(2) NOT NULL COMMENT'性别' )ENGINE = INNODB DEFAULT CHARSET = utf8; -- engine 就是引擎的意思 default charset就是设置表的字符编码 虽然在安装mysql时在my.ini中设置了默认字符编码 -- 但是:为了保险起见,所以在这里又加入和字符编码 -- 2、删除表 /* 语法: drop table [ if exists ] 要删除的表名;; */ DROP TABLE IF EXISTS `test`; -- 3、修改表 -- (1)、对表重命名 /* 语法: alter table 旧表名 rename as 新表名 */ ALTER TABLE `test` RENAME AS `person`; -- (2)、给表添加新的字段 /* 语法: alter table 表名 add 字段名 数据类型( 空间大小 ) 其他说明; */ ALTER TABLE `person` ADD `phone` VARCHAR(12) NOT NULL COMMENT'电话号码'; -- (3)、修改字段的约束 / 数据类型等 /* 语法: alter table 表名 modify 字段名 数据类型( 空间大小 ) 其他说明; */ ALTER TABLE `person` MODIFY `phone` VARCHAR(20) NULL COMMENT'电话号码'; -- 对alter的一个补充 可以跟change 即:字段重命名 /* 语法: alter table 表名 change 旧字段名 新字段名 [ 数据类型( 空间大小 ) 其他说明 ] ; 从这个结构可以看出:其实这个change也可以实现修改字段的约束,只是不建议用,这个change最好用来字段重名 而:修改字段的约束就用modify */ ALTER TABLE `person` CHANGE `phone` `phoneNumber`; -- 对alter的第二个补充 删除表的字段 /* 语法: alter table 表名 drop 字段名; */ ALTER TABLE `person` DROP `phoneNumber`;
-
-
补充:外键 —— 其实不太想说明,因为外键这个东西切记最好别出现在mysql中,要实现外键的效果最好在程序中去实现( 如:java中 ),因为数据库的本质是存储数据的,所以不应该出现另外任何的附属操作( 这个就和javaSE中说的线程一样,线程就是一个资源类,不应出现任何的附属操作 ),另外:外键会增加表与表之间的耦合度,即:使用了外键,那么要删除表就需要先删除从表( 即:一个表A的一个字段当做另一个表B的主键,这里的B表 ),然后再删除主表( 即:前面说的A表 ),在表很少的情况使用外键还没什么,但是试想一下:要是表很多的话,那么使用了外键的话,删表不是很麻烦?这不是增加了工作量吗。因此:这里就当做知识来了解吧!
-
添加外键的手段有两种,一种是在创建表的时候就添加;另一种就是把表创建完了之后,再添加外键,这里只弄出语法,不演示,因为:这种东西都是一看就会的,顺便养成一种学习的思想,不然新技术出来自己摸索文档不是很难受吗。
-
语法: 在建表时就进行添加外键 key ·FK_要添加为外键的字段名`( ` 要添加为外键的字段名 ` ), -- 这里`FK_要添加为外键的字段名`其实是给外键起名字,只是格式最好是这样而已 -- 然后这句代码以 , 逗号结尾 constraint ` 上一步起的外键名 ` foreign key( ` 要添加为外键的字段名 ` ) references `从表的名字`( ` 和主表中要作为外键的相同字段名 ` ); -- constraint是约束的意思,foreign key就是外键的关键字,references就是涉及的意思 -- 上述的 ·· 还是tab按键上面 esc按键下那个飘字符,下面也是 在建表完成之后进行外键添加 alter table `主表的名字` add constraint `外键的名字` foreign key( ` 作为外键的列 ` ) references 从表名字( ` 和主表中要作为外键的相同字段名 ` );
-
-
添加外键的手段有两种,一种是在创建表的时候就添加;另一种就是把表创建完了之后,再添加外键,这里只弄出语法,不演示,因为:这种东西都是一看就会的,顺便养成一种学习的思想,不然新技术出来自己摸索文档不是很难受吗。
前面这些都是基操
后续的都是重点
-
-
-
(3)、DML语言 —— 即:所谓的增删改语言( data modify language ) 需要全部记住
- insert
- delete / truncate
- update
-
(3)、DML语言 —— 即:所谓的增删改语言( data modify language ) 需要全部记住
-
-
-
-
-
准备工作:先创建一个数据库 和 表
-
CREATE DATABASE IF NOT EXISTS `sqlstudy`; USE `sqlstudy`; CREATE TABLE IF NOT EXISTS `student`( `snum` VARCHAR(20) NOT NULL PRIMARY KEY COMMENT'学号', -- '学号' 这里的' ' 是单引号 `name` VARCHAR(15) NOT NULL COMMENT'学生名字', `sex` CHAR(2) NOT NULL COMMENT'学生性别' CHECK( `sex` = '男' OR `sex` = '女' ), -- check()就是为了约束的 -- 在这里就是为了输入时只能输入男或女 `phone` VARCHAR(12) NOT NULL COMMENT'学生电话' )ENGINE = INNODB DEFAULT CHARSET = utf8; -
创建好之后效果如下:
-
-
准备工作:先创建一个数据库 和 表
-
-
-
-
-
-
①、给表中增加数据
-
效果如下:
-- ①、给表中添加数据 /* 语法: insert into 表名( `要添加数据的字段名1` , `要添加数据的字段名2`..... ) values( '字段1的值' , '字段2的值'..... ); 注:1、如果要赋多个值 则:在values后面用多个()括号就可以了,然后多个()之间使用 , 逗号隔开 如下: insert into 表名( `要添加数据的字段名1` , ` 要添加数据的字段名2 ` ) values( '字段1的值1' , '字段2的值1' ..... ), ...... ( '字段1的值2' , '字段2的值2' ..... ); 2、表名()这个括号里面的 `` 是tab按键上面、esc按键下面的那个飘字符 values()这个括号中的 '' 是单引号 如果嫌麻烦 那么:表名()这里面的 `` 不用每个都写 只要遇到和mysql中原有的名字冲突再加``都行 3、还是前面说的,mysql中的符号都是英文输入法下打出的( 应该说:编程中和符号相关的符号都是英文输入法下的) */ INSERT INTO `student`( `snum` , `name` , `sex` , `phone` ) VALUES( 'xh123001' , '紫邪情' , '女' , '1234567' ); INSERT INTO student( snum , `name` , sex , phone ) VALUES( 'xh123002' , '梅雪嫣' , '女' , '9694321' ), ( 'xh123003' , '韩非' , '男' , '9964367' );
-
-
①、给表中增加数据
-
-
-
-
-
-
②、删除表中的数据
-
效果如下( 韩非的信息没了 ):
-- ②、删除表中的数据 /* 有两种方式 第一种: 语法 delete from `表名` [ 条件 ]; 第二种:下面这种方法是直接把表的所有数据清空了 但是不影响表的结构( 即:表中有哪些字段不会变 ) 所以:下面这种方法用得不多,但是有时需要用 truncate table `表名`; delete和truncate的区别 delete是单纯的删除数据,不会影响表的结构,但是:如果表中的字段使用了自增( 即:auto_increment ) 那么:这个自增的顺序是不会被清除的 ( 如:该字段在删除之前的自增序号为3,那么删除之后,下一次就是从4开始 )
另外:delete删除只是一种状态的删除,即sql只是标记要删除的那一行数据为删除状态,因此:数据的空间并没有释放
这样是为了可以数据复用,下一次创建时就不需要再开辟新空间了,直接使用留下的这个空间
所以:这种删除是可以恢复的,但是有点麻烦,不演示了 —— 面向百度编程 而truncate是清空整个表中的数据,也不会影响表的结构和索引约束( 索引在后续做说明 ), 但是:自增会归0( 即:上一次自增为3,那么下一次重新存数据就是从0开始 )
同时:truncate还不会影响事务
*/ DELETE FROM student WHERE `name` = '韩非'; TRUNCATE TABLE student;
-
-
②、删除表中的数据
-
-
-
-
-
-
③、修改表中的数据
-
效果如下:
-- ③、修改表中的数据 /* 语法 update 表名 set 列字段名 = 要修改的值..... 条件 注:不加条件的话是把整个表中符合条件都修改了 所以需要指定是哪一行的数据要做修改 说明: 多个列字段名之间使用 , 逗号隔开 知识补充:条件 where子句 后面可以跟哪些 运算符: > < >= <= !=或<>这两个都是不等于的意思
and or 与、或嘛
区间: between.....and..... 指的是:在什么之间 是[ ] 取值范围是前后双开的 */ UPDATE student SET `sex` = '男' WHERE `snum` = 'xh123001';
-
-
③、修改表中的数据
-
-
-
-
-
(4)、DQL语言 —— 即:所谓的查询语言( date query language ) 最重要:需要达到贼熟练
- 所有的查询都需要用它 select
- 数据库中最核心、最重要的语句
- 使用频率最高的语句
-
-
-
-
-
select完整语句
-
-- select语句 /* select完整语法 select colnum_name... from table_name -- colnum_name 是要查询的列字段名 table_name 为表名 [ left or right or inner ] join table_name on 链接条件 -- 这是联表查询 where子句条件 -- 指出结果需要满足的条件 group by 要分组的字段 -- 这是分组 having 过滤条件 -- 这是为了过滤掉一些信息 order by 需要进行排序的字段 -- 这是为了以某一字段进行排序 limit dateStart , pageSize; -- 这是为了让查询出来的数据进行分页显示 以上的这个语句顺序都不能乱( 可以少,但不能把顺序打乱 ),需要用对应的语句时,只能以这个顺序来进行写sql
接下来会依次对上面的语句进行说明,但是不是按顺序来进行说明的,而是从简到难 */
-
-
select完整语句
-
-
-
-
-
-
①、select的简单玩法
-
-- ①、查询全部 SELECT * FROM student; -- * 就表示所有 -- ②、查询字段字段 SELECT snum , `name` , phone FROM student; -- ③、有时列字段名 / 表名 不是那么的见名知意,因此:我们还可以自己给它起别名,使用 as 关键字 -- 不用as 直接跟自定义别名也可以 SELECT snum AS studentNumber , `name` studentName , phone FROM student; -- 这样起了别名之后,我们用的时候,就可以直接使用别名了
-
-
①、select的简单玩法
-
-
-
-
-
-
②、有时发现查询出来的结果有重复的,怎么去重?
-
使用distinct关键字
-
如:在student表中新增一个重复数据
-
这样虽然学号不一样,但是:其他信息是重复的,所以查询一下:
-
这不是想要的结果,所以来去重一下
-
加上distinct关键字就去重成功了
-
-
-
-
如:在student表中新增一个重复数据
-
使用distinct关键字
-
②、有时发现查询出来的结果有重复的,怎么去重?
-
-
-
-
-
-
③、where条件子句 —— 这个其实已经玩过了,如下:
- 作用:检索数据中符合条件的值
-
-- ⑤、where条件子句 SELECT * FROM student WHERE snum = 'xh123001'; -- 单条件查询 SELECT * FROM student WHERE snum = 'xh123001' AND `name` = '紫邪情'; -- 多条件查询
-
③、where条件子句 —— 这个其实已经玩过了,如下:
-
-
-
-
-
-
-
where查询的延伸 —— 模糊查询
-
-- 对where查询的补充 —— 模糊查询 -- 利用运算符 和 区间查询已经说明过了 -- 那么在不确定完整信息、只记得大概信息的情况下怎么查询 -- 就两种 like 和 in /* 对于like % 表示前面 / 后面 / 中间有 0 - 任意个字符 _ 表示一个字符 当然 __ 两个就表示两个字符,依次类推 */ -- 这里假设我要查询紫邪情这个人的信息,但是:我只知道她姓紫,然后她名字后面有多少个字我都不知道 SELECT * FROM student WHERE `name` LIKE '紫%'; -- 这样就可以表示出来了,姓紫,后面的字是任意个 -- 假设:我要查紫邪情的信息,但是我只知道她名字的中间那个字是邪,其他我都不知道 SELECT * FROM student WHERE `name` LIKE '%邪%'; -- 这样就表示出来了,中间字为邪,前面和后面是任意个字符 -- 假设我知道紫邪情的最后一个字为情 SELECT * FROM student WHERE `name` LIKE '%情'; -- 假设我知道紫邪情姓紫,是三个字 SELECT * FROM student WHERE `name` LIKE '紫__'; -- 这里是两个 _ 下划线 /* 对于in a in ( b1 , b2 , b3 ) 只要a在b1 , b2 , b3中的任意一个里面就为true */ -- 假设:我知道名字是紫邪情 或 紫邪晴 当然:通过前面的方法也可以拿到这里想要的结果 -- 这里只是为了演示这个知识点 in这个东西一般都是在子查询中嵌套时会用到 而且还很重要 -- 复杂的联表查询一般都会用到这个in SELECT * FROM student WHERE `name` IN ( '紫邪情' , '紫邪晴' );
-
-
where查询的延伸 —— 模糊查询
-
-
-
-
-
-
-
④、联表查询 join on
-
准备工作 重新建表 不再用前面的student
-
效果如下:
-- 新建表、添数据 CREATE TABLE IF NOT EXISTS stuInfo( snum VARCHAR(20) NOT NULL PRIMARY KEY COMMENT'学号', `name` VARCHAR(20) NOT NULL COMMENT'学生姓名', sex CHAR(2) NOT NULL COMMENT'学生性别' CHECK( sex = '男' OR sex = '女' ), phone VARCHAR(12) NOT NULL COMMENT'学生电话号码' CHECK( len( phone ) = 11 ) )ENGINE = INNODB DEFAULT CHARSET = utf8; CREATE TABLE IF NOT EXISTS score( snum VARCHAR(20) NOT NULL PRIMARY KEY COMMENT'学号', `name` VARCHAR(20) NOT NULL COMMENT'学生姓名', score INT NOT NULL COMMENT'学生成绩' )ENGINE = INNODB DEFAULT CHARSET = utf8; INSERT INTO stuInfo VALUES( 'xh123001' , '紫邪情' , '女' , '1234567' ), ( 'xh123002' , '君莫邪' , '男' , '1433243' ), ( 'xh123003' , '张雪' , '女' , '694537' ), ( 'xh123004' , '不知火舞' , '女' , '9090950' ); INSERT INTO score VALUES( 'xh123001' , '紫邪情' , '90' ), ( 'xh123002' , '君莫邪' , '98' ), ( 'xh123003' , '张雪' , '99' ), ( 'xh123004' , '不知火舞' , '100' ); -
-
-
准备工作 重新建表 不再用前面的student
-
④、联表查询 join on
-
-
-
-
-
-
-
现在来开始玩联表查询 —— 只演示一个,其他的都是一样的原理
-
结果如下:
-- 想要查 紫邪情 的学号、姓名、性别、成绩 /* join on 的语法 select colnum_name from table_name [ left or right or inner ] join 要加入的表 on 两个表的链接条件 -- 最常用的是这三种连接 说明: 使用left join on 那么就是以left左边的表为主,即:需要的数据全是来自于左边的表 即使左边的表没有想要数据也没事 使用right join on 那么就是右边的表为主,即:需要的数据全是来自于右边的表 即使左边的表没有想要数据也没事 使用inner join on 那么从 要加入的表 中得到数据,是只要这个表中有一个数据满足就得吃
上述说的“为主”是什么意思?
即:查询出来的字段以哪张表为主。举个例子:
如:要查询的字段,在两张表中,前一张表中有这个字段,后一张表中也有这个字段,
那么:以哪张表为主,查询的字段也以哪张表为主。 */ -- 1、首先看需求:需要查询什么? -- 学号、姓名、性别、成绩 SELECT snum , `name` , sex , score -- 2、再看怎么去拿到这些数据 -- 这些数据是来自不同的表,那么联表 SELECT s.snum , s.`name` , sex , score FROM stuInfo AS s LEFT JOIN score ON s.`snum` = score.`snum` ;
-- 把score表连进来,连接条件就是:stuinfo表中的snum 和 score表中的snum是一样 -- 故:找连接条件就是找两个表之间相同的列字段
-
-
现在来开始玩联表查询 —— 只演示一个,其他的都是一样的原理
-
-
-
-
-
-
-
-
-
上述的查询可以做简化
-
-- 联表查询做简化 SELECT stuInfo.`snum` , stuInfo.`name` , sex ,score FROM stuInfo , score WHERE stuInfo.`snum` = score.`snum`; -- 这样得到的结果也是一样的,但是:这种比join no的性能更低
-
-
上述的查询可以做简化
-
-
-
-
-
-
-
-
-
-
对联表查询的拓展 —— 总的联表查询有7种方式 最常用的是上述说的三种而已,这些玩法也是差不多的
- 注意:联表查询在做简单的小系统时,如:xxx管理系统之类的,这种弄联表查询没关系的,但是:大型系统,如:分布式的,访问量贼大,动不动同一时刻几千万访问量的系统,坚决别用联表查询( 数据库设计时“一般”也不会整这种没前途的表设计,一般都会大表拆小表,玩分布式架构的演进时再去了解吧 ),因为:联表查询性能低,查数据、添加数据、修改数据等都需要联表嘛,这性能能不低吗
-
对联表查询的拓展 —— 总的联表查询有7种方式 最常用的是上述说的三种而已,这些玩法也是差不多的
-
-
-
-
-
-
-
-
-
⑤、自连接 ———— 就是把一张表拆成两张表( 要懂得怎么看这种表,怎么拆这种表 )
-
- 所谓的自连接就是:自己玩自己,简称:自wei嘛,这种建表方式其实很常见,如:我国的城市划分,省下有哪些市,市下有哪些县.........
-
-
⑤、自连接 ———— 就是把一张表拆成两张表( 要懂得怎么看这种表,怎么拆这种表 )
-
-
-
-
-
-
-
⑥、分页和排序
-
还是用前面创建的学生信息表stuInfo 和 成绩表score 不过:数据太少,那就加多一点
-
添加的数据如下:
-
添加的数据如下:
-
-- 想要查询学生信息表中的学号、姓名、电话号码,并且显示前5行数据 /* 分页limit的公式 limit ( n - 1 )*pageSize , pageSize 其中: n 是当前页的大小 如:第1页、第2页....第n页 pageSize 为当前页要显示的数据量 如:当前页显示5条数据 另:页的总数 = 总数据条数 / 每页要显示的数据量 */ SELECT snum , `name` , phone FROM stuInfo LIMIT 0,5 -- 第1页 ( 1 -1 )*5 , 5 ————> 0 , 5 -- limit 5,5 -- 第2页 -- limit 10,5 -- 第3页 -- limit 11 -- 排序 /*
语法: order by 使用排序的列字段 desc / asc 其中:desc为降序 asc为升序 */ -- 查询学生信息表中的学号、姓名、并以降序排列 SELECT snum , `name` FROM stuInfo ORDER BY snum DESC; -- 升序也就会玩了嘛 SELECT snum , `name` FROM stuInfo ORDER BY snum ASC; -- 既有升序、又有降序,那么就用 , 逗号隔开,如:学号降序,成绩升序 order by snum desc , score asc
-
还是用前面创建的学生信息表stuInfo 和 成绩表score 不过:数据太少,那就加多一点
-
⑥、分页和排序
-
-
-
-
-
-
⑦、子查询 —— 就是再套一个查询语句罢了,一个不够,那就继续套
- 玩这个的逻辑就是从里到外 —— 就像搞函数一样
-
⑦、子查询 —— 就是再套一个查询语句罢了,一个不够,那就继续套
-
-
-
-
-
-
-
-- 子查询 -- 还是查询学号、姓名、成绩 -- 使用连接查询 SELECT stuinfo.`snum` , stuinfo.`name` , score FROM stuinfo , score WHERE stuinfo.`snum` = score.`snum`; -- 这样是很轻松办到的,不过有时使用这种方法并不能得到想要的结果 -- 所以:开始推导、演变 -- 1、需要查询什么? 学号、姓名、成绩 -- 学号、姓名都可以在stuinfo表中查询,而成绩是在score表中 -- 因此:需要在score表中查询成绩 SELECT score FROM score; -- 这样可以把成绩查出来 -- 2、需要查询stuinfo表中的学号、姓名 SELECT stuinfo.`snum` , stuinfo.`name` FROM stuinfo; -- 这样可以把学号和姓名查出来 -- 3、需要把这两个结果连接起来 ———— 联表 下面加粗的就是子查询,即:在一个查询语句中套了另一个查询语句 SELECT stuinfo.`snum` , stuinfo.`name` , score FROM stuinfo , score -- 问题来了:成绩这个字段是怎么来的? -- 当然是从:score表中来的 所以:怎么把这个查score的子查询 和 查stuinfo的查询连接起来? -- 前面在说模糊查询的时候,不是说过一个关键字吗 ———— in 即:结果来自于in里面 SELECT stuinfo.`snum` , stuinfo.`name` , score FROM stuinfo , score WHERE score IN( -- 这里可以用in 也可以用= /* 区别就是: in里面的结果是可能有多个( 如:这里成绩查出来是很多个 ) = 里面的结果是一个,等于嘛,当然是一个了,难不成是多个值吗 */ SELECT score FROM score ); -- 根据需求多层子查询嵌套也是可以的,这只是最简单的子查询,逻辑都是一样的,一层一层推导就可以了
-- 上述的整个子查询不就感觉和java中写函数一样吗 ———— 因此:注意排版,这样更容易让人看懂逻辑,别搞成一行整完所有 -
延伸:组合查询
- 看名字就知道,把多个查询结果组合起来嘛
-
-
-
-
-
-
-
-
-
-
什么情况下可以用组合查询?
- 1、需要在多个表中查询数据
- 2、多个查询之后,按一个查询来返回数据
-
什么情况下可以用组合查询?
-
-
-
-
-
-
-
-
-
-
示例:
-
效果如下( 这就把后面查询的结果 和 上一个查询的结果拼接在一起了 ):
-- 组合查询 ———— 使用union关键字进行拼接 -- 查询学生信息表中的学号、姓名、性别、电话 ———— 用以前的方法可以做到,但是:这里不用,而是为了演示union -- 查询学号、姓名 SELECT snum , `name` FROM stuinfo; -- 查询性别、电话 SELECT score FROM score; -- 以上都可以分别查出应查的列字段 -- 但是想要的结果是:这二者的组合 -- 因此:使用union关键字 把 两个结果组合( 拼接 )在一起 SELECT snum , `name` FROM stuinfo UNION SELECT sex , phone FROM stuinfo; /* 使用union需要保证表的列字段都是一样的 换句话说:就是对同一个表做多次查询 为什么需要这样做? 因为:有时需求需要在一个表中查询不同的结果,然后和另外的表进行比对,所以就需要用到这个 */-
这个例子举的不好,和真正的需求不一样,所以看起来感觉没多大用,但是:实质上这个组合查询很有用
-
假如:有如下这样的一个表
-
-
需求:查询“计算机系”与“电子工程系“不同职称教师的Tname和Prof
-
效果如下:
-- 就需要下面这么玩
SELECT Tname,Prof FROM Teacher WHERE Depart ='计算机系' AND Prof NOT IN( SELECT Prof FROM Teacher WHERE Depart ='电子工程系' ) UNION SELECT Tname,Prof FROM Teacher WHERE Depart ='电子工程系' AND Prof NOT IN( SELECT Prof FROM Teacher WHERE Depart ='计算机系' );
-
-
-
-
示例:
-
-
-
-
-
-
-
-
⑧、分组和过滤
-
-- 分组和过滤 /* 语法: group by 要进行分组的字段 having 要过滤的条件 */ - 示例就不演示了,因为用法和排序差不多,这个就是用来以某一个 / 多个字段进行分组,同时还可以在分组之后过滤掉一些条件罢了
-
-
⑧、分组和过滤
-
-
-
-
-
(4)、 MySQL中的一些常用函数
-
①、与数学相关
-
-- 与数学相关 /* abs( a ) 绝对值 如:abs(-2) mod( a , b ) 求余数 如:mod( 5 , 2 ) 结果为:1 ceil( a ) 向上取整 如:ceil( 9.6 ) floor( a ) 向下取整 如:floor( 9.6 ) rand() 生成一个0 - 1之间的随机数 sign( a ) 获取符号 正数为1 负数为-1 */ SELECT ABS( -1 ); SELECT MOD( 5,2 ); SELECT CEIL( 9.6 ); SELECT FLOOR( 9.6 ); SELECT RAND(); SELECT SIGN( -2 );
-
-
①、与数学相关
-
(4)、 MySQL中的一些常用函数
-
-
-
-
-
②、与字符串相关
-
-- 与字符串相关 /* char_length( String str ) 获取字符串的长度 concat( String str , String s ) 字符串拼接 insert( String s , int start , int end , String str ) 从某个位置开始替换某个长度的字符串 lower( String s ) 转小写 upper( String s ) 转大写 instr( String s , String childS ) 返回指定字串ChildS在S中第一次出现的索引值 replace( String s , String futureReplaceS , String replaceS ) 把s中的子串futureReplceS替换成replaceS substr( String s , int start , int end ) 返回指定区间的子字符串 reverse( String s ) 反转 */ SELECT CHAR_LENGTH('老衲来了'); SELECT CONCAT( '太阳出来东边亮,' , '俺想和你搞对象' ); -- 基本上java中都有,不演示了
-
-
②、与字符串相关
-
-
-
-
-
-
③、和时间和日期相关 ——— 这个很重要
-
-- 和时间与日期相关(这个很重要) /* current_date() 获取当前日期 如:2021-09-03 curdate() 获取当前日期 如:2021-09-03 now() 获取当前日期 -- 这个更常用 如:2021-09-03 17:14:16 localtime() 本地时间 如:2021-09-03 17:14:16 dayofweek( date ) 获取一个时间是星期几 这个返回值结果是: 1 - 7表示周一 到 周天
当然还有年月日、时分秒的函数
year( date )
month( date )
day( date )
hour( date )
minute( date )
second( date ) */ SELECT CURRENT_DATE(); SELECT CURDATE(); SELECT NOW(); SELECT LOCALTIME(); SELECT DAYOFWEEK( NOW() );
-
-
③、和时间和日期相关 ——— 这个很重要
-
-
-
-
-
-
④、与系统相关 —— 了解即可
-
-- 与系统相关 SELECT VERSION(); -- 查看自己mysql的版本 这个有点用,因为:不知道mysql版本的时候就可以用这个 -- 获取登录用户名和权限 SELECT USER(); -- 是用来显示当前登陆的用户名与它对应的host SELECT SYSTEM_USER(); -- 是用来获取系统的用户名和对应host SELECT CURRENT_USER(); -- 是用来显示当前登陆用户对应在user表中的哪一个
-
-
④、与系统相关 —— 了解即可
-
-
-
-
-
⑤、聚合函数 ———— 很重要、非常重要
-
-- 聚合函数 很重要、非常重要 /* count() 计数 avg() 平均数 max() 最大数 min() 最小数 sum() 求和 */ SELECT COUNT(snum) FROM stuinfo; SELECT AVG(score) FROM score; SELECT SUM(score) FROM score; SELECT MAX(score) FROM score; SELECT MIN(score) FROM score;
-
-
⑤、聚合函数 ———— 很重要、非常重要
-
-
-
-
⑥、创建存储过程 和 自定义函数
-
壹、准备知识
-
if语句
-
-- MySQL中的if语句 /* 语法: if 条件 then 逻辑代码 end if; 或 if 条件 then 逻辑代码 else 逻辑代码 end if; 或 if 条件 then 逻辑代码 else if 条件 then 逻辑代码 ..... end if; */
-
-
MySQL中的循环语句
-
-- MySQL中的循环 /* 一共有三种: loop 相当于java中的for循环 repeat 相当于是java中的do while while 循环中的两个关键字 leave 相当于java中的break iterect 相当于java中的continue loop语法: 循环名:loop 循环体; 这里面可以使用 leave 循环名 来中断程序 end loop; -- 注意:这里是有 ; 分号结尾的 repeat的语法: repeat 循环体; until 条件; -- 注意:这里是有 ; 分号结尾的 end repeat; -- 注意:这里是有 ; 分号结尾的 while和java中的用法一样 */
-
-
if语句
-
壹、准备知识
-
⑥、创建存储过程 和 自定义函数
-
-
-
-
-
贰、MySQL的自定义函数 function
-
效果如下:
-- MySQL中的自定义函数
/*
为什么需要自定义函数?
这个就和java中的封装是一样的思想,那种经常增删改、特别是查询的语句,每一次都写,不是很麻烦吗?
所以:自定义函数,把这些东西封装起来,下一次用的时候直接调用即可
*/
/* 创建函数语法: -- 版本不一样,所以创建时总有一些bug,MySQL5.7版本的就需要加一个delimiter // ..... // delimiter;
delimiter $$ create function fun_函数名( 参数名字 数据类型 , 参数名字 数据类型.....) [ returns 返回值类型 ] begin 函数体; 这里面还可以定义变量,语法如下: declare 变量名 变量类型 [ default 默认值 ];
给变量赋值:
set 变量名 = 值; end $$
delimiter; 说明: fun_函数名 这整个是一个函数名,只是命名规范需要这样 数据类型 就是MySQL前面一开始的讲的那些列类型,如:int 、 float 、 double...... 函数的调用 函数名( 传参 / 不传参 ); 删除函数 drop function 函数名; 查看函数 show create function 函数名; */ -- 练习 编写绝对值函数 DELIMITER $$ -- 这个是自定义分隔符,因为MySQL遇到 ; 就表示结束了 -- 所以这里需要用这个来自定义结束符,不一定是// 用$$也行,这是MySQL版本的语法解析器的问题 CREATE FUNCTION fun_abs( a INT ) RETURNS INT BEGIN IF( a > 0 ) THEN RETURN a; ELSE RETURN -a; END IF; -- if中其实要不要这个end if都行 循环中才注意需要 END $$ DELIMITER; -- 这是恢复MySQL的分隔符
-- 创建好了,记得运行
SELECT fun_abs( -3 ); -- 调用自定义函数 SHOW CREATE FUNCTION fun_abs; -- 查看自定义函数 DROP FUNCTION fun_abs; -- 删除自定义函数 -
创建成功之后是可以看到自定义的函数的
-
因为版本问题,所以可能会导致:语句对的,在别人哪里可以运行成功,但是在自己那里就不行,所以:这里补充一种查看适合自己版本的自定义函数
-
选择这个函数,然后鼠标右键,选择创建函数
- 输入函数名 —— 注意:命名规范 fun_真正的函数名
-
这里面就可以告诉自己:怎么创建适合自己版本的函数,同时也可以从这里看出,自己的函数中可以包含哪些东西
-
-
-
贰、MySQL的自定义函数 function
-
-
-
-
-
-
叁、MySQL中创建存储过程 procedure
-
其实和自定义函数贼像,就是关键字变了、少了一点东西而已
-
其实和自定义函数贼像,就是关键字变了、少了一点东西而已
-
叁、MySQL中创建存储过程 procedure
-
-
-
-
-
-
-
-- MySQL创建存储过程 /* 那为什么需要创建存储过程? 试想一下:如果表很多、表中的数据很庞大,那么读写的时候很慢怎么办? 使用存储过程,这样就和自定义函数有点类似了,把需要进行读写的数据进行提前存储起来 对外只需要接收参数即可。 补充一点:MySQL是先编译,然后再执行,这样在高并发访问时,就会造成浪费资源和时间 导致MySQL占用的线程多,也就是所谓的“慢“ 所以:存储过程就是用来提示性能的 MySQL创建存储过程语法: delimiter$$ create procedure pro_名字( 模式 参数名 数据类型 , 模式 参数名 数据类型....) begin 逻辑代码; end $$ delimiter; 说明: 模式 指的是参数的模式 即:输入型参数in 输出型参数out 输入输出型参数inout( 这个不常用 了解即可 ) 调用存储过程: call pro_名字; 删除存储过程: drop procedure pro_名字; 在这个存储过程中有一个除了变量赋值,还有一种结果赋值 即:把查询出来的结果赋给一个变量 */ DELIMITER $$ CREATE PROCEDURE pro_test( IN studentNumber VARCHAR(20) ) BEGIN DECLARE scoreNum INT; SELECT score INTO scoreNum FROM score WHERE snum = studentNumber; -- 这里就是利用into把查询出来的score赋给了scoreNum变量 IF scoreNum = 90 THEN UPDATE score SET score = score + 10 WHERE snum = studentNumber; END IF; END$$ DELIMITER; -- 记得编写好之后,运行创建 CALL pro_test('xh123001'); SELECT * FROM score; DROP PROCEDURE pro_test; -- 删除存储过程效果如下:
-
-
-
-
-
-
-
(5)、MySQL的事务
-
什么是事务?
- 将sql放到一个批次中去执行,要么都成功,要么都失败。最典型的就是转账:一个要转出,一个要转入
-
什么是事务?
-
(5)、MySQL的事务
-
-
-
-
-
①、事务的四原则 ACID原则 —— 参考网址:事务ACID理解_dengjili的专栏-CSDN博客_acid
-
原子性(Atomicity)
- 一个事务中的语句,要么都成功,要么都失败
-
原子性(Atomicity)
-
①、事务的四原则 ACID原则 —— 参考网址:事务ACID理解_dengjili的专栏-CSDN博客_acid
-
-
-
-
-
-
-
一致性(Consistency)
- 事务前后的数据完整性要保持一致,就如:A给B转了1000,结果A自己的钱还没减
-
一致性(Consistency)
-
-
-
-
-
-
-
-
持久性(Durability)
- 事务一旦被提交,则不可逆,会持久化到数据库中
-
持久性(Durability)
-
-
-
-
-
-
-
- 隔离性(Isolation)
- 事务之间不可以彼此影响
-
隔离性会导致的一些问题:
- ①、脏读 指:一个事务读取了另一个事务未提交的数据 。如:转钱中,A给B转钱,还没转成功呢,但是:B事务那边就已经读取到了A事务要提交的数据( 即:B事务的钱增加了 )
- ②、虚读 指:表级别的,就是:一个事务A读取了一遍“表的数据”,但是:另一个事务B又对表插入了一条数据,然后A事务 / 其他事务C读取表的数据时,两次的结果就不一样了( 多一行 / 少一行.... )
- ③、不可重复读 指:一个事务读取“某一行数据",但是:每次读取的结果都不一样( 这种不一定是错误,是一种巧合 )。如:A事务去查询一个数据,这时A事务已经提交了,但是此时也有其他事务修改了这一行数据,所以A事务再读取时发现数据发生了改变,和上一次读取的不一样了
- 这些我只是简单说了一下,要看详细的就看我前面放的那个CSDN链接,他那里面更详细
-
-
-
-
-
-
-
-
②、开始玩事务
-
/* 知识准备工作: MySQL是默认自动提交事务的 所以:我们怎么来手动开启和关闭自动提交? set autocommit = 0; -- 1、关闭自动提交 set autocommit = 1; -- 开启自动提交 MySQL默认就是这个 MySQL怎么开启事务? start transaction-- 2、开启事务 这就是标记一个事务的开始 -- 从这之后,到结束事务( 即:提交事务 )这中间的sql都在一个事务内 -- 3、这中间干的事情就是: insert / delete / update / select; commit; -- 4、事务的结束标志,就是提交事务( 即:持久化到数据库 ) -- 但是还有一种情况涩,就是万一断网了爪子之类的,没有提交成功呢? -- 所以:这里还有一个命令 rollback; -- 4.1、回滚 即:回到没有提交事务之前( 即:数据库中数据原来的样子 ) -- 5、最后:记得做一件事,把自动提交给别人开启 set autocommit = 1; */
-
-
玩一个事务:模拟一下转钱的事
-
效果如下:
-- 开始整事务 SET autocommit = 0; -- 关闭MySQL的自动提交 START TRANSACTION; -- 开启事务 -- 事务之间干的事情 -- A给B转钱,所以A自己少钱,B多钱咯 UPDATE account SET money = money - 500 WHERE `name` = 'A'; UPDATE account SET money = money + 500 WHERE `name` = 'B'; COMMIT; -- 提交事务 ROLLBACK; -- 事务回滚 SET autocommit = 1; -- 还原MySQL默认的自动提交设置 -- 检验一下: SELECT * FROM account;
-
-
②、开始玩事务
-
-
-
-
-
-
(6)、MySQL的索引 —— 很重要:上档次的面试喜欢问
- 对于基础人员,推荐学习网址:数据库索引详解_超帅的土拨鼠的博客-CSDN博客
- 官网索引讲解网址:MySQL :: MySQL 5.7 参考手册 :: C 索引
-
(6)、MySQL的索引 —— 很重要:上档次的面试喜欢问
-
-
-
-
-
简单说一下索引的简单知识
-
索引 指的是:能够更高效的获取数据的数据结构
- 提取主干: 索引的本质就是一种数据结构
-
索引 指的是:能够更高效的获取数据的数据结构
-
简单说一下索引的简单知识
-
-
-
-
-
-
- 索引在小数据量中效果不明显,但是:如果数据量很大时,效果就出来了,速率会很快( 但是:不是绝对的快,索引不是越多越好 )
-
-
-
-
-
-
-
-
索引分类
-
①、主键索引 即:primary key
- 一个表中只能有一个,不可重复
-
①、主键索引 即:primary key
-
索引分类
-
-
-
-
-
-
-
-
-
②、唯一索引 即:unique key
- 一个表中可以有多个,可以重复( 多个列组合成唯一索引也可以 )。这是为了避免出现重复的列字段
-
②、唯一索引 即:unique key
-
-
-
-
-
-
-
-
-
-
③、常规索引 即:key / index
- 也是默认的索引。通过key 和 index来设置。即:可以在常规索引的列出现重复的值,
-
③、常规索引 即:key / index
-
-
-
-
-
-
-
-
-
-
④、全文索引 即:fullText
- 在MyISAM引擎下才有
- 就是为了快速定位到数据,是查询更快
-
④、全文索引 即:fullText
-
-
-
-
-
-
-
-
-
-
-- 索引 /* 手动创建,鼠标点击嘛 sql语句创建: 语法( 建完表之后再添加 ): alter table 数据库名.表名 add 索引类型 index index_索引名( 表中要添加索引的字段名 ) 说明:老规矩 index_索引名才是真正的索引名,只是索引名规范需要这么写而已 另外一种写法: create 索引类型 index index_索引名 on 表名( 要添加为索引的字段 ) 删除索引: drop index index_索引名 这是一种方式,有些版本不支持,所以:第二种如下: alter table 表名 drop index 索引名; 查询全部索引: show index from 表名; */ ALTER TABLE sqlstudy.score ADD FULLTEXT INDEX index_score(snum); CREATE UNIQUE INDEX index_test ON score(snum , score); -- 这两种索引创建方式都可以 ALTER TABLE score DROP INDEX index_test; -- 删除索引 SHOW INDEX FROM score; -- 查看表的所有索引表结构如下:
-
-
-
-
-
-
-
-
-
-
-
附加:看sql的执行状态 —— 了解即可
-
-- 分析sql的执行状态( expain ) 下面两种的规律自行总结 EXPLAIN SELECT * FROM score; -- 针对非全文索引的 -- 针对全文索引 需要先建立全文索引 这样使用以下方法就可以知道查询有多快了 EXPLAIN SELECT * FROM score WHERE MATCH(`name`) AGAINST('紫'); -- MATCH 匹配 AGAINST 依靠...
-
效果如下( 其他的不用管,我们只需要盯住一个地方就行 ):
-
-
附加:看sql的执行状态 —— 了解即可
-
-
-
-
-
-
-
-
-
-
使用索引的情况
-
在大数据量中
- 经常查询的列
- 经常分组 或 排序的列
- 经常进行链接的列
-
在大数据量中
-
使用索引的情况
-
-
-
-
-
-
-
-
-
-
最后:索引原则
- 索引不是越多越好
- 索引不是乱加的,一般是加在常用来查询的字段上的
- 小数据量的表不要加索引
- 不要对线程变动数据加索引
-
最后:索引原则
-
-
-
-
-
-
-
-
索引的简单总结:
-
索引的简单总结:
-
-
-
-
-
- 最后:索引其实不难,如果是本专业的( 即:计算机系的 ),那么理解索引非常的简单,相信本专业的都学过计算机组成原理,那么有没有想过,当自己在搜索大数据量时,你电脑的那个风扇为什么会转得很快( 急需扇热 )?这其实就和索引挂钩了,索引的硬件底层原理就是在这里,电脑磁盘其实就是很细小的一个格子,小到肉眼看不见,而我们在访问大数据量时,会急速转动,会听到风扇急速扇热的声音,这就是为了去找到我们要访问的数据是在哪个格子里,找到之后,把磁盘上的数据拷贝出来,然后返回给我们看得到的地方,因此转的很快,所以:索引其实就相当于是一个门牌号,就是为了标记我们要的数据在哪个位置罢了
-
-
-
-
-
(7)、用户权限管理 与 数据备份
-
①、创建用户 和 给用户授权
-
sqlyog手建 ———— 想要用户有什么权限,直接在里面手动赋予就可以了
-
-
sqlyog手建 ———— 想要用户有什么权限,直接在里面手动赋予就可以了
-
①、创建用户 和 给用户授权
-
(7)、用户权限管理 与 数据备份
-
-
-
-
-
-
sql建用户、授权
-
预备知识:整用户,那么本质就是对mysql中的mysql.user这张user表进行操作 ———— 前面安装mysql时,不是有一个修改密码的操作吗,就是对这张表进行增删改查操作
-
预备知识:整用户,那么本质就是对mysql中的mysql.user这张user表进行操作 ———— 前面安装mysql时,不是有一个修改密码的操作吗,就是对这张表进行增删改查操作
-
sql建用户、授权
-
-
-
-
-
-
-
-
-
权限分类
-
-- 1、创建用户 /* 语法: create user 用户名 identified by '密码'; -- 注意啊:用户名没单引号 密码有单引号 */ CREATE USER xieGongZi IDENTIFIED BY '123456'; -- 2、修改当前登录的用户 的 密码 /* set password = '新密码'; */ SET PASSWORD = '123456'; -- 3、对用户重命名 /* rename user 用户名 To 新用户名; */ RENAME USER xieGongZi TO ziXieQing; -- 4、删除用户 /* drop user 用户名; */ DROP USER ziXieQing; -- 5、给用户授权 /* grant 权限 on 库名.表名 from 用户名; -- grant就是授权的意思,这个很重要 -- 库名.表名 就是给哪个数据库中的哪个表授权 -- 用户名 就是要授权的对象 -- 权限有哪些,在手动创建时就可以看到,那里面全是字面意思 查看用户权限: show grant for 用户名; 删除用户的权限: revoke 哪些权限 on 哪个库.哪个表 from 哪个用户; */ GRANT ALL PRIVILEGES sqlstudy.`stuinfo` FROM xieGongZi; -- ALL PRIVILEGES 是授予所有的权限 REVOKE ALL PRIVILEGES ON sqlstudy.`stuinfo` FROM xieGongZi; -- 删除指定用户的权限
-
-
权限分类
-
-
-
-
-
-
-
-
-
②、数据备份
-
为什么要数据备份?
- 保证数据不丢失
- 数据转移
-
为什么要数据备份?
-
②、数据备份
-
-
-
-
-
-
-
-
-
数据备份的方式
-
手动备份
- 一、直接去盘符中的data目录中拷贝物理地址
-
二、在可视化工具中,右键对应的数据库 / 表进行导出( 注:选择导出数据和结构 ,这样表的列字段,对应的数据这些才不会丢失 ),如以下sqlyog的导出
-
手动备份
-
数据备份的方式
-
-
-
-
-
-
-
-
-
-
-
使用命令导出
-
使用命令导出
-
-
-
-
-
-
-
-
(8)、MySQL触发器 —— 不推荐使用,建议使用存储过程
-
①、手动创建
-
①、手动创建
-
(8)、MySQL触发器 —— 不推荐使用,建议使用存储过程
-
-
-
-
-
②、使用sql命令创建
-
老规矩:不知道怎么创建,那么就手动创建一个,然后看默认生成的是怎么创建的?
-
-
老规矩:不知道怎么创建,那么就手动创建一个,然后看默认生成的是怎么创建的?
-
②、使用sql命令创建
-
-
-
-
-
-
-
把里面的东西提出出来,然后做一下调整
-
效果如下:
-- 使用sql命令创建触发器 /* 为什么需要使用触发器? 主要原因:在进行增删改之前 / 之后 做一个检查 触发器是什么? 在数据增删改之前 / 之后,触发某一个事件 创建触发器: delimiter $$ create trigger trigger_名字 before / after insert / update / delete ON 库名.表名 for each row -- 对于每一行语句 begin 逻辑代码; -- 这里面可以是一句sql 也可以是多行sql end$$ delimiter ; 删除触发器: drop trigger trigger_名字; 查看触发器: show trigger_名字 */ -- 创建触发器 -- 给stuinfo表添加数据 也给student表中添加数据 DELIMITER $$ CREATE TRIGGER trigger_insert AFTER -- 表示在执行相应的操作之后,执行另外的操作 INSERT ON stuinfo -- 表示是在给stuinfo表进行插入数据时会触发某个事件 FOR EACH ROW -- 表示给stuinfo表进行插入数据一次 / 多次就要开始触发某个事件 BEGIN -- 这个begin 和 end之间就是要触发的事件 -- 这里面也支持定义变量、变量赋值、if语句、循环 INSERT INTO student VALUES( 'xh123004' , '邪公子' , '女' , '7749321' ); END$$ DELIMITER ; -- 测试一下:给stuinfo添加数据 INSERT INTO stuinfo VALUES( 'xh123012' , '梅雪烟' , '女' , '4626746' ); -- 查看触发器 SHOW TRIGGER \G; -- 加 \G 是为了让结果看起来有条理 就像查看电脑属性一样 -- 删除触发器 DROP TRIGGER IF EXISTS trigger_insert; -- 修改触发器 删了重建想要的触发器 -
-
-
把里面的东西提出出来,然后做一下调整
-
-
-
-
-
-
(9)、数据库设计
-
①、为什么需要进行数据库设计?
- 当数据库很复杂的时候就需要我们设计了
-
①、为什么需要进行数据库设计?
-
(9)、数据库设计
-
-
-
-
-
-
糟糕的数据库
- 数据冗余,浪费空间
- 效率慢
- 数据库增删查改都麻烦得很,还不定会整些异常出来
-
糟糕的数据库
-
-
-
-
-
-
-
-
优秀的数据库
- 节约空间
- 效率高
- 保证数据的完整性
-
优秀的数据库
-
-
-
-
-
-
-
②、怎么设计数据库?
- 先分析需求:分析业务和数据库处理的需求
- 然后进行概要设计:即 设计关系图 E-R模型
-
②、怎么设计数据库?
-
-
-
-
-
-
③、附加:优化数据库
- 优化的第一步:去掉所有的 * 如:select * from xxx; 这里就把 * 换成指定的列字段
- 优化连接:当数据量很大时,保证 on 之后的子句上面有索引
- 给出字符串合理的长度 如:性别 就两种 所以:char(2) 就够了
- 使用了count()的话,那么就尽量使用count( * ),因为:count( * )的本质是统计行数
- 给热点数据增加索引、让热点数据的列字段成为最左(这个最左原则看前面放的我个人喜欢的索引介绍就懂了)
- 以上是随便列举的MySQL方面的,后续还有Redis缓存技术、ElasticSearch搜索增强
- ...........
-
③、附加:优化数据库
-
-
-
-
-
-
④、附加二、数据库设计的一些规范
- 直接上阿里云的网址:
-
④、附加二、数据库设计的一些规范
-
-
-
-
-
(10)、三大范式
-
第一范式 1NF :原子性
- 即:保证每一列不可以再分 如:学院 还可以分大数据与信息工程学院、传媒学院..........
-
第一范式 1NF :原子性
-
(10)、三大范式
-
-
-
-
-
第二范式 2NF :
- 前提:满足第一范式
- 每张表只做一件事
-
第二范式 2NF :
-
-
-
-
-
-
第三范式 3NF :
- 满足第一、二范式
- 确保表中的每一列都和主键直接相关,而不是间接相关
-
第三范式 3NF :
-
-
-
-
-
- 在设计时,必须保证第一范式,另外两个范式,以能力、情况来
-
-
至此:数据库的基本知识就完毕了,JDBC我原本想放在这里面的,但是想了一下还是单独提出来
把JDBC单独弄成一篇小随笔!!!!!