常用数据类型与约束

孤街浪徒 提交于 2019-11-27 23:45:49

常用数据类型与约束

数据类型

创建表的完整语法

# 语法:
create table 表名(
    字段1 类型[(宽度) 约束条件],
    字段2 类型[(宽度) 约束条件],
    字段3 类型[(宽度) 约束条件])
# 注意:
1.在同一张表中,字段名不能相同
2.宽度和约束条件可选,字段名和类型是必须的
3.最后一个字段后不能加逗号!

# 补充:
# 1.宽度指的是对存储数据的限制
create table userinfo(name char);
insert into userinfo values("jason");
"""
1.没有安全模式的数据库版本,能够存放数据但是只会存进去一个j
2.最新数据库版本直接报错提示无法存储:Data too long for coulumn "name" at row1
"""

# 2.约束条件初始>>>
create table t1(id int,name char not null);
insert into t1 values(1,"j");  # 正常存储
insert into t1 values(2,"null");  # 报错

# 总结:类型与约束条件区别
# 类型:限制字段必须以什么样的数据类型之外添加一种额外的限制

整型

1.tinyint:1个字节,有符号:-128~127,无符号:0~255
2.smallint:2个字节
3.mediumint:3个字节
4.int:4个字节
5.bigint:8个字节

一个字节1bytes就是8位二进制,范围是有符号(-128, 127),无符号(0, 255),

# 注意:默认情况下整数是有符号的

# 设置为无符号的三种方式

# 新建表的时候:create table 表名(字节名 tinyint unsigned);
# 新建字节:alter table 表名 add 字节名 tinyint unsigned;
# 修改字节:alter table 表名 modify 字节名 tinyint unsigned;

# 测试整数默认情况下有无符号
mysql> create table t1(id tinyint);
# 严格模式就会报错,非严格模式就会保存成127,说明是默认情况下是有符号的
mysql> insert into t1 values(200);

# 指定长度
mysql> create table t2(id int(10) zerofill);
mysql> insert into t2 values(1);
mysql> select * from t2;
+------------+
| id         |
+------------+
| 0000000001 |
+------------+
1 row in set (0.01 sec)

# int(10) 如果你的数据不足10位,用0填充(需要添加zerofill 这个约束)
# 对于整数和小数而言,都是用来控制显示填充的最小长度


# int(n):n并不代表能够存储的最大长度,只有在定义zerofill时有用,不满足长度就在前面补零
create table t(num int(5) zerofill unsigned not null);  # 无符号不为空用0填充
insert into t values(12345),(123);
mysql> select * from t;
+--------+
| num    |
+--------+
| 123456 |
|  00123 |
+--------+
# 验证整型字段有无符号及范围
create table t1(x tinyint);
insert into t1 values(128),(-129);

create table t2(x tinyint unsigned);
insert into t2 values(-1),(256);

create table t3(x int unsigned);
insert into t3 values(4294967296);

疑问:类型后面的宽度能够改变字段存储的大小限制

create table t4(x int(8));
insert into t4 values(4294967296123);

# 显示时,不够8位用0填充,如果超出8位则正常显示
create table t5(x int(8) unsigned zerofull);
insert into t5 values(4294967296123);

# create table t6(id int(10) unsigned);
# create table t7(id int(11));

==强调:对于整型开说,数据类型后的宽度并不是存储限制,而是显示宽度限制,所以在创建表时,如果字段采用的是整型类型,完全无需指定显示宽度,默认的显示宽度,足够显示完整当初存放的数据。==

浮点型

1.float:最大总位数m 255,小数位d 30
2.double:最大总位数m 255,小数位d 30
3.decimal:最大总位数m 65,小数位d 30。精度最高

# 精确度:float < double < decimal

# 存储限制
float(255,30)
double(255,30)
decimal(255,30)

# 精确度验证
create table t9(x float(255,30));
create table t10(x float(255,30));
create table t11(x float(65,30));

insert into t9 values(1.111111111111111111111111111111);
insert into t10 values(1.111111111111111111111111111111);
insert into t11 values(1.111111111111111111111111111111);

# 通常会将数字在数据库存储上存成字符串来方便存储。不需要考虑精确度。

字符类型

# 1.char(4):(定长)4表示最大能够存储的字符长度为4,不加长度时默认为1,超出来会直接报错,如果少了,会自动用空格填充,最大可存255个字符
# 2.varchar(4):(变长)4表示最大能够存储的字符长度为4,超过4个会直接报错,如果少于4个,有几个存几个。必须要加长度,能存的长度<21845个字符
# 3.text:可以用来存大量的字符

# 只能保存3个字符,超出3个字符报错,不够3个字符空格补全
create table char_test(name char(3)); 

# 超出5个字符报错,不够5个有几个存几个
create table varchar_test(name varchar(5));  

# 在严格模式下会提示Date too long 错误
insert into char_test values("123"),('12'),("1234"),("你是谁呀"),("你");  

# 正常显示
insert into varchar_test value("你是谁的谁");

# 插入指验证是字节长度还是字符长度。可以插入3个中文字符。所以是指存储的字符长度
insert into char_test values("123"),("12"),("你是谁"),("你");  
select length(name) from char_test;  # 查看字节长度
select char_length(name) from char_test;  # 查看字符长度


create table t10(name char(4));  # 超过4个字符会报错,不够4个字符空格补全
create table t11(name varchar(4));  # 超过4个字符报错,不够四个有几个就存几个  

# 验证存储限制
insert into t12 values("hello");
insert into t13 values("hello");
# 验证存储长度
insert into t12 values("a"); # 'a
insert into t13 values('a'); # 'a'
select * from t12
select * from t13  # 无法查看真正的结果

select char_length(name) from t12
select chat_length(name) from t13  # 依然无法查看到真正对的结果

"""
首先应该肯定的是在硬盘上存的绝对是真正的数据,但显示的时候mysql会自动将末尾的空格取掉
"""
# 如果不想让mysql帮你做自动去除末尾空格的操作,需要再添加一个模式
set global sql_mode = "strict_trans-tables,pad_char_to_full_length";

# 退出客户端重新登录
select char_length(x) from t12; # 4
select char_length(y) from t13; # 1

# 真对char类型,mysql在存储时会将数据用空格补全存放到硬盘中。但是会在读出结果的时候自动去掉末尾的空格


"""
char与varchar的使用区别
"""
name char(5)
# 缺点:浪费硬盘空间
# 优点:存取速度都快
egon alex lxx jxx txx

name varchar(5)
# 缺点:存取速度慢,相对于varchar()而言
# 优点:节省硬盘空间
1bytes+egon 1bytes+alex 1bytes+lxx 1bytes+jxx 1bytes+txx


char存取速度快,varchar会用1字节来存数据的长度,超过255个就用2个字节来存长度。所以varchar存取速度慢

char存的时候会存定长字符长度,但是取的时候会很不要脸的把末尾的空格去掉。可以使用sql_mode=PAS_CAHR_TO_FILL_LENGTH让它现出原形长度,在查询的时候用="李杰"可以查到,但是like"李杰"查询不到,通常不这么做

设置严格模式与非严格模式

我们刚刚在上面设置的char,tinyint,存储数据时超过他们的最大存储长度,发现数据也能正常存储进入,只是mysql帮我们自动截取了最大长度。但在实际情况下,我们应该尽量减少数据库的操作,缓解数据库的压力,让它仅仅只管理数据即可,这样的情况下就需要设置安全模式。

# 模糊匹配
like 
    %匹配任意多个字符
    _匹配任意一个字符
show variables like "%mode%";  # 查看数据库配置中变量名包含mode的配置参数
show variables like "sql_mode";  # 查看数据库配置中变量名包含mode的配置参数

# 修改安全模式
set session sql_mode = "STRICT_TRANS_TABLES" # 只在当前操作界面有效,立即生效
set global sql_mode = "STRICT_TRANS_TABLES" # 全局有效

set global sql_mode = "STRICT_TRANS_TABLES"
# 修改完之后退出当前客户端重新登录即可

mysql> show variables like "sql_mode";
+---------------+------------------------+
| Variable_name | Value                  |
+---------------+------------------------+
| sql_mode      | NO_ENGINE_SUBSTITUTION |  # 非严格模式
+---------------+------------------------+
set sql_mode = strict_trans_tables;  # 设置临时严格模式,只在当前创口操作有效

mysql> set sql_mode = strict_trans_tables;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "sql_mode";
+---------------+---------------------+
| Variable_name | Value               |
+---------------+---------------------+
| sql_mode      | STRICT_TRANS_TABLES |  # 严格模式
+---------------+---------------------+
set sql_mode = ansi;  # 设置非严格模式

mysql> show variables like "sql_mode";
+---------------+------------------------+
| Variable_name | Value                  |
+---------------+------------------------+
| sql_mode      | NO_ENGINE_SUBSTITUTION |
+---------------+------------------------+
1 row in set (0.00 sec)

日期时间类型

日期类型
1.year:年  2019
2.data:日期  2019-05-01 
3.time:时间  11:11:11
4.datetime:占8个字节  2019-05-01 11:11:11
5.timestamp:占4个字节
    
creat table student(
    id int,
    name char(16),
    born_year year,
    birth date,
    study_time time,
    reg_time datetime
);
insert into student values(1,"egon","2019-05-09","11:11:00","2019-11-11 11:11:11");

枚举与集合类型

1.enum('man',"woman","other")  枚举,多选一
2.set('man','woman','other')  集合,可以选多个


create table user(
    id int,
    name char(16),
    gender enum("male","female","other")
);
insert into user values(1,"jason","xxx");  # 报错
insert into user values(2,"egon","female");  # 正确


create table teacher(id int,
                    name char(16),
                    gender enum("male","female","others"),
                    hobby set("read","sleep","sanna","dbj")
                    ):
insert into teacher values(1,"egon","male","read,sleep,dbj");  # 集合也可以只存一个

约束条件

数据库的约束,是对数据安全性,完整性的保证。

"""
not null  标识该字段不能为空,非空
default  为该字段设置默认值
unsigned  无符号
zerofill  使用0填充
primary key (PK)  标识该字段为该表的主键,可以唯一的标识记录
foreign key (FK)  标识该字段为该表的外键
auto_increment  标识该字段的值自动增长(整数类型,而且为主键)
"""

not null+default

create table user(
    id int,
    name char(16)
);
insert into user values(1,null);  # 可以修改
alter table user modify name char(16) not null;
insert into user(name,id) values(null,2);  # 报错,插入数据可以在表名后面指定插入数据对应的字段

create table student(
    id int,
    name char(10) not null,
    gender enum("male","female","other")) default "male"

insert into student(id,name) values(1,"jason");  # 成功

unique key:唯一约束

# 1.id int unique 或则unique(id):单一字段唯一
# 2.unique(ip,port):联合唯一,只有两字段都相同时为重复

# 单列唯一
create table user1(
    id int unique,
    name char(16)
);
insert into user1 values(1,"jason"),(1,"egon");  # 报错
insert into user1 values(1,"jason"),(2,"egon");  # 成功

# 联合唯一
create table server(
    id int,
    ip char(16),
    port int,
    unique(ip,port)
);
insert into server values(1,"127.0.0.1",8080);
insert into server values(2,"127.0.0.1",8080);  # 报错
insert into server values(1,"127.0.0.1",8081);

primary key+auto_increment

# 1.primary key:主键约束,对于innodb存储引擎来说,一张表内必须有一个主键
# 2.id int primary key或则primary key(id):单列主键
# 3.primary key(name,age):复合主键,只有两字段都相同时为重复


# 单从约束角度来说primary key就等价于not null unique
create table t11(id int primary key);
desc t11;
insert into t11 values(1),(1);  # 报错
insert into t11 values(1),(2);

# 除了约束之外,它还是innodb引擎组织数据的依据,提升查询效率
"""
1.一张表必须有且只有一个主键,如果你没有设置主键,那么会从上到下搜索直到遇到一个非空唯一的字段自动将其设置为主键
"""
create table t12(
    id int,
    name char(16),
    age int not null unique,
    addr char(16) not null unique
)engine=innodb;
desc t12;
"""
2.如果表里面没有指定任何的可以设置为主键的字段,那么innodb会采用自己默认的一个隐藏字段作为主键,隐藏意味着你在查询的时候无法根据这个主键字段加速查询了
索引:类似于书的目录,没有主键将相当于一页一页翻着看
3.一张表中通常都应该有一个id字段,并且通常将改id字段作成主键
"""
# 联合主键:多个字段联合起来作为表的一个主键,本质还是一个主键
create table t18(
    ip char(16),
    port int,
    primary key(ip,port)
);
desc t18;

# 主键id作为数据的编号,每次最好能自动递增
create table t13(
    id int primary key auto_increment,
    name char(16)
);
insert into t13("jason"),('jason'),("jason");  # id字段自动从1开始递增
# 注意:auto_increment通常都是加在主键上,并且只能给设置为key的字段加
not null;非空
————————————————————————————————————————————————————————————
default:默认值
————————————————————————————————————————————————————————————
unique key:唯一约束
    * id int unique 或则unique(id):单一唯一
    * unique(name,age):联合唯一,只有两字段都相同时为重复
————————————————————————————————————————————————————————————



auto_increment:自动增长:可以自定义增长,与primary key搭配使用
    * show variables like "auto_incr%";
    mysql> show variables like "auto_incr%";
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | auto_increment_increment | 1     |  # 步长
    | auto_increment_offset    | 1     |  # 起始偏移量位置,必须小于等于步长
    +--------------------------+-------+
    set global auto_increment_increment = 5;  # 全局改
    set session auto_increment_increment = 3;  # 会话层改,下次回到默认值
————————————————————————————————————————————————————————————

foreign key(id) references biao(id)  # 外键约束,建立表之间的关系
on delete cascade  # 级联删除,删除主表时,从表跟着删除
# 建立表
    * 先建被关联的表,并且保证被关联的字段唯一
    * 再建关联的表:从表
# 插入表
    * 先往被关联的表插入数据
    * 再往关联表插入记录
# 删除、更新数据
    * 先删除、更新先操作关联表
    * 再操作被关联的表
    * 用了on delete|update cascade就可以先操作被关联的主表
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!