MySQL 数据库简介
什么是数据库
数据库是按照数据结构来组织、储存和管理数据的仓库。
在日常生活中,我们常常需要把某些相关的数据放入这样的仓库,并根据管理的需要来进行相应的处理。例如,企业或事业单位的人事部门常常要把本单位职工的基本情况(职工号,姓名,年龄,性别,工资等等)存放在表里,这张表就可以看成是一个数据库。
关系型数据库
关系型数据库,是建立在关系模型上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据,日常生活中的各种事物之间的联系均用关系模型来表示。
关系模型是由埃德加·科德于 1970 年首先提出的,并配合“科德十二定律”。现如今虽然对此模型有一些批评意见,但它还是数据存储的传统标准。标准数据查询语言SQL就是一种基于关系数据库的语言,这种语言执行对关系数据库中数据的检索和操作。
关于 MySQL
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。
MySQL 的优点
开源免费 不需要支付额外费用
对 PHP 有很好的支持,与 Apache 或 Nginx 组成一个稳定免费的网站系统,也就是 LAMP
、LNMP
环境
支持多种存储引擎,支持大型的数据库。可以处理拥有上千万条记录的大型数据库。可以处理每天数亿次访问
为多种编程语言提供了 API,这些编程语言包括 C、C++、Python、Java、Perl、PHP、Eiffel、Ruby,.NET 和 Tcl 等
SQL 简介
结构化查询语言(Structured Query Language)简称 SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
SQL 语言一般分为以下几种语言:
数据查询语言(DQL:Data Query Language):
其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。这些DQL保留字常与其他类型的SQL语句一起使用。
数据操作语言(DML:Data Manipulation Language):
其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。
事务处理语言(TPL):
它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。
数据控制语言(DCL):
它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
数据定义语言(DDL):
其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。
指针控制语言(CCL):
它的语句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用于对一个或多个表单独行的操作。
MySQL 支持的数据类型
整数类型
整型值可以用十进制,十六进制或十八进制符号指定,前面可以加上可选符号(- 或者 +)。
MySQL 以一个可选的显示宽度指示器的形式对 SQL 标准进行了扩展,这样当从数据库检索一个值时,就可以把这个值加长到指定的长度。
例如:指定一个字段的类型为int(6),就可以保证说包含的数字少于6个的值在从数据库中被检索出来时能够自动用空格进行填充。
需要注意的是:使用一个宽度指示器并不会影响字段的大小和它可以储存的值的范围
浮点数类型
由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学计数法。或者简单理解为数字加小数点加数字构成
对于小数点后面的位置超过允许范围的值,MySQL会自动将它四舍五入为最接近它的值
定点数类型
浮点数型在数据库中存放的是近似值,而定点数类型在数据库中存放的是精确值。decimal( m, d ),参数m是数字的总位数,m<65,参数d是小数的总位数,d<30,d<m。
字符串类型
类型 | 占用长度与占用空间大小 |
---|---|
char(n) | 限制该字段的每条记录最多存入 n 个字符,n 的值最大为 255,占用空间由字符编码格式及 n 共同决定,例如 utf8_mb4 格式,类型为 char(10) 的字段每条记录的实际占用空间为 4 * 10 个字节 |
varchar(n) | 限制该字段的每条记录最多存入 n 个字符,n 的最大值由字符编码格式决定,例如 uft8_mb4 格式,1 个英文字母占用 1 个字节,1 个汉字(含繁体)占用 3 个字节,而设置为 varchar 类型的字段最多可占用 65535 个字节的空间,所以最大可存入的字符长度由字符编码决定。 |
tinytext | 限制该字段的每条记录最多存入 255 个字符 |
text | 限制该字段的每条记录最多存入 65535 个字节 |
mediumntext | 限制该字段的每条记录最多存入 2^24 个字节 |
longtext | 限制该字段的每条记录最多存入 2^32 个字节 |
需要注意 字节 与 字符 的区别:
字节 是空间单位,在计算机中,一个字节(byte)占 8 个 bit 位,而一个 bit 位 可以表示 1
和 0
两种状态,所以一个字节可以表示 256
(2 的 8 次方)种状态,而通常我们所说的 1 KB 则等于 1024 Byte,1 MB 则等于 1024 KB,1GB 等于 1024 MB …以此类推。
字符 是一个名词,char(n) 及 varchar(n) 代表每条记录最多可以存入 n 个字符。1 个汉字、1 个英文字母或 1 个表情符号等占用的字符数基本都是 1
。
其实也有不是 1
的情况例如,假设 Mysql 数据库使用 utf_mb4
编码, user
表的 nickname
字段中存入一条记录:👴
, 👴
这个 emoji 表情符号实际占用 2 个字符数。
使用 MySQL 自带的函数 char_length
可以计算出字符串所占用的字符数,length
可以计算出字符串所占用的字节数,例如:
select char_length(nickname), length(nickname), nickname from users where id = 1;
运行结果如下:
+-------------------+--------------+------+
| char_length(nickname) | length(nickname) | nickname |
+-------------------+--------------+------+
| 2 | 8 | 👴 |
+-------------------+--------------+------+
1 row in set (0.04 sec)
上面的例子中数据库编码为 utf8_mb4
,字符串 👴
占用 2 个字符数、8 字节空间,如果设置 nickname
字段的格式为 char(10)
,则一条记录最多可存入 5 个 👴
、占用 40 个字节空间。由于 char(10)
代表该字段每条记录固定占有 10 个字符数,所以如果你只存入 1 个 👴
,剩余的 8 个字符则会被 MySQL 使用空格字符填充,实际也是占用固定的 40 个字节空间。
php 中如何计算字符长度
我们知道,限制用户输入字符的长度属于业务逻辑,实际项目中一般都是逻辑层先做限制,比如网站或客户端请求 PHP 的 API
接口更新某个用户的 nickname
,此时 PHP 接口需要判断字符长度是否溢出了 10 个字符,做法如下:
<?php
$nickname = $_POST['nickname'];
$length = mb_strlen($nickname, 'UTF-8');
if ($length > 10) echo '昵称不可超过 10 个字符';
dart 如何计算字符长度
前面只在 PHP 的接口做判断是不够的,例如由 Flutter 编写的手机 App 端请求接口前,肯定要先判断长度,避免无效的请求,浪费资源。做法如下:
Future<void> handleSubmit() async {
if (_isSubmitting) return;
final nickname= textEditingController.text;
if (nickname.runes.length > 10) {
showTip('昵称不可超过 10 个字符');
return;
}
_isSubmitting = true;
final isError = await UserApi.updateProfile(nickname: nickname);
_isSubmitting = false;
if (isError) return;
Constants.user.nickanme = nickname;
Constants.saveUserToDB();
Routes.pop();
}
char 与 varchar 的区别
-
char(n) 若存入字符数小于 n,则以空格补于其后,查询之时再将空格去掉。所以 char 存储的字符串末尾不能有空格,而 varchar 可以。
-
char(n) 固定长度,char(4) 不管是存入几个字符,都将占用4个字节,varchar 是存入的实际字符数+1个字节(n<=255)或2个字节(n > 255),所以 varchar(4),存入 3 个字符将占用 4 个字节。
-
char 类型的字符串检索速度要比 varchar 类型的快。
varchar 与 text 的区别
-
varchar可指定 n,text 不能指定,varchar 存入的实际字符数 +1 个字节(n <= 255)或2个字节(n > 255),text 是实际字符数 +2个字节。
-
varchar可指定默认值,而text不能指定默认值,默认始终为NULL。
-
varchar可直接创建索引,text 创建索引要指定前多少个字符。varchar 查询速度快于 text,创建索引的情况下,text 索引几乎不起作用。
二进制数据类型
bob 与 text 的区别
1 bob 和 text 的存储方式不同,text 以文本方式存储,英文存储区分大小写,而 blob 是以二进制方式存储,不分大小写。
2 bob 储存的数据只能整体读出。
3 text 可以指定字符集 而 blob 不用指定字符集。
日期时间类型
若定义表里的一个字段为 timestamp,那么这个字段里的时间数据会随其他字段修改的时候自动刷新,所以这个数据类型的字段可以存放最后被修改的时间。
字段修饰与类型修饰等关键字
null
该字段可包含 null
值
not null
该字段不可包含NULL值
default
设置字段的默认值,如果没有向这个字段插入内容,则使用默认值。
primary key
约束唯一标识数据库表中的每一条记录。主键必须包含唯一的值,主键列不能包含NULL值。每个表都应该有一个主键,并且只能有一个
auto_increment
设置该字段的值自动递增,适合整数类型。若插入数据时指定了该字段的值,不与之前的值出现重复则下次递增从该值开始递增,若出现重复,则会报错。
zerofill
使用前导0填充数值以达到指定的显示位数,使用该修饰符可以阻止数据库储存负值,需要与int(n)这种格式的字段配合使用。
unsigned
规定字段只保存正值。因为不需要保存数字的正、负符号,可以在储存时节约一个’位’的空间。从而增大这个字段可以储存的值的范围。
enum
只允许在规定的集合中取一个值,有点类似与单选项。在处理相互排斥的数据时容易让人理解,比如性别。集合最大可以有65535个值
set
SET与ENUM相似单不相同。SET可以从预定义的集合中取得任意数量的值。一个SET类型最多可以包含64项元素。
unique
约束唯一标识数据库表中的每条记录,一个表中可以有多个UNIQUE约束。
character set name
指定一个字符集。