数据类型(列类型)
SQL中将数据类型分成了三大类: 数值类型, 字符串类型和时间日期类型
数值型
整数型
存放整型数据: 在SQL中因为更多要考虑如何节省磁盘空间, 所以系统将整型又细分成了5类:
Tinyint: 迷你整型,使用一个字节存储, 表示的状态最多为256种(常用)
Smallint: 小整型,使用2个字节存储,表示的状态最多为65536种
Mediumint: 中整型, 使用3个字节存储
Int: 标准整型, 使用4个字节存储(常用)
Bigint: 大整型,使用8个字节存储
创建一张整形表
插入数据: 只能插入整型, 只能插入范围内的整型
SQL中的数值类型全部都是默认有符号: 分正负
有时候需要使用无符号数据: 需要给数据类型限定: int unsigned; — 无符号: 从0开始
数据的插入
查看表结构的时候,发现每个字段的数据类型之后都会自带一个括号,里面有指定的数字
显示宽度: 没有特别的含义, 只是默认的告诉用户可以显示的形式而已: 世界上用户是可以控制的,这种控制不会改变数据本身的大小.
显示宽度的意义: 在于当数据不够显示宽度的时候,会自动让数据变成对应的显示宽度: 通常需要搭配一个前导0来增加宽度, 不改变值大小: zerofill(零填充): 零填充会导致数值自动变成无符号,因为如果数字为-1,前填充0就变成0-1,所以添加zerofill属性,也会给这个列增加unsigned属性
零填充+显示宽度的效果
零填充的意义(显示宽度): 保证数据格式
小数型
小数型: 带有小数点或者范围超出整型的数值类型.
SQL中: 将小数型细分成两种: 浮点型和定点型
浮点型: 小数点浮动, 精度有限,而且会丢失精度
定点型: 小数点固定, 精度固定, 不会丢失精度
浮点型
浮点型数据是一种精度型数据: 因为超出指定范围之后, 会丢失精度(自动四舍五入)
浮点型: 理论分为两种精度
Float: 单精度, 占用4个字节存储数据, 精度范围大概为7位左右
- float单精度小数部分只能精确到后面6位,加上小数点前的一位,即有效数字为7位
Double: 双精度,占用8个字节存储数据, 精度方位大概为15位左右
- double双精度小数部分能精确到小数点后的15位,加上小数点前的一位 有效位数为16位。
FLOAT 类型的取值范围如下:
- 有符号的取值范围:-3.402823466E+38~-1.175494351E-38。
- 无符号的取值范围:0 和 -1.175494351E-38~-3.402823466E+38。
DOUBLE 类型的取值范围如下:
- 有符号的取值范围:-1.7976931348623157E+308~-2.2250738585072014E-308。
- 无符号的取值范围:0 和 -2.2250738585072014E-308~-1.7976931348623157E+308。
计算器表达10的幂是一般是用E或e
3.4E+38:3.4乘以10的38次方,10的38次方也就是小数部分有38位
所以3.4E+38的值为:34后面加37个0
浮点的使用方式: 直接float表示没有小数部分; float(M,D): M代表总长度,D代表小数部分长度, 整数部分长度为M-D
插入数据: 可以是直接小数,也可以是科学计数法
浮点型数据的插入: 整型部分是不能超出长度的,但是小数部分可以超出长度(系统会自动四舍五入)
结果: 浮点数一定会进行四舍五入(超出精度范围): 浮点数如果是因为系统进位导致整数部分超出指定的长度,那么系统也允许成立.
定点型
decimal内部以字符形式存储小数,属于准确存储。在设置精度的范围内,存储数据都不会发生精度丢失;超出设置的精度,都会四舍五入进行截取,导致精度丢失。
创建定点数表: 以浮点数作为对比
插入数据: 定点数的整数部分一定不能超出长度(进位不可以),小数部分的长度可以随意超出(系统自动四舍五入)
浮点数如果进位导致长度溢出没有问题,但是定点数不行
查看数据效果
时间日期类型
Datetime: 时间日期, 格式是YYYY-mm-dd HH:ii:ss,表示的范围是从1000到9999年,有0值: 0000-00-00 00:00:00
Date: 日期,就是datetime中的date部分
Time: 时间(段), 指定的某个区间之间, -时间到+时间
Timestamp: 时间戳, 并不是时间戳,只是从1970年开始的YYYY-mm-dd HH:ii:ss格式与datetime完全一致
Year: 年份,两种形式, year(2)和year(4): 1901-2156
创建时间日期表
插入数据: 时间time可以是负数,而且可以是很大的负数, year可以使用2位数插入,也可以使用4位数
Timestamp字段: 只要当前所在的记录被更新, 该字段一定会自动更新成当前时间
自动更新指的是如果修改了其它字段,则该字段的值将自动更新为当前系统时间。
它与“explicit_defaults_for_timestamp”参数有关。
默认情况下,该参数的值为OFF
mysql> show variables like ‘%explicit_defaults_for_timestamp%’;
在MySQL 5.6.5版本之前,Automatic Initialization and Updating只适用于TIMESTAMP,而且一张表中,最多允许一个TIMESTAMP字段采用该特性。从MySQL 5.6.5开始,Automatic Initialization and Updating同时适用于TIMESTAMP和DATETIME,且不限制数量。
网站是以PHP为实现的主要操作对象: PHP中有非常强大的时间日期处理函数: date,只需要一个时间戳就可以转换成任意类型的时间:
以PHP为主的时候, 都是在数据库使用时间戳(整型int)来存储时间.
如果要保存直观的时间,如:2018-03-04 18:57:48,可以选择用datetime和timestamp。两者区别如下:
1 最主要的区别-受时区影响不同。timestamp会跟随设置的时区变化而变化,而datetime保存的是绝对值不会变化。
对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储。查询时,将其又转化为客户端当前时区进行返回。
UTC格式:YYYYMMDD T HHMMSS Z(或者时区标识)。
例如,20100607T152000Z,表示2010年6月7号15点20分0秒,Z表示是标准时间
而对于DATETIME,不做任何改变,基本上是原样输入和输出。
2 自动更新时间。Timestamp字段: 只要当前所在的记录被更新, 该字段会自动更新成当前时间,explicit_defaults_for_timestamp”参数有关,默认关闭。MySQL5.6.5开始,该设置同样适用于datetime。
3 占用存储空间不同。timestamp储存占用4个字节,datetime储存占用8个字可表示的时间范围不同。
4 timestamp可表示范围:1970-01-01 00:00:00~2038-01-09 03:14:07,datetime支持的5 范围更宽1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
6 索引速度不同。timestamp更轻量,索引相对datetime更快。
结论:可见两者的存储格式完全一样,timestamp效率更高,但是有很多限制。个人推荐使用datetime避免麻烦。
字符串类型
在SQL中,将字符串类型分成了6类: char,varchar,text , blob, enum和set
定长字符串
定长字符串: char, 磁盘(二维表)在定义结构的时候,就已经确定了最终数据的存储长度.
Char(L): L代表length, 可以存储的长度, 单位为字符, 最大长度值可以为255字符.
Char(4): 在UTF8 环境下,需要4 * 3 = 12个字节
变长字符串
变长字符串: varchar, 在分配空间的时候, 按照最大的空间分配: 但是实际上最终用了多少,是根据具体的数据来确定.
Varchar(L): L表示字符长度 理论长度是65536个字符, 但是会多处1到2个字节来确定存储的实际长度(L小于255需要一个字节,大于255需要2个字节): 但是实际上如果长度超过255,既不用定长也不用变长, 使用文本字符串text
Varchar(10): 的确存了10个汉字, utf8环境, 10 3 + 1 = 31(bytes)
存储了3个汉字: 3 3 + 1 = 10(bytes)
- MySQL |
ver < 4.1
: VARCHAR以字节为单位存储,所以假设全部为常用汉字(UTF-8 3字节编码长度),则VARCHAR(255)共可存放约85个汉字; MySQL |
ver >= 4.1
: VARCHAR以字符为单位存储,假设输入仍然为常用汉字,则VARCHAR(255)可以存放255个汉字。
定长与变长的存储实际空间(UTF8)
实际存储数据 | Char(4) | Varchar(4) | Char占用字节 | Varchar(占用字节) |
---|---|---|---|---|
ABCD | ABCD | ABCD | 4 * 3 = 12 | 4 * 3 + 1 = 13 |
A | A | A | 4 * 3 = 12 | 1 * 3 + 1 = 4 |
ABCDE | 数据超过长度 | 数据超过长度 |
如何选择定长或者是变长字符串呢?
定长的磁盘空间比较浪费, 但是效率高: 如果数据基本上确定长度都一样, 就是使用定长, 如身份证, 电话号码, 手机号码等
变长的磁盘空间比较节省, 但是效率低: 如果数据不能确定长度(不同数据有变化), 如姓名, 地址等
文本字符串
如果数据量非常大, 通常说超过255个字符就会使用文本字符串
文本字符串根据存储的数据的格式进行分类: text和blob
Text: 存储文字(二进制数据实际上都是存储路径)
Blob: 存储二进制数据(通常不用)
枚举字符串
枚举: enum, 事先将所有可能出现的结果都设计好, 实际上存储的数据必须是规定好的数据中的一个.
枚举的使用方式
定义: enum(可能出现的元素列表); //如enum(‘男’,’女’,’不男不女’,’妖’,’保密’);
使用: 存储数据,只能存储上面定义好的数据
创建枚举表
加入数据: 作用之一: 规范数据格式: 数据只能是规定的数据中的其中一个
作用之二: 节省存储空间(枚举通常有一个别名: 单选框): 枚举实际存储的是数值而不是字符串本身.
在mysql中,系统也是自动转换数据格式的: 而且基本与PHP一样(尤其是字符串转数字)
证明字段存储的数据是数值: 将数据取出来 + 0 就可以判断出原来的数据存的到底是字符串还是数值: 如果是字符串最终结果永远为0, 否则就是其他值.
找出了枚举元素的实际规律: 按照元素出现的顺序, 从1开始编号
枚举原理: 枚举在进行数据规范的时候(定义的时候),系统会自动建立一个数字与枚举元素的对应关系(关系放到日志中): 然后在进行数据插入的时候,系统自动将字符转换成对应的数字存储, 然后在进行数据提取的时候, 系统自动将数值转换成对应的字符串显示.
如果是存全国的城市就不适合用枚举,因为枚举将字符转换成数字是降低效率的。目前硬件便宜,磁盘降价。效率为主
因为枚举实际存储的是数值,所以可以直接插入数值.
集合字符串
集合跟枚举很类似: 实际存储的是数值,而不是字符串(集合是多选)
集合使用方式:
定义: Set(元素列表)
使用: 可以使用元素列表中的元素(多个), 使用逗号分隔
创建集合表
插入数据: 可以使用多个元素字符串组合, 也可以直接插入数值
查看数据: 数值 + 数据查看
集合中没一个元素都是对应一个对应二进制位
集合中元素的顺序没有关系: 最终系统都会去匹配顺序
集合的强大在于能够规范数据和节省空间: PHP也可以规范数据, 但是对于PHP来说效率优先, 而且数据的维护可以通过数字进行, 增加PHP的维护成本: PHP根本没有办法判断数据在数据库的形式.
Mysql记录长度
Mysql中规定: 任何一条记录最长不能超过65535个字节.(varchar永远达不到理论值)
Varchar的实际存储长度能达到多少呢? 看字符集编码.
Utf8 下varchar的实际顶配: 21844字符
GBK下的varchar的实际顶配: 32766字符
想用完整个65535个字节长度: 增加一个tinyint字段即可
Mysql记录中: 如果有任何一个字段允许为空,那么系统会自动从整个记录中保留一个字节来存储NULL(若想释放NULL所占用的字节: 必须保证所有的字段都不允许为空,多个NULL只占用一个字节存储null)
Mysql中text文本字符串,不占用记录长度: 额外存储. 但是text文本字符串也是属于记录的一部分: 一定需要占据记录中的部分长度: 10个字节(保存数据的地址以及长度).
列属性
列属性: 真正约束字段的是数据类型, 但是数据类型的约束很单一. 需要有一些额外的约束, 来更加保证数据的合法性.
列属性有很多: NULL/NOT NULL, default, Primary key, unique key, auto_increment,comment
空属性
两个值: NULL(默认的)和NOT NULL(不为空)
虽然默认的, 数据库基本都是字段为空, 但是实际上在真实开发的时候, 尽可能的要保证所有的数据都不应该为空: 空数据没有意义; 空数据没有办法参与运算.
创建一个实际案例表: 班级表(名字,教室)
列描述
列描述: comment, 描述, 没有实际含义: 是专门用来描述字段,会根据表创建语句保存: 用来给程序猿(数据库管理员)来进行了解的.
默认值
默认值: 某一种数据会经常性的出现某个具体的值, 可以在一开始就指定好: 在需要真实数据的时候,用户可以选择性的使用默认值.
默认值关键字: default
默认值的生效: 使用, 在数据进行插入的时候,不给改字段赋值
想要使用默认值,可以不一定去指定列表,故意不使用字段列表: 可以使用default关键字代替值