1. 程式人生 > >myql之完整性約束

myql之完整性約束

reat session 約束 單單 varchar ngs field lob 應該

一 介紹

約束條件與數據類型的寬度一樣,都是可選參數

作用:用於保證數據的完整性和一致性
主要分為:

PRIMARY KEY (PK)    標識該字段為該表的主鍵,可以唯一的標識記錄
FOREIGN KEY (FK)    標識該字段為該表的外鍵
NOT NULL    標識該字段不能為空
UNIQUE KEY (UK)    標識該字段的值是唯一的
AUTO_INCREMENT    標識該字段的值自動增長(整數類型,而且為主鍵)
DEFAULT    為該字段設置默認值

UNSIGNED 無符號
ZEROFILL 使用0填充

註意:

1. 是否允許為空,默認NULL,可設置NOT NULL,字段不允許為空,必須賦值
2. 字段是否有默認值,缺省的默認值是NULL,如果插入記錄時不給字段賦值,此字段使用默認值 sex enum(male,female) not null default male age int unsigned NOT NULL default 20 必須為正值(無符號) 不允許為空 默認是20 3. 是否是key 主鍵 primary key 外鍵 foreign key 索引 (index,unique...)

二 not null與default

是否可空,null表示空,非字符串
not null - 不可空
null - 可空


默認值,創建列時可以指定默認值,當插入數據時如果未主動設置,則自動添加默認值
create table tb1(
id int not null defalut 2,
num int not null
)

技術分享圖片
==================not null====================
mysql> create table t1(id int); #id字段默認可以插入空
mysql> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
mysql
> insert into t1 values(); #可以插入空 mysql> create table t2(id int not null); #設置字段id不為空 mysql> desc t2; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | | NULL | | +-------+---------+------+-----+---------+-------+ mysql> insert into t2 values(); #不能插入空 ERROR 1364 (HY000): Field id doesnt have a default value ==================default==================== #設置id字段有默認值後,則無論id字段是null還是not null,都可以插入空,插入空默認填入default指定的默認值 mysql> create table t3(id int default 1); mysql> alter table t3 modify id int not null default 1; ==================綜合練習==================== mysql> create table student( -> name varchar(20) not null, -> age int(3) unsigned not null default 18, -> sex enum(male,female) default male, -> hobby set(play,study,read,music) default play,music -> ); mysql> desc student; +-------+------------------------------------+------+-----+------------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------------------------+------+-----+------------+-------+ | name | varchar(20) | NO | | NULL | | | age | int(3) unsigned | NO | | 18 | | | sex | enum(male,female) | YES | | male | | | hobby | set(play,study,read,music) | YES | | play,music | | +-------+------------------------------------+------+-----+------------+-------+ mysql> insert into student(name) values(egon); mysql> select * from student; +------+-----+------+------------+ | name | age | sex | hobby | +------+-----+------+------------+ | egon | 18 | male | play,music | +------+-----+------+------------+
驗證

三 unique (key)(*****)

技術分享圖片
============設置唯一約束 UNIQUE===============
方法一:
create table department1(
id int,
name varchar(20) unique,
comment varchar(100)
);


方法二:
create table department2(
id int,
name varchar(20),
comment varchar(100),
constraint uk_name unique(name)
);


mysql> insert into department1 values(1,IT,技術);
Query OK, 1 row affected (0.00 sec)
mysql> insert into department1 values(1,IT,技術);
ERROR 1062 (23000): Duplicate entry IT for key name
唯一約束unique 技術分享圖片
mysql> create table t1(id int not null unique);
Query OK, 0 rows affected (0.02 sec)

mysql> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   | PRI | NULL    |       |
+-------+---------+------+-----+---------+-------+
row in set (0.00 sec)

這是由於mysql內部存儲和查找機制決定的,mysql內部存儲查找都是基於索引的,這就要求每一個表都必須有一個主鍵primary key,mysql就會依據這個key來組織數據,這樣可以優化查找速度,相當於目錄,
也就是說,如果你創建表是沒有指定主鍵,那麽mysql會從上自下自動查找你的定義字段,只要遇到非空和唯一字段,就會自動將其設置為主鍵,而如果非空且唯一字段也沒有的話,那麽mysql會默認用自帶的隱藏主鍵,但是這樣的話就喪失優化查找的能力,大大降低了效率。
not null+unique的化學反應 技術分享圖片
create table service(
id int primary key auto_increment,
name varchar(20),
host varchar(15) not null,
port int not null,
unique(host,port) #聯合唯一
);

mysql> insert into service values
    -> (1,nginx,192.168.0.10,80),
    -> (2,haproxy,192.168.0.20,80),
    -> (3,mysql,192.168.0.30,3306)
    -> ;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into service(name,host,port) values(nginx,192.168.0.10,80);
ERROR 1062 (23000): Duplicate entry 192.168.0.10-80 for key host

聯合的任意一方都可以單獨重復,但是雙方組合起來的數據不能重復,這就是聯合唯一!
聯合唯一

四 primary key(******)

從約束角度看primary key字段的值不為空且唯一,那我們直接使用not null+unique不就可以了嗎,要它幹什麽?

主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之為索引組織表,一張表中必須有且只有一個主鍵。

一個表中可以:

單列做主鍵
多列做主鍵(復合主鍵)

技術分享圖片
============單列做主鍵===============
#方法一:not null+unique
create table department1(
id int not null unique, #主鍵
name varchar(20) not null unique,
comment varchar(100)
);

mysql> desc department1;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | NO   | UNI | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

#方法二:在某一個字段後用primary key
create table department2(
id int primary key, #主鍵
name varchar(20),
comment varchar(100)
);

mysql> desc department2;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.00 sec)

#方法三:在所有字段後單獨定義primary key
create table department3(
id int,
name varchar(20),
comment varchar(100),
constraint pk_name primary key(id); #創建主鍵並為其命名pk_name

mysql> desc department3;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)
主鍵產生的三者方式 技術分享圖片
==================多列做主鍵================
create table service(
ip varchar(15),
port char(5),
service_name varchar(10) not null,
primary key(ip,port)
);


mysql> desc service;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| ip           | varchar(15) | NO   | PRI | NULL    |       |
| port         | char(5)     | NO   | PRI | NULL    |       |
| service_name | varchar(10) | NO   |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+
rows in set (0.00 sec)

mysql> insert into service values
    -> (172.16.45.10,3306,mysqld),
    -> (172.16.45.11,3306,mariadb)
    -> ;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into service values (172.16.45.10,3306,nginx);
ERROR 1062 (23000): Duplicate entry 172.16.45.10-3306 for key PRIMARY
聯合主鍵

五 auto_increment

約束字段為自動增長,被約束的字段必須同時被key約束(unique key,primary key)

技術分享圖片
#不指定id,則自動增長
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum(male,female) default male
);

mysql> desc student;
+-------+-----------------------+------+-----+---------+----------------+
| Field | Type                  | Null | Key | Default | Extra          |
+-------+-----------------------+------+-----+---------+----------------+
| id    | int(11)               | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)           | YES  |     | NULL    |                |
| sex   | enum(male,female) | YES  |     | male    |                |
+-------+-----------------------+------+-----+---------+----------------+
mysql> insert into student(name) values
    -> (egon),
    -> (alex)
    -> ;

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  1 | egon | male |
|  2 | alex | male |
+----+------+------+


#也可以指定id
mysql> insert into student values(4,asb,female);
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(7,wsb,female);
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+------+--------+
| id | name | sex    |
+----+------+--------+
|  1 | egon | male   |
|  2 | alex | male   |
|  4 | asb  | female |
|  7 | wsb  | female |
+----+------+--------+


#對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增長
mysql> delete from student;
Query OK, 4 rows affected (0.00 sec)

mysql> select * from student;
Empty set (0.00 sec)

mysql> insert into student(name) values(ysb);
mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  8 | ysb  | male |
+----+------+------+

#應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它
mysql> truncate student;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into student(name) values(egon);
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  1 | egon | male |
+----+------+------+
row in set (0.00 sec)
自增在用delete刪除後會發生什麽?

了解知識

技術分享圖片
#在創建完表後,修改自增字段的起始值
mysql> create table student(
    -> id int primary key auto_increment,
    -> name varchar(20),
    -> sex enum(male,female) default male
    -> );

mysql> alter table student auto_increment=3;

mysql> show create table student;
.......
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

mysql> insert into student(name) values(egon);
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  3 | egon | male |
+----+------+------+
row in set (0.00 sec)

mysql> show create table student;
.......
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8


#也可以創建表時指定auto_increment的初始值,註意初始值的設置為表選項,應該放到括號外
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum(male,female) default male
)auto_increment=3;




#設置步長
sqlserver:自增步長
    基於表級別
    create table t1(
        id int。。。
    )engine=innodb,auto_increment=2 步長=2 default charset=utf8

mysql自增的步長:
    show session variables like auto_inc%;
    
    #基於會話級別
    set session auth_increment_increment=2 #修改會話級別的步長

    #基於全局級別的
    set global auth_increment_increment=2 #修改全局級別的步長(所有會話都生效)


#!!!註意了註意了註意了!!!
If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 
翻譯:如果auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值會被忽略 ,這相當於第一步步子就邁大了,扯著了蛋
比如:設置auto_increment_offset=3,auto_increment_increment=2




mysql> set global auto_increment_increment=5;
Query OK, 0 rows affected (0.00 sec)

mysql> set global auto_increment_offset=3;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like auto_incre%; #需要退出重新登錄
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+



create table student(
id int primary key auto_increment,
name varchar(20),
sex enum(male,female) default male
);

mysql> insert into student(name) values(egon1),(egon2),(egon3);
mysql> select * from student;
+----+-------+------+
| id | name  | sex  |
+----+-------+------+
|  3 | egon1 | male |
|  8 | egon2 | male |
| 13 | egon3 | male |
+----+-------+------+
步長:auto_increment_increment,起始偏移量:auto_increment_offset

六 總結

not null與default

技術分享圖片

unique唯一

技術分享圖片

主鍵

#primary key:單單從約束角度去看,primary key就等同於not null unique
#強調(******)
1、一張表中必須有,並且只能有一個主鍵
2、一張表中都應該有一個id字段,而且應該把id字段做成主鍵

create table t17(
id int primary key,
name char(16),
age int,
sex char(6)
)engine=innodb;

#聯合主鍵
create table t19(
ip char(15),
port int,
primary key(ip,port)
);

# primary key auto_increment
create table t20(
id int primary key auto_increment,
name char(16)
)engine=innodb;


# auto_increment註意點:
1、通常與primary key連用,而且通常是給id字段加
2、auto_incremnt只能給被定義成key(unique key,primary key)的字段加

myql之完整性約束