wordpress 整站语言,企业展示设计公司,智联招聘官方网,用ps制作网页教程文章目录 1. MySQL中的数据类型2. 整数类型2.1 类型介绍2.2 可选属性2.2.1 M2.2.2 UNSIGNED2.2.3 ZEROFILL 2.3 适用场景2.4 如何选择#xff1f; 3. 浮点类型3.1 类型介绍3.2 数据精度说明3.3 精度误差说明 4. 定点数类型4.1 类型介绍4.2 开发中经验 5. 位类型#xff1a;BI… 文章目录 1. MySQL中的数据类型2. 整数类型2.1 类型介绍2.2 可选属性2.2.1 M2.2.2 UNSIGNED2.2.3 ZEROFILL 2.3 适用场景2.4 如何选择 3. 浮点类型3.1 类型介绍3.2 数据精度说明3.3 精度误差说明 4. 定点数类型4.1 类型介绍4.2 开发中经验 5. 位类型BIT6. 日期与时间类型6.1 YEAR类型6.2 DATE类型6.3 TIME类型6.4 DATETIME类型6.5 TIMESTAMP类型6.6 开发中经验 7. 文本字符串类型7.1 CHAR与VARCHAR类型7.2 TEXT 类型 8. ENUM类型9. SET类型10. 二进制字符串类型11. JSON 类型12. 空间类型(略)13. 小结及选择建议 1. MySQL中的数据类型 常见数据类型的属性如下 2. 整数类型
2.1 类型介绍
整数类型一共有 5 种包括 TINYINT、SMALLINT、MEDIUMINT、INTINTEGER和 BIGINT。 它们的区别如下表所示
2.2 可选属性
整数类型的可选属性有三个
2.2.1 M
M : 表示显示宽度M的取值范围是(0, 255)。例如int(5)当数据宽度小于5位的时候在数字前面需要用字符填满宽度。该项功能需要配合“ ZEROFILL ”使用表示用“0”填满宽度否则指定显示宽度无效。
如果设置了显示宽度那么插入的数据宽度超过显示宽度限制会不会截断或插入失败
答案不会对插入的数据有任何影响还是按照类型的实际宽度进行保存即 显示宽度与类型可以存储的值范围无关 。从MySQL 8.0.17开始整数数据类型不推荐使用显示宽度属性。整型数据类型可以在定义表结构时指定所需要的显示宽度如果不指定则系统为每一种类型指定默认的宽度值。
举例
CREATE TABLE test_int1 ( x TINYINT, y SMALLINT, z MEDIUMINT, m INT, n BIGINT );
查看表结构 MySQL5.7中显式如下MySQL8中不再显式范围 TINYINT有符号数和无符号数的取值范围分别为-128 ~ 127和0 ~ 255由于负号占了一个数字位因此TINYINT默认的显示宽度为4。同理其他整数类型的默认显示宽度与其有符号数的最小值的宽度相同。
举例
CREATE TABLE test_int2(
f1 INT,
f2 INT(5),
f3 INT(5) ZEROFILL
) DESC test_int2; INSERT INTO test_int2(f1,f2,f3)
VALUES(1,123,123); INSERT INTO test_int2(f1,f2)
VALUES(123456,123456); INSERT INTO test_int2(f1,f2,f3)
VALUES(123456,123456,123456); 2.2.2 UNSIGNED
UNSIGNED : 无符号类型非负所有的整数类型都有一个可选的属性UNSIGNED无符号属性无符号整数类型的最小取值为0。所以如果需要在MySQL数据库中保存非负整数值时可以将整数类型设置为无符号类型。int类型默认显示宽度为int(11)无符号int类型默认显示宽度为int(10)。
2.2.3 ZEROFILL
ZEROFILL : 0填充,如果某列是ZEROFILL那么MySQL会自动为当前列添加UNSIGNED属性如果指定了ZEROFILL只是表示不够M位时用0在左边填充如果超过M位只要不超过数据存储范围即可。原来在 int(M) 中M 的值跟 int(M) 所占多少存储空间并无任何关系。 int(3)、int(4)、int(8) 在磁盘上都是占用 4 bytes 的存储空间。也就是说int(M)必须和UNSIGNED ZEROFILL一起使用才有意义。如果整数值超过M位就按照实际位数存储。只是无须再用字符 0 进行填充。
2.3 适用场景
TINYINT 一般用于枚举数据比如系统设定取值范围很小且固定的场景。SMALLINT 可以用于较小范围的统计数据比如统计工厂的固定资产库存数量等。 MEDIUMINT 用于较大整数的计算比如车站每日的客流量等。INT、INTEGER 取值范围足够大一般情况下不用考虑超限问题用得最多。比如商品编号。BIGINT 只有当你处理特别巨大的整数时才会用到。比如双十一的交易量、大型门户网站点击量、证券公司衍生产品持仓等。
2.4 如何选择 在评估用哪种整数类型的时候你需要考虑 存储空间 和 可靠性 的平衡问题一方 面用占用字节数少的整数类型可以节省存储空间另一方面要是为了节省存储空间 使用的整数类型取值范围太小一旦遇到超出取值范围的情况就可能引起 系统错误 影响可靠性。 举个例子商品编号采用的数据类型是 INT。原因就在于客户门店中流通的商品种类较多而且每天都有旧商品下架新商品上架这样不断迭代日积月累。 如果使用 SMALLINT 类型虽然占用字节数比 INT 类型的整数少但是却不能保证数据不会超出范围65535。相反使用 INT就能确保有足够大的取值范围不用担心数据超出范围影响可靠性的问题。 你要注意的是在实际工作中系统故障产生的成本远远超过增加几个字段存储空间所产生的成本。因此我建议你首先确保数据不会超过取值范围在这个前提之下再去考虑如何节省存储空间。
3. 浮点类型
3.1 类型介绍
浮点数和定点数类型的特点是可以 处理小数 你可以把整数看成小数的一个特例。因此浮点数和定点数的使用场景比整数大多了。 MySQL支持的浮点数类型分别是 FLOAT、DOUBLE、REAL。
FLOAT 表示单精度浮点数DOUBLE 表示双精度浮点数 REAL默认就是 DOUBLE。如果你把 SQL 模式设定为启用“ REAL_AS_FLOAT ”那 么MySQL 就认为REAL 是 FLOAT。如果要启用“REAL_AS_FLOAT”可以通过以下 SQL 语句实现
SET sql_mode “REAL_AS_FLOAT”;
问题1FLOAT 和 DOUBLE 这两种数据类型的区别是啥呢 FLOAT 占用字节数少取值范围小DOUBLE 占用字节数多取值范围也大。
问题2为什么浮点数类型的无符号数取值范围只相当于有符号数取值范围的一半也就是只相当于有符号数取值范围大于等于零的部分呢 MySQL 存储浮点数的格式为 符号(S) 、 尾数(M) 和 阶码(E) 。因此无论有没有符号MySQL 的浮点数都会存储表示符号的部分。因此 所谓的无符号数取值范围其实就是有符号数取值范围大于等于零的部分。
3.2 数据精度说明
对于浮点类型在MySQL中单精度值使用 4 个字节双精度值使用 8 个字节。 MySQL允许使用 非标准语法 其他数据库未必支持因此如果涉及到数据迁移则最好不要这么用FLOAT(M,D) 或 DOUBLE(M,D) 。这里M称为 精度 D称为 标度 。(M,D)中 M整数位小数位D小数位。 DM2550D30。 例如定义为FLOAT(5,2)的一个列可以显示为-999.99-999.99。如果超过这个范围会报错。 FLOAT和DOUBLE类型在不指定(M,D)时默认会按照实际的精度由实际的硬件和操作系统决定来显示。 说明浮点类型也可以加 UNSIGNED 但是不会改变数据范围例如FLOAT(3,2) UNSIGNED仍然只能表示0-9.99的范围。 不管是否显式设置了精度(M,D)这里MySQL的处理方案如下 如果存储时整数部分超出了范围MySQL就会报错不允许存这样的值如果存储时小数点部分若超出范围就分以下情况 若四舍五入后整数部分没有超出范围则只警告但能成功操作并四舍五入删除多余的小数位后保存。例如在FLOAT(5,2)列内插入999.009近似结果是999.01。若四舍五入后整数部分超出范围则MySQL报错并拒绝处理。如FLOAT(5,2)列内插入999.995和-999.995都会报错。 从MySQL 8.0.17开始FLOAT(M,D) 和DOUBLE(M,D)用法在官方文档中已经明确不推荐使用将来可能被移除。另外关于浮点型FLOAT和DOUBLE的UNSIGNED也不推荐使用了将来也可能被移除。 举例
CREATE TABLE test_double1(
f1 FLOAT,
f2 FLOAT(5,2),
f3 DOUBLE,
f4 DOUBLE(5,2)
); DESC test_double1; INSERT INTO test_double1
VALUES(123.456,123.456,123.4567,123.45); #Out of range value for column f2 at row 1
INSERT INTO test_double1
VALUES(123.456,1234.456,123.4567,123.45); SELECT * FROM test_double1;
3.3 精度误差说明
浮点数类型有个缺陷就是不精准。下面我来重点解释一下为什么 MySQL 的浮点数不够精准。比如我们设计一个表有f1这个字段插入值分别为0.47,0.44,0.19我们期待的运行结果是0.47 0.44 0.19 1.1。而使用sum之后查询 查询结果是 1.0999999999999999。看到了吗虽然误差很小但确实有误差。 你也可以尝试把数据类型改成 FLOAT然后运行求和查询得到的是 1.0999999940395355。显然误差更大了。 那么为什么会存在这样的误差呢问题还是出在 MySQL 对浮点类型数据的存储方式上。 MySQL 用 4 个字节存储 FLOAT 类型数据用 8 个字节来存储 DOUBLE 类型数据。无论哪个都是采用二进制的方式来进行存储的。比如 9.625用二进制来表达就是 1001.101或者表达成 1.001101×2^3。如果尾数不是 0 或 5比如 9.624你就无法用一个二进制数来精确表达。进而就只好在取值允许的范围内进行四舍五入。 在编程中如果用到浮点数要特别注意误差问题因为浮点数是不准确的所以我们要避免使用“”来判断两个数是否相等。同时在一些对精确度要求较高的项目中千万不要使用浮点数不然会导致结果错误甚至是造成不可挽回的损失。那么MySQL 有没有精准的数据类型呢当然有这就是定点数类型 DECIMAL 。
4. 定点数类型
4.1 类型介绍
MySQL中的定点数类型只有 DECIMAL 一种类型。 使用 DECIMAL(M,D) 的方式表示高精度小数。其中M被称为精度D被称为标度。0M650D30DM。例如定义DECIMAL5,2的类型表示该列取值范围是-999.99~999.99。 DECIMAL(M,D)的最大取值范围与DOUBLE类型一样但是有效的数据范围是由M和D决定的。DECIMAL 的存储空间并不是固定的由精度值M决定总共占用的存储空间为M2个字节。也就是说在一些对精度要求不高的场景下比起占用同样字节长度的定点数浮点数表达的数值范围可以更大一些。 定点数在MySQL内部是以 字符串 的形式进行存储这就决定了它一定是精准的。 当DECIMAL类型不指定精度和标度时其默认为DECIMAL(10,0)。当数据的精度超出了定点数类型的精度范围时则MySQL同样会进行四舍五入处理。 浮点数 vs 定点数 浮点数相对于定点数的优点是在长度一定的情况下浮点类型取值范围大但是不精准适用于需要取值范围大又可以容忍微小误差的科学计算场景比如计算化学、分子建模、流体动力学等定点数类型取值范围相对小但是精准没有误差适合于对精度要求极高的场景 比如涉及金额计算的场景 举例
CREATE TABLE test_decimal1(
f1 DECIMAL,
f2 DECIMAL(5,2)
); DESC test_decimal1; INSERT INTO test_decimal1(f1,f2)
VALUES(123.123,123.456); #Out of range value for column f2 at row 1
INSERT INTO test_decimal1(f2)
VALUES(1234.34); 举例
我们运行下面的语句把test_double2表中字段“f1”的数据类型修改为 DECIMAL(5,2)
ALTER TABLE test_double2
MODIFY f1 DECIMAL(5,2);
然后我们再一次运行求和语句
mysql SELECT SUM(f1)
- FROM test_double2;
---------
| SUM(f1) |
---------
| 1.10 |
---------
1 row in set (0.00 sec)
mysql SELECT SUM(f1) 1.1
- FROM test_double2;
---------------
| SUM(f1) 1.1 |
---------------
| 1 |
---------------
1 row in set (0.00 sec)
4.2 开发中经验 5. 位类型BIT
BIT类型中存储的是二进制值类似010110。
二进制字符串类型长度长度范围占用空间BIT(M)M1M4约为(M7)/8个字节
BIT类型如果没有指定(M)默认是1位。这个1位表示只能存1位的二进制值。这里(M)是表示二进制的位数位数最小值为1最大值为64。
CREATE TABLE test_bit1(
f1 BIT,
f2 BIT(5),
f3 BIT(64));
INSERT INTO test_bit1(f1)
VALUES(1); #Data too long for column f1 at row 1
INSERT INTO test_bit1(f1)
VALUES(2); INSERT INTO test_bit1(f2)
VALUES(23);
注意在向BIT类型的字段中插入数据时一定要确保插入的数据在BIT类型支持的范围内。 使用SELECT命令查询位字段时可以用 BIN() 或 HEX() 函数进行读取。
6. 日期与时间类型
日期与时间是重要的信息在我们的系统中几乎所有的数据表都用得到。原因是客户需要知道数据的时间标签从而进行数据查询、统计和处理。
MySQL有多种表示日期和时间的数据类型不同的版本可能有所差异MySQL8.0版本支持的日期和时间类型主要有YEAR类型、TIME类型、DATE类型、DATETIME类型和TIMESTAMP类型。
YEAR 类型通常用来表示年DATE 类型通常用来表示年、月、日TIME 类型通常用来表示时、分、秒DATETIME 类型通常用来表示年、月、日、时、分、秒TIMESTAMP 类型通常用来表示带时区的年、月、日、时、分、秒 可以看到不同数据类型表示的时间内容不同、取值范围不同而且占用的字节数也不一样你要根据实际需要灵活选取。 为什么时间类型 TIME 的取值范围不是 -23:59:5923:59:59 呢原因是 MySQL 设计的 TIME 类型不光表示一天之内的时间而且可以用来表示一个时间间隔这个时间间隔可以超过 24 小时。
6.1 YEAR类型
YEAR类型用来表示年份在所有的日期时间类型中所占用的存储空间最小只需要 1个字节 的存储空间。
在MySQL中YEAR有以下几种存储格式
以4位字符串或数字格式表示YEAR类型其格式为YYYY最小值为1901最大值为2155。以2位字符串格式表示YEAR类型最小值为00最大值为99。当取值为01到69时表示2001到2069当取值为70到99时表示1970到1999当取值整数的0或00添加的话那么是0000年当取值是日期/字符串的’0’添加的话是2000年。
从MySQL5.5.27开始2位格式的YEAR已经不推荐使用。YEAR默认格式就是“YYYY”没必要写成YEAR(4)从MySQL 8.0.19开始不推荐使用指定显示宽度的YEAR(4)数据类型。
CREATE TABLE test_year(
f1 YEAR,
f2 YEAR(4));INSERT INTO
test_year
VALUES(2020,2021); 6.2 DATE类型
DATE类型表示日期没有时间部分格式为 YYYY-MM-DD 其中YYYY表示年份MM表示月份DD表示日期。需要 3个字节 的存储空间。在向DATE类型的字段插入数据时同样需要满足一定的格式条件。 以 YYYY-MM-DD 格式或者 YYYYMMDD 格式表示的字符串日期其最小取值为1000-01-01最大取值为9999-12-03。YYYYMMDD格式会被转化为YYYY-MM-DD格式。 以 YY-MM-DD 格式或者 YYMMDD 格式表示的字符串日期此格式中年份为两位数值或字符串满足YEAR类型的格式条件为当年份取值为00到69时会被转化为2000到2069当年份取值为70到99时会被转化为1970到1999。 使用 CURRENT_DATE() 或者 NOW() 函数会插入当前系统的日期。
举例 创建数据表表中只包含一个DATE类型的字段f1。
CREATE TABLE test_date1(
f1 DATE
);
Query OK, 0 rows affected (0.13 sec)
插入数据
INSERT INTO test_date1
VALUES (2020-10-01), (20201001),(20201001); INSERT INTO test_date1
VALUES (00-01-01), (000101), (69-10-01), (691001), (70-01-01), (700101), (99-01-01), (990101); INSERT INTO test_date1
VALUES (000301), (690301), (700301), (990301); INSERT INTO test_date1 VALUES (CURRENT_DATE()), (NOW()); SELECT * FROM test_date1;6.3 TIME类型 TIME类型用来表示时间不包含日期部分。在MySQL中需要 3个字节 的存储空间来存储TIME类型的数据可以使用“HH:MM:SS”格式来表示TIME类型其中HH表示小时MM表示分钟SS表示秒。 在MySQL中向TIME类型的字段插入数据时也可以使用几种不同的格式。 1可以使用带有冒号的字符串比如’ D HH:MM:SS’ 、’ HH:MM:SS ‘、’ HH:MM ‘、’ D HH:MM ‘、’ D HH ‘或’ SS ‘格式都能被正确地插入TIME类型的字段中。其中D表示天其最小值为0最大值为34。如果使用带有D格式的字符串插入TIME类型的字段时D会被转化为小时计算格式为D*24HH。当使用带有冒号并且不带D的字符串表示时间时表示当天的时间比如12:10表示12:10:00而不是00:12:10。 2可以使用不带有冒号的字符串或者数字格式为’ HHMMSS 或者 HHMMSS 。如果插入一个不合法的字符串或者数字MySQL在存储数据时会将其自动转化为00:00:00进行存储。比如1210MySQL会将最右边的两位解析成秒表示00:12:10而不是12:10:00。 3使用 CURRENT_TIME() 或者 NOW() 会插入当前系统的时间。
举例: 创建数据表表中包含一个TIME类型的字段f1。
CREATE TABLE test_time1(
f1 TIME
);
Query OK, 0 rows affected (0.02 sec)
INSERT INTO test_time1
VALUES(2 12:30:29), (12:35:29), (12:40), (2 12:40),(1 05), (45); INSERT INTO test_time1
VALUES (123520), (124011),(1210); INSERT INTO test_time1
VALUES (NOW()), (CURRENT_TIME()); SELECT * FROM test_time1;
6.4 DATETIME类型
DATETIME类型在所有的日期时间类型中占用的存储空间最大总共需要 8 个字节的存储空间。在格式上为DATE类型和TIME类型的组合可以表示为 YYYY-MM-DD HH:MM:SS 其中YYYY表示年份MM表示月份DD表示日期HH表示小时MM表示分钟SS表示秒。
在向DATETIME类型的字段插入数据时同样需要满足一定的格式条件。
以 YYYY-MM-DD HH:MM:SS 格式或者 YYYYMMDDHHMMSS 格式的字符串插入DATETIME类型的字段时最小值为1000-01-01 00:00:00最大值为9999-12-03 23:59:59。 以YYYYMMDDHHMMSS格式的数字插入DATETIME类型的字段时会被转化为YYYY-MM-DD HH:MM:SS格式。以 YY-MM-DD HH:MM:SS 格式或者 YYMMDDHHMMSS 格式的字符串插入DATETIME类型的字段时两位数的年份规则符合YEAR类型的规则00到69表示2000到206970到99表示1970到1999。 使用函数 CURRENT_TIMESTAMP() 和 NOW() 可以向DATETIME类型的字段插入系统的当前日期和时间。
举例
创建数据表表中包含一个DATETIME类型的字段dt。
CREATE TABLE test_datetime1(
dt DATETIME
);
Query OK, 0 rows affected (0.02 sec)
插入数据
INSERT INTO test_datetime1
VALUES (2021-01-01 06:50:30), (20210101065030); INSERT INTO test_datetime1
VALUES (99-01-01 00:00:00), (990101000000), (20-01-01 00:00:00),(200101000000);
INSERT INTO test_datetime1
VALUES (20200101000000), (200101000000), (19990101000000), (990101000000); INSERT INTO test_datetime1
VALUES (CURRENT_TIMESTAMP()), (NOW());
6.5 TIMESTAMP类型
TIMESTAMP类型也可以表示日期时间其显示格式与DATETIME类型相同都是 YYYY-MM-DD HH:MM:SS 需要4个字节的存储空间。但是TIMESTAMP存储的时间范围比DATETIME要小很多只能存储 “1970-01-01 00:00:01 UTC”到“2038-01-19 03:14:07 UTC”之间的时间。其中UTC表示世界统一时间也叫作世界标准时间。 存储数据的时候需要对当前时间所在的时区进行转换查询数据的时候再将时间转换回当前的时区。因此使用TIMESTAMP存储的同一个时间值在不同的时区查询时会显示不同的时间。 向TIMESTAMP类型的字段插入数据时当插入的数据格式满足YY-MM-DD HH:MM:SS和YYMMDDHHMMSS时两位数值的年份同样符合YEAR类型的规则条件只不过表示的时间范围要小很多。 如果向TIMESTAMP类型的字段插入的时间超出了TIMESTAMP类型的范围则MySQL会抛出错误信息。 举例 创建数据表表中包含一个TIMESTAMP类型的字段ts。
CREATE TABLE test_timestamp1(
ts TIMESTAMP
);
插入数据
INSERT INTO test_timestamp1
VALUES (1999-01-01 03:04:50), (19990101030405), (99-01-01 03:04:05),(990101030405);
INSERT INTO test_timestamp1
VALUES (20200101000000), (200101000000); INSERT INTO test_timestamp1
VALUES (CURRENT_TIMESTAMP()), (NOW()); #Incorrect datetime value
INSERT INTO test_timestamp1
VALUES (2038-01-20 03:14:07);TIMESTAMP和DATETIME的区别 TIMESTAMP存储空间比较小表示的日期时间范围也比较小 底层存储方式不同TIMESTAMP底层存储的是毫秒值距离1970-1-1 0:0:0 0毫秒的毫秒值。 两个日期比较大小或日期计算时TIMESTAMP更方便、更快。 TIMESTAMP和时区有关。TIMESTAMP会根据用户的时区不同显示不同的结果。而DATETIME则只能反映出插入时当地的时区其他时区的人查看数据必然会有误差的。
CREATE TABLE temp_time(
d1 DATETIME,
d2 TIMESTAMP
);
INSERT INTO temp_time VALUES(2021-9-2 14:45:52,2021-9-2 14:45:52); INSERT INTO temp_time VALUES(NOW(),NOW()); #修改当前的时区
SET time_zone 9:00; 6.6 开发中经验 用得最多的日期时间类型就是 DATETIME 。虽然 MySQL 也支持 YEAR年、 TIME时间、DATE日期以及 TIMESTAMP 类型但是在实际项目中尽量用 DATETIME 类型。因为这个数据类型包括了完整的日期和时间信息取值范围也最大使用起来比较方便。毕竟如果日期时间信息分散在好几个字段很不容易记而且查询的时候SQL 语句也会更加复杂。 此外一般存注册时间、商品发布时间等不建议使用DATETIME存储而是使用 时间戳 因为DATETIME虽然直观但不便于计算。 7. 文本字符串类型 在实际的项目中我们还经常遇到一种数据就是字符串数据。 MySQL中文本字符串总体上分为 CHAR 、 VARCHAR 、 TINYTEXT 、 TEXT 、 MEDIUMTEXT 、 LONGTEXT 、 ENUM 、 SET 等类型。 7.1 CHAR与VARCHAR类型
CHAR和VARCHAR类型都可以存储比较短的字符串。
CHAR类型
CHAR(M) 类型一般需要预先定义字符串长度。如果不指定(M)则表示长度默认是1个字符。如果保存时数据的实际长度比CHAR类型声明的长度小则会在 右侧填充 空格以达到指定的长度。当MySQL检索CHAR类型的数据时CHAR类型的字段会去除尾部的空格。定义CHAR类型字段时声明的字段长度即为CHAR类型字段所占的存储空间的字节数。
CREATE TABLE test_char1(
c1 CHAR,c2 CHAR(5) ); DESC test_char1;INSERT INTO test_char1
VALUES(a,Tom); SELECT c1,CONCAT(c2,***) FROM test_char1;
VARCHAR类型
VARCHAR(M) 定义时 必须指定 长度M否则报错。MySQL4.0版本以下varchar(20)指的是20字节如果存放UTF8汉字时只能存6个每个汉字3字节 MySQL5.0版本以上varchar(20)指的是20字符。检索VARCHAR类型的字段数据时会保留数据尾部的空格。VARCHAR类型的字段所占用的存储空间为字符串实际长度加1个字节。
CREATE TABLE test_varchar1(
NAME VARCHAR #错误
);
#Column length too big for column NAME (max 21845);
CREATE TABLE test_varchar2(
NAME VARCHAR(65535) #错误
);
CREATE TABLE test_varchar3(
NAME VARCHAR(5)
); INSERT INTO test_varchar3
VALUES(尚硅谷),(尚硅谷教育); #Data too long for column NAME at row 1
INSERT INTO test_varchar3
VALUES(尚硅谷IT教育);
哪些情况使用 CHAR 或 VARCHAR 更好 情况1存储很短的信息。比如门牌号码101201……这样很短的信息应该用char因为varchar还要占1个byte用于存储信息长度本来打算节约存储的结果得不偿失。
情况2固定长度的。比如使用uuid作为主键那用char应该更合适。因为他固定长度varchar动态根据长度的特性就消失了而且还要占个长度信息。
情况3十分频繁改变的column。因为varchar每次存储都要有额外的计算得到长度等工作如果一个非常频繁改变的那就要有很多的精力用于计算而这些对于char来说是不需要的。
情况4具体存储引擎中的情况 MyISAM 数据存储引擎和数据列MyISAM数据表最好使用固定长度(CHAR)的数据列代替可变长度(VARCHAR)的数据列。这样使得整个表静态化从而使 数据检索更快 用空间换时间。 MEMORY 存储引擎和数据列MEMORY数据表目前都使用固定长度的数据行存储因此无论使用CHAR或VARCHAR列都没有关系两者都是作为CHAR类型处理的。 InnoDB 存储引擎建议使用VARCHAR类型。因为对于InnoDB数据表内部的行存储格式并没有区分固定长度和可变长度列所有数据行都使用指向数据列值的头指针而且主要影响性能的因素是数据行使用的存储总量由于char平均占用的空间多于varchar所以除了简短并且固定长度的其他考虑varchar。这样节省空间对磁盘I/O和数据存储总量比较好。
7.2 TEXT 类型 在MySQL中TEXT用来保存文本类型的字符串总共包含4种类型分别为TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT 类型。 在向TEXT类型的字段保存和查询数据时系统自动按照实际长度存储不需要预先定义长度。这一点和VARCHAR类型相同。 由于实际存储的长度不确定MySQL 不允许 TEXT 类型的字段做主键。遇到这种情况你只能采用CHAR(M)或者 VARCHAR(M)。
举例 创建数据表
CREATE TABLE test_text(
tx TEXT
);
INSERT INTO test_text
VALUES(atguigu ); SELECT CHAR_LENGTH(tx)
FROM test_text; #10说明在保存和查询数据时并没有删除TEXT类型的数据尾部的空格。
开发中经验 TEXT文本类型可以存比较大的文本段搜索速度稍慢因此如果不是特别大的内容建议使用CHARVARCHAR来代替。还有TEXT类型不用加默认值加了也没用。而且text和blob类型的数据删除后容易导致“空洞”使得文件碎片比较多所以频繁使用的表不建议包含TEXT类型字段建议单独分出去单独用一个表。
8. ENUM类型 ENUM类型也叫作枚举类型ENUM类型的取值范围需要在定义字段时进行指定。设置字段值时ENUM类型只允许从成员中选取单个值不能一次选取多个值。 其所需要的存储空间由定义ENUM类型时指定的成员个数决定。 当ENUM类型包含1255个成员时需要1个字节的存储空间当ENUM类型包含25665535个成员时需要2个字节的存储空间。ENUM类型的成员个数的上限为65535个。
举例 创建表如下
CREATE TABLE test_enum(
season ENUM(春,夏,秋,冬,unknow)
);
添加数据
INSERT INTO test_enum
VALUES(春),(秋); # 忽略大小写
INSERT INTO test_enum
VALUES(UNKNOW); # 允许按照角标的方式获取指定索引位置的枚举值
INSERT INTO test_enum
VALUES(1),(3); # Data truncated for column season at row 1
INSERT INTO test_enum
VALUES(ab); # 当ENUM类型的字段没有声明为NOT NULL时插入NULL也是有效的
INSERT INTO test_enum
VALUES(NULL);
9. SET类型
取值范围内的 0 个或多个值。当SET类型包含的成员个数不同时其所占用的存储空间也是不同的具体如下 SET类型在存储数据时成员个数越多其占用的存储空间越大。注意SET类型在选取成员时可以一次选择多个成员这一点与ENUM类型不同。
举例 创建表
CREATE TABLE test_set(
s SET (A, B, C)
);
向表中插入数据
INSERT INTO test_set (s)
VALUES (A), (A,B); #插入重复的SET类型成员时MySQL会自动删除重复的成员
INSERT INTO test_set (s)
VALUES (A,B,C,A); #向SET类型的字段插入SET成员中不存在的值时MySQL会抛出错误。
INSERT INTO test_set (s) VALUES (A,B,C,D); SELECT *FROM test_set;
举例
CREATE TABLE temp_mul(
gender ENUM(男,女),
hobby SET(吃饭,睡觉,打豆豆,写代码)
);
INSERT INTO temp_mul
VALUES(男,睡觉,打豆豆); #成功 # Data truncated for column gender at row 1
INSERT INTO temp_mul VALUES(男,女,睡觉,写代码); #失败 # Data truncated for column gender at row 1
INSERT INTO temp_mul VALUES(妖,睡觉,写代码);#失败 INSERT INTO temp_mul VALUES(男,睡觉,写代码,吃饭); #成功
10. 二进制字符串类型 MySQL中的二进制字符串类型主要存储一些二进制数据比如可以存储图片、音频和视频等二进制数据。 MySQL中支持的二进制字符串类型主要包括BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB 和
LONGBLOB类型。
BINARY与VARBINARY类型 BINARY和VARBINARY类似于CHAR和VARCHAR只是它们存储的是二进制字符串。 BINARY (M)为固定长度的二进制字符串M表示最多能存储的字节数取值范围是0~255个字符。如果未指定(M)表示只能存储 1个字节 。例如BINARY (8)表示最多能存储8个字节如果字段值不足(M)个字节将在右边填充’\0’以补齐指定长度。 VARBINARY (M)为可变长度的二进制字符串M表示最多能存储的字节数总字节数不能超过行的字节长度限制65535另外还要考虑额外字节开销VARBINARY类型的数据除了存储数据本身外还需要1或2个字节来存储数据的字节数。VARBINARY类型 必须指定(M) 否则报错。 举例 创建表
CREATE TABLE test_binary1(
f1 BINARY,
f2 BINARY(3),
# f3 VARBINARY,
f4 VARBINARY(10)
);添加数据
INSERT INTO test_binary1(f1,f2)
VALUES(a,a); INSERT INTO test_binary1(f1,f2)
VALUES(尚,尚);#失败
INSERT INTO test_binary1(f2,f4)
VALUES(ab,ab); mysql SELECT LENGTH(f2),LENGTH(f4)
- FROM test_binary1;
------------------------
| LENGTH(f2) | LENGTH(f4) |
------------------------
| 3 | NULL || 3 | 2 | ------------------------
2 rows in set (0.00 sec)BLOB类型 BLOB是一个 二进制大对象 可以容纳可变数量的数据。 MySQL中的BLOB类型包括TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB 4种类型它们可容纳值的最大长度不同。可以存储一个二进制的大对象比如 图片 、 音频 和 视频 等。 需要注意的是在实际工作中往往不会在MySQL数据库中使用BLOB类型存储大对象数据通常会将图片、音频和视频文件存储到 服务器的磁盘上 并将图片、音频和视频的访问路径存储到MySQL中。 举例
CREATE TABLE test_blob1(
id INT,
img MEDIUMBLOB
);
TEXT和BLOB的使用注意事项 在使用text和blob字段类型时要注意以下几点以便更好的发挥数据库的性能。
① BLOB和TEXT值也会引起自己的一些问题特别是执行了大量的删除或更新操作的时候。删除这种值会在数据表中留下很大的 空洞 以后填入这些空洞的记录可能长度不同。为了提高性能建议定期使用 OPTIMIZE TABLE 功能对这类表进行 碎片整理 。 ② 如果需要对大文本字段进行模糊查询MySQL 提供了 前缀索引 。但是仍然要在不必要的时候避免检索大型的BLOB或TEXT值。例如SELECT * 查询就不是很好的想法除非你能够确定作为约束条件的WHERE子句只会找到所需要的数据行。否则你可能毫无目的地在网络上传输大量的值。 ③ 把BLOB或TEXT列 分离到单独的表 中。在某些环境中如果把这些数据列移动到第二张数据表中可以让你把原数据表中的数据列转换为固定长度的数据行格式那么它就是有意义的。这会 减少主表中的碎片 使你得到固定长度数据行的性能优势。它还使你在主数据表上运行 SELECT * 查询的时候不会通过网络传输大量的BLOB或TEXT值。
11. JSON 类型 JSONJavaScript Object Notation是一种轻量级的 数据交换格式 。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。它易于人阅读和编写同时也易于机器解析和生成并有效地提升网络传输效率。**JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串然后就可以在网络或者程序之间轻松地传递这个字符串并在需要的时候将它还原为各编程语言所支持的数据格式。 **在MySQL 5.7中就已经支持JSON数据类型。在MySQL 8.x版本中JSON类型提供了可以进行自动验证的JSON文档和优化的存储结构使得在MySQL中存储和读取JSON类型的数据更加方便和高效。 创建数据表表中包含一个JSON类型的字段 js 。
CREATE TABLE test_json(
js json
);向表中插入JSON数据。
INSERT INTO test_json (js)
VALUES ({name:songhk, age:18, address:{province:beijing,city:beijing}});
查询t19表中的数据。
mysql SELECT *
- FROM test_json; 当需要检索JSON类型的字段中数据的某个具体值时可以使用“-”和“-”符号。 12. 空间类型(略)
13. 小结及选择建议 在定义数据类型时如果确定是 整数 就用 INT 如果是 小数 一定用定点数类型 DECIMAL(M,D) 如果是日期与时间就用 DATETIME 。 这样做的好处是首先确保你的系统不会因为数据类型定义出错。不过凡事都是有两面的可靠性好并不意味着高效。比如TEXT 虽然使用方便但是效率不如 CHAR(M) 和 VARCHAR(M)。 关于字符串的选择建议参考如下阿里巴巴的《Java开发手册》规范 阿里巴巴《Java开发手册》之MySQL数据库 任何字段如果为非负数必须是 UNSIGNED【 强制 】小数类型为 DECIMAL禁止使用 FLOAT 和 DOUBLE。说明在存储的时候FLOAT 和 DOUBLE 都存在精度损失的问题很可能在比较值的时候得到不正确的结果。如果存储的数据范围超过 DECIMAL 的范围建议将数据拆成整数和小数并分开存储。【 强制 】如果存储的字符串长度几乎相等使用 CHAR 定长字符串类型。【 强制 】VARCHAR 是可变长字符串不预先分配存储空间长度不要超过 5000。如果存储长度大于此值定义字段类型为 TEXT独立出来一张表用主键来对应避免影响其它字段索引效率。