爲了防止不符合規範的數據進入數據庫,在用戶對數據進行插入、修改、刪除等操做時,DBMS自動按照必定的約束條件對數據進行監測,使不符合規範的數據不能進入數據庫,以確保數據庫中存儲的數據正確、有效、相容。python
約束條件與數據類型的寬度同樣,都是可選參數,主要分爲如下幾種:mysql
約束條件 | 解釋 |
---|---|
NOT NULL | 非空約束,指定某列不能爲空; |
UNIQUE | 惟一約束,指定某列或者幾列組合不能重複 |
PRIMARY KEY | 主鍵,指定該列的值能夠惟一地標識該列記錄 |
FOREIGN KEY | 外鍵,指定該行記錄從屬於主表中的一條記錄,主要用於參照完整性 |
是否可控,null表示空,非空字符串nginx
not null - 不可空sql
null - 可空數據庫
mysql> create table t12 (id int not null); Query OK, 0 rows affected (0.02 sec) mysql> select * from t12; Empty set (0.00 sec) mysql> desc t12; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | | NULL | | +-------+---------+------+-----+---------+-------+ row in set (0.00 sec) #不能向id列插入空元素。 mysql> insert into t12 values (null); ERROR 1048 (23000): Column 'id' cannot be null mysql> insert into t12 values (1); Query OK, 1 row affected (0.01 sec)
咱們約束某一列不爲空,若是這一列中常常有重複的內容,就須要咱們頻繁的插入,這樣會給咱們的操做帶來新的負擔,因而就出現了默認值的概念。session
默認值,建立列時能夠指定默認值,當插入數據時若是未主動設置,則自動添加默認值。架構
mysql> create table t13 (id1 int not null,id2 int not null default 222); Query OK, 0 rows affected (0.01 sec) mysql> desc t13; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id1 | int(11) | NO | | NULL | | | id2 | int(11) | NO | | 222 | | +-------+---------+------+-----+---------+-------+ rows in set (0.01 sec) # 只向id1字段添加值,會發現id2字段會使用默認值填充 mysql> insert into t13 (id1) values (111); Query OK, 1 row affected (0.00 sec) mysql> select * from t13; +-----+-----+ | id1 | id2 | +-----+-----+ | 111 | 222 | +-----+-----+ row in set (0.00 sec) # id1字段不能爲空,因此不能單獨向id2字段填充值; mysql> insert into t13 (id2) values (223); ERROR 1364 (HY000): Field 'id1' doesn't have a default value # 向id1,id2中分別填充數據,id2的填充數據會覆蓋默認值 mysql> insert into t13 (id1,id2) values (112,223); Query OK, 1 row affected (0.00 sec) mysql> select * from t13; +-----+-----+ | id1 | id2 | +-----+-----+ | 111 | 222 | | 112 | 223 | +-----+-----+ rows in set (0.00 sec)
設置嚴格模式: 不支持對not null字段插入null值 不支持對自增加字段插入」值 不支持text字段有默認值 直接在mysql中生效(重啓失效): mysql>set sql_mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"; 配置文件添加(永久失效): sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
惟一約束,指定某列或者幾列組合不能重複。sqlserver
方法一: create table department1( id int, name varchar(20) unique, comment varchar(100) ); 方法二: create table department2( id int, name varchar(20), comment varchar(100), 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'
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)
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'
主鍵爲了保證表中的每一條數據的該字段都是表格中的惟一值。換言之,它是用來獨一無二地確認一個表格中的每一行數據。
主鍵能夠包含一個字段或多個字段。當主鍵包含多個欄位時,稱爲組合鍵 (Composite Key),也能夠叫聯合主鍵。
主鍵能夠在建置新表格時設定 (運用 CREATE TABLE 語句),或是以改變現有的表格架構方式設定 (運用 ALTER TABLE)。
主鍵必須惟一,主鍵值非空;能夠是單一字段,也能夠是多字段組合。翻譯
============單列作主鍵=============== #方法一: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), 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) # 方法四:給已經建成的表添加主鍵約束 mysql> create table department4( -> id int, -> name varchar(20), -> comment varchar(100)); Query OK, 0 rows affected (0.01 sec) mysql> desc department4; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.01 sec) mysql> alter table department4 modify id int primary key; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc department4; +---------+--------------+------+-----+---------+-------+ | 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'
約束字段爲自動增加,被約束的字段必須同時被key約束code
#不指定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 -> ('nick'), -> ('tank') -> ; mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | nick | male | | 2 | tank | 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 | nick | male | | 2 | tank | 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('nick'); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | nick | male | +----+------+------+ row in set (0.00 sec)
#在建立完表後,修改自增字段的起始值 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('nick'); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 3 | nick | 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('nick1'),('nick2'),('nick3'); mysql> select * from student; +----+-------+------+ | id | name | sex | +----+-------+------+ | 3 | nick1 | male | | 8 | nick2 | male | | 13 | nick3 | male | +----+-------+------+ 步長:auto_increment_increment,起始偏移量:auto_increment_offset
多表 :
假設咱們要描述全部公司的員工,須要描述的屬性有這些 : 工號 姓名 部門
公司有3個部門,可是有1個億的員工,那意味着部門這個字段須要重複存儲,部門名字越長,越浪費
解決方法: 咱們徹底能夠定義一個部門表 而後讓員工信息表關聯該表,如何關聯,即foreign key
mysql> create table departments (dep_id int(4),dep_name varchar(11)); Query OK, 0 rows affected (0.02 sec) mysql> desc departments; +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | dep_id | int(4) | YES | | NULL | | | dep_name | varchar(11) | YES | | NULL | | +----------+-------------+------+-----+---------+-------+ rows in set (0.00 sec) # 建立外鍵不成功 mysql> create table staff_info (s_id int,name varchar(20),dep_id int,foreign key(dep_id) references departments(dep_id)); ERROR 1215 (HY000): Cannot add foreign key # 設置dep_id非空,仍然不能成功建立外鍵 mysql> alter table departments modify dep_id int(4) not null; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc departments; +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | dep_id | int(4) | NO | | NULL | | | dep_name | varchar(11) | YES | | NULL | | +----------+-------------+------+-----+---------+-------+ rows in set (0.00 sec) mysql> create table staff_info (s_id int,name varchar(20),dep_id int,foreign key(dep_id) references departments(dep_id)); ERROR 1215 (HY000): Cannot add foreign key constraint # 當設置字段爲unique惟一字段時,設置該字段爲外鍵成功 mysql> alter table departments modify dep_id int(4) unique; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc departments; +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | dep_id | int(4) | YES | UNI | NULL | | | dep_name | varchar(11) | YES | | NULL | | +----------+-------------+------+-----+---------+-------+ rows in set (0.01 sec) mysql> create table staff_info (s_id int,name varchar(20),dep_id int,foreign key(dep_id) references departments(dep_id)); Query OK, 0 rows affected (0.02 sec)
#表類型必須是innodb存儲引擎,且被關聯的字段,即references指定的另一個表的字段,必須保證惟一 create table department( id int primary key, name varchar(20) not null )engine=innodb; #dpt_id外鍵,關聯父表(department主鍵id),同步更新,同步刪除 create table employee( id int primary key, name varchar(20) not null, dpt_id int, foreign key(dpt_id) references department(id) on delete cascade # 級連刪除 on update cascade # 級連更新 )engine=innodb; #先往父表department中插入記錄 insert into department values (1,'教質部'), (2,'技術部'), (3,'人力資源部'); #再往子表employee中插入記錄 insert into employee values (1,'jason',1), (2,'oscar',2), (3,'nick',2), (4,'tank',2), (5,'mac',3), (6,'李沁洋',3), (7,'皮卡丘',3), (8,'程咬金',3), (9,'程咬銀',3) ; #刪父表department,子表employee中對應的記錄跟着刪 mysql> delete from department where id=2; Query OK, 1 row affected (0.00 sec) mysql> select * from employee; +----+-----------+--------+ | id | name | dpt_id | +----+-----------+--------+ | 1 | jason | 1 | | 5 | mac | 3 | | 6 | 李沁洋 | 3 | | 7 | 皮卡丘 | 3 | | 8 | 程咬金 | 3 | | 9 | 程咬銀 | 3 | +----+-----------+--------+ rows in set (0.00 sec) #更新父表department,子表employee中對應的記錄跟着改 mysql> update department set id=2 where id=3; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from employee; +----+-----------+--------+ | id | name | dpt_id | +----+-----------+--------+ | 1 | jason | 1 | | 5 | mac | 2 | | 6 | 李沁洋 | 2 | | 7 | 皮卡丘 | 2 | | 8 | 程咬金 | 2 | | 9 | 程咬銀 | 2 | +----+-----------+--------+ rows in set (0.00 sec)
. cascade方式 在父表上update/delete記錄時,同步update/delete掉子表的匹配記錄 . set null方式 在父表上update/delete記錄時,將子表上匹配記錄的列設爲null 要注意子表的外鍵列不能爲not null . No action方式 若是子表中有匹配的記錄,則不容許對父表對應候選鍵進行update/delete操做 . Restrict方式 同no action, 都是當即檢查外鍵約束 . Set default方式 父表有變動時,子表將外鍵列設置成一個默認的值 但Innodb不能識別