閱讀目錄---MySQL常見的建表選項及約束:mysql
一、create table選項sql
二、指定表選項:engine、auto_increment、comment函數
二、create table約束 測試
一、not null:非空約束spa
二、unique:惟一約束rest
三、primary key:主鍵約束code
四、foreign key:外鍵orm
五、check:檢查---enum、set對象
當插入一個新行到表中而且沒有給該列明確賦值時,若是定義了列的默認值,將自動獲得默認值 ;若是沒有,則爲null。
mysql> create table people -> ( -> id int not null primary key, -> name varchar(20) not null, -> sex char(1) default 'm'
-> ); mysql> insert into people(id,name) values(1,'張三'); mysql> insert into people values(2,'李四','f'); mysql> select * from people; +----+--------+------+
| id | name | sex |
+----+--------+------+
| 1 | 張三 | m |
| 2 | 李四 | f |
+----+--------+------+
固然,也能夠在INSERT和UPDATE語句中使用DEFAULT關鍵字顯式地給列賦默認值:
mysql> insert into people values(3,'王五',default); mysql> update people set sex=default where id=2; mysql> select * from people; +----+--------+------+
| id | name | sex |
+----+--------+------+
| 1 | 張三 | m |
| 2 | 李四 | m |
| 3 | 王五 | m |
+----+--------+------+
函數default(column)能夠獲得一個列的默認值:
mysql> select default(sex) from people; +--------------+
| default(sex) |
+--------------+
| m |
| m |
| m |
+--------------+
2)comment:用來給列添加註釋,最多255個字符,註釋會保存到數據字典中。
建立帶有列註釋的表stu_comment
mysql> create table stu_comment -> ( -> id int not null primary key -> comment '學號', -> name varchar(20) not null
-> comment '姓名'
-> );
從數據字典查詢註釋信息
mysql> select column_name,column_comment -> from information_schema.columns -> where table_name='stu_comment'; +-------------+----------------+
| column_name | column_comment |
+-------------+----------------+
| id | 學號 |
| name | 姓名 |
+-------------+----------------+
存儲引擎:決定了數據如何存儲以及如何訪問,還有事務如何處理
MySQL容許對每一個表使用不一樣的存儲引擎,若是在create table語句中沒有指定存儲引擎,則使用默認的存儲引擎。
mysql> show engines; #查詢全部支持的存儲引擎
mysql> CREATE TABLE sexes(sex char(1) NOT NULL) ENGINE = INNODB;
注意:存儲引擎是個重點,後面咱們詳細講解。
2)auto_increment:決定當向表中插入第一行時,自增列獲得的第一個值是多少
3)comment:給表添加註釋
mysql> create table mycomm(num int) comment '測試表'; mysql> select table_name,table_comment -> from information_schema.tables -> where table_name='mycomm'; +------------+---------------+
| table_name | table_comment |
+------------+---------------+
| mycomm | 測試表 |
+------------+---------------+
做用:能夠爲列定義約束(constraint)
約束主要是防止非法數據進入到表中,確保數據的正確性和一致性(統稱數據完整性);
約束也能夠防止一個表被刪除 。
注意:
1)MySQL中約束保存在information_schema.table_constraints中,能夠經過該表查詢約束信息;
2)進行約束定義的時間:使用create table語句、使用alter table語句。
經常使用的約束的類型:5種
①not null:非空約束,指定某列不爲空
②unique:惟一約束,指定某列和幾列組合的數據不能重複
③primary key:主鍵約束,指定某列的數據不能重複、惟一
④foreign key:外鍵,指定該列記錄屬於主表中的一條記錄,參照另外一條數據
⑤check:檢查,指定一個表達式,用於檢驗指定數據
約束定義的語法:
列級別: CREATE TABLE table_name(column_name data_type [ [NOT NULL] | [UNIQUE [KEY] | PRIMARY KEY]
|CHECK(expr)],…) 表級別: CREATE TABLE table_name( column_name data_type [NOT NULL], column_name data_type [not null],…, [CONSTRAINT constraint_name] PRIMARY KEY (col_name,...) |[CONSTRAINT constraint_name] unique (col_name,...) |[CONSTRAINT constraint_name] foreign KEY (col_name) REFERENCES tbl_name (index_col_name) |check(expr)
注意:
1)NOT NULL約束只能在列級別定義,做用在多個列上的約束只能定義在表級別,例如複合主鍵約束;
2)列級別上不能定義外鍵約束,而且不能給約束起名字,由MySQL自動命名(NOT NULL除外);
3)表級別上定義的約束能夠給約束起名字(CHECK約束除外)
做用:用於確保當前列的值不爲空。
mysql> create table temp_nn(id int not null);
約束直接對DML操做帶來影響 mysql> insert into temp_nn values(1); Query OK, 1 row affected (0.00 sec) mysql> insert into temp_nn values(null); ERROR 1048 (23000): Column 'id' cannot be null 具備非空約束的列不容許有null值
注意:非空約束只能出如今表對象的列上。
1.惟一約束是指定table的列或列組合不能重複,保證數據的惟一性,約束的列不容許有重複值;
2.惟一約束不容許出現重複的值,可是能夠爲多個null;
3.同一個表能夠有多個惟一約束,多個列組合的約束
mysql> create table temp_uk( -> id int not null unique, -> name varchar(20) unique); mysql> insert into temp_uk values(1,'a'); mysql> insert into temp_uk values(2,'a'); ERROR 1062 (23000): Duplicate entry 'a' for key 'name' mysql> insert into temp_uk values(2,null); mysql> insert into temp_uk values(3,null); mysql> select * from temp_uk; +----+------+
| id | name |
+----+------+
| 2 | NULL |
| 3 | NULL |
| 1 | a |
+----+------+
可見,惟一性約束的列能夠有多個null值,由於null <> null
4.在建立惟一約束時,若是不給惟一約束名稱,就默認和列名相同;
5.惟一約束不只能夠在一個表內建立,並且能夠同時多表建立組合惟一約束。
mysql> create table test( -> id int not null, -> name varchar(20), -> password varchar(16), ---使用表級約束語法 -> constraint uk_name_pwd unique(name,password) -> ); #表示用戶名和密碼組合不能重複 Query OK, 0 rows affected (0.08 sec) 查詢數據字典,查看惟一鍵約束的信息 mysql> select * from information_schema.table_constraints -> where table_name='test';
primary key = not null + unique
主鍵:用來惟一的標示表中的每一行(類型通常爲整型或者字符串)
具備主鍵約束的列不容許有null值,而且不容許有重複值;
每一個表最多隻容許一個主鍵(可定義聯合主鍵),主鍵名老是PRIMARY。
mysql> create table temp_pk( -> id int primary key); mysql> insert into temp_pk values(1),(2);
mysql> insert into temp_pk values(1); ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' mysql> update temp_pk set id=1 where id=2; ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' mysql> insert into temp_pk values(null); ERROR 1048 (23000): Column 'id' cannot be null
!!給主鍵一個新的名字,但在數據字典中,主鍵名仍是顯示primary
聯合主鍵(用幾個列進行惟一標識一行)
mysql> create table temp_pk( -> id int, -> name varchar(20), -> constraint pk_id_name primary key(id,name) -> ); Query OK, 0 rows affected (0.06 sec) mysql> desc temp_pk; +-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | NO | PRI | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec) mysql> insert into temp_pk values(1,'張三'); Query OK, 1 row affected (0.00 sec) mysql> insert into temp_pk values(2,'李四'); Query OK, 1 row affected (0.01 sec)
mysql> insert into temp_pk values(1,'王五'); Query OK, 1 row affected (0.00 sec) mysql> insert into temp_pk values(1,'張三'); ERROR 1062 (23000): Duplicate entry '1-張三' for key 'PRIMARY'
mysql> select * from temp_pk; +----+--------+
| id | name |
+----+--------+
| 1 | 張三 |
| 1 | 王五 |
| 2 | 李四 |
+----+--------+
3 rows in set (0.00 sec)
外鍵約束:
參照完整性約束,保證一個或兩個表之間的參照完整性,外鍵是構建於一個表的兩個字段或是兩個表的兩個字段之間的參照關係。
注意:
1)具備外鍵約束的列的值不能隨便給,必須知足外鍵所引用的主鍵的取值;
2)一張表中能夠定義多個外鍵;
3)外鍵列默承認以給null值。
按照定義,外鍵必須引用一個主鍵或者惟一鍵,引用的主鍵通常在另一張表中,也能夠是本表的主鍵(後者稱爲「自引用」)。
父子表:
外鍵所在的表叫作子表、從表
外鍵所引用的主鍵所在的表叫作父表、主表
注意:父子表是相對而言的,表a能夠是表b的子表,但同時也能夠是表c的父表
示例:建立外鍵約束
//建立父表 mysql> create table dept( -> deptid int, -> dname varchar(20), -> constraint dept_deptid_pk primary key(deptid) -> ); mysql> insert into dept(deptid,dname) values(10,'市場部'); mysql> insert into dept(deptid,dname) values(20,'銷售部'); //建立子表(表級別建立外鍵約束)
mysql> create table emp( -> id int, -> name varchar(20), -> deptid int, -> constraint emp_id_pk primary key(id), -> constraint emp_deptid_fk foreign key(deptid) -> references dept(deptid) -> );
查詢數據字典,查看外鍵約束的信息:
上面建立子表的時候給外鍵約束命名emp_deptid_fk;
若是不給外鍵約束命名,那麼默認的名字是表名_ibfk_n, n是整數,從1開始;
此時,emp表中deptid列(外鍵約束)受dept主表限制
mysql> insert into emp(id,name,deptid) values(1,'張三',10); Query OK, 1 row affected (0.00 sec) mysql> insert into emp(id,name,deptid) values(2,'李四',10); Query OK, 1 row affected (0.00 sec) mysql> insert into emp(id,name,deptid) values(3,'王五',50); #insert主表deptid列沒有的數據 ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `emp_deptid_fk` FOREIGN KEY (`deptid`) REFERENCES `dept` (`deptid`)) mysql> update emp set deptid=30 where id=1; #update主表deptid列沒有的數據 ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `emp_deptid_fk` FOREIGN KEY (`deptid`) REFERENCES `dept` (`deptid`)) 外鍵的update更新操做規則以下刪除規則…… mysql> delete from dept where deptid=10; #delete父表中的行(子表中有引用的數據行) ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `emp_deptid_fk` FOREIGN KEY (`deptid`) REFERENCES `dept` (`deptid`)) 外鍵的默認刪除規則: 當刪除父表中的行時,若是子表中有依賴於被刪除父行的子行存在,那麼就不容許刪除,並拋出異常(默認對外鍵使用on delete restrict 或on delete no action選項)
外鍵引用定義:
reference_definition: REFERENCES tbl_name (index_col_name,...) [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE] [ON DELETE reference_option] [ON UPDATE reference_option] reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION
在定義外鍵約束時,經過使用on delete cascade或者on delete set null選項,能夠改變外鍵的默認刪除規則:
①ON DELETE CASCADE:級聯刪除。當刪除父表中的行時,若是子表中有依賴於被刪除父行的子行存在,那麼連同子行一塊兒刪除(很危險!!!)
②ON DELETE SET NULL:當刪除父表中的行時,若是子表中有依賴於被刪除父行的子行存在,那麼不刪除,而是將子行的外鍵列設置爲null
……
mysql> create table emp( -> id int, -> name varchar(20), -> deptid int, -> constraint emp_id_pk primary key(id), -> constraint emp_deptid_fk foreign key(deptid) -> references dept(deptid) -> on delete cascade -> ); ……
MySQL可使用check約束,但check約束對數據驗證沒有任何做用。
Oracle中可使用check約束,是有相應的做用的。
mysql> create table test_ck( -> id int check(id>0) -> ); mysql> insert into test_ck values(-100); mysql> select * from test_ck; +------+
| id |
+------+
| -100 |
+------+
The CHECK clause is parsed but ignored by all storage engines。
定義數據庫列時,可使用ENUM(enumeration,枚舉)和SET(集合)類型:變通的實現CHECK約束
二者的區別是:
使用ENUM,只能選一個值;
使用SET,能夠選多個值;
ENUM和SET中的值都必須是字符串類型。
一、enum枚舉類型
注意:
在內部存儲ENUM值時,MYSQL給ENUM中的每一個值一個順序號碼:第一個值的順序號碼是1,第二個值的順序號碼是2,以此類推。當排序或比較ENUM的時候,使用這些順序號碼進行。
mysql> select * from student order by sex; +----+--------+------+
| id | name | sex |
+----+--------+------+
| 5 | 王五 | NULL |
| 1 | 張三 | M |
| 2 | 李四 | F |
+----+--------+------+
二、set類型:由於能夠列舉多個值,因此在建表列約束中常被使用到。
mysql> create table team( -> teamno int not null, -> division set('north','south','east','west') -> ); mysql> insert into team values(1,'west'); mysql> insert into team values(2,'west,south'); mysql> insert into team values(4,null); mysql> insert into team values(3,'east,asia'); ERROR 1265 (01000): Data truncated for column 'division' at row 1 mysql> select * from team; +--------+------------+
| teamno | division |
+--------+------------+
| 1 | west |
| 2 | south,west |
| 4 | NULL |
+--------+------------+