MySQL表約束的實(shí)現(xiàn)
前言
hello,各位小伙伴大家好,本章內(nèi)容為大家介紹關(guān)于MySQL約束的相關(guān)內(nèi)容,關(guān)于約束這個(gè)概念,如果是第一次接觸可能會(huì)有一點(diǎn)難以理解,不過也不用擔(dān)心,相信看完這篇文章對(duì)約束這個(gè)概念會(huì)有一個(gè)清晰的認(rèn)識(shí)。
1.什么是約束
在談MySQL表的約束之前,先舉一個(gè)生活中的例子,我們?cè)趯W(xué)校中讀書,會(huì)受到學(xué)校中各種各樣規(guī)矩的約束,本質(zhì)上在學(xué)校制定許多的規(guī)矩是為了更好的管理學(xué)生,而在MySQL中也有許多的規(guī)矩,這些規(guī)矩是為了規(guī)范程序員在向數(shù)據(jù)庫(kù)插入數(shù)據(jù)的時(shí)候正確操作,體現(xiàn)為對(duì)程序員的一種約束,下面我們就具體來看看,建表的時(shí)候都有哪些約束。
2.空屬性
兩個(gè)值:null(默認(rèn)的) 和 not null(不為空)
數(shù)據(jù)庫(kù)默認(rèn)字段基本都是為空,但是在實(shí)際開發(fā)中,盡可能保證字段不為空,因?yàn)閿?shù)據(jù)為空,沒辦法參與運(yùn)算
mysql> select null; +------+ | NULL | +------+ | NULL | +------+ 1 row in set (0.00 sec) mysql> select 1+null; +--------+ | 1+null | +--------+ | NULL | +--------+ 1 row in set (0.00 sec)
案例:
創(chuàng)建一個(gè)班級(jí)表,包含班級(jí)名和班級(jí)所在的教室。
站在正常的業(yè)務(wù)邏輯中:
- 如果班級(jí)沒有名字,你不知道你在哪個(gè)班級(jí)
- 如果教室名字可以為空,就不知道在哪上課
所以我們?cè)谠O(shè)計(jì)數(shù)據(jù)庫(kù)表的時(shí)候,一定要在表中進(jìn)行限制,班級(jí)名和教室名都不能為空,這就是“約束”。
//創(chuàng)建表 mysql> create table myclass( class_name varchar(20) not null, class_room varchar(20) not null); Query OK, 0 rows affected (0.03 sec) //表結(jié)構(gòu) mysql> desc myclass; +------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ | class_name | varchar(20) | NO | | NULL | | | class_room | varchar(20) | NO | | NULL | | +------------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) //正常插入數(shù)據(jù) mysql> insert into myclass values('通信211','4406'); Query OK, 1 row affected (0.00 sec) //給非空屬性字段不插入值報(bào)錯(cuò) mysql> insert into myclass (class_name) values('通信211'); ERROR 1364 (HY000): Field 'class_room' doesn't have a default value
總結(jié):在創(chuàng)建屬性字段的時(shí)候,默認(rèn)情況是null,可以為空,指定為not null,在插入數(shù)據(jù)的時(shí)候不能為空,必須有值,而必須有值,則體現(xiàn)為MySQL建表的一種約束
3.默認(rèn)值
默認(rèn)值:某一種數(shù)據(jù)會(huì)經(jīng)常性的出現(xiàn)某個(gè)具體的值,可以一開始就指定好,在需要真實(shí)數(shù)據(jù)的時(shí)候,用戶可以選擇性的使用默認(rèn)值。
//創(chuàng)建表 mysql> create table if not exists stu( -> name varchar(12) not null, -> age tinyint unsigned default 18, -> sex char(2) default '男' -> ); Query OK, 0 rows affected (0.03 sec) //表結(jié)構(gòu) mysql> desc stu; +-------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+-------+ | name | varchar(12) | NO | | NULL | | | age | tinyint(3) unsigned | YES | | 18 | | | sex | char(2) | YES | | 男 | | +-------+---------------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) //全插入 mysql> insert into stu (name,age,sex) values ('張三','20','男'); Query OK, 1 row affected (0.00 sec) //按照默認(rèn)值進(jìn)行插入 mysql> insert into stu (name) values ('李四'); Query OK, 1 row affected (0.01 sec) //插入后的數(shù)據(jù) mysql> select* from stu; +--------+------+------+ | name | age | sex | +--------+------+------+ | 張三 | 20 | 男 | | 李四 | 18 | 男 | +--------+------+------+ 2 rows in set (0.00 sec)
設(shè)置了default的列,在插入數(shù)據(jù)的時(shí)候,可以對(duì)列進(jìn)行省略。
4.列描述
列描述:comment,沒有實(shí)際含義,專門用來描述字段,體現(xiàn)為一種軟性約束
//創(chuàng)建表,通過comment對(duì)每個(gè)字段進(jìn)行描述 mysql> create table if not exists t7( -> name varchar(20) not null comment "姓名", -> age int default 18 comment '年齡' -> ); Query OK, 0 rows affected (0.03 sec) //查看表結(jié)構(gòu) mysql> show create table t7\G; *************************** 1. row *************************** Table: t7 Create Table: CREATE TABLE `t7` ( `name` varchar(20) NOT NULL COMMENT '姓名', `age` int(11) DEFAULT '18' COMMENT '年齡' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
5.zerofill
zerofill對(duì)數(shù)據(jù)進(jìn)行格式化顯示,如果寬度小于設(shè)定的寬度,自動(dòng)填充0
mysql> create table if not exists t8( -> id int zerofill, -> name varchar(20) not null -> ); Query OK, 0 rows affected (0.04 sec) //插入數(shù)據(jù) mysql> insert into t8 values (1,'張三'); Query OK, 1 row affected (0.00 sec) mysql> insert into t8 values (2,'李四'); Query OK, 1 row affected (0.01 sec) //插入數(shù)據(jù)的時(shí)候?qū)挾刃∮谠O(shè)定的寬度用0填充。 mysql> select* from t8; +------------+--------+ | id | name | +------------+--------+ | 0000000001 | 張三 | | 0000000002 | 李四 | +------------+--------+ 2 rows in set (0.00 sec) //int類型數(shù)據(jù)寬度為10位 mysql> show create table t8\G; *************************** 1. row *************************** Table: t8 Create Table: CREATE TABLE `t8` ( `id` int(10) unsigned zerofill DEFAULT NULL, `name` varchar(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
注:自動(dòng)填充0,這是最后顯示的結(jié)果,在MySQL中實(shí)際存儲(chǔ)的還是1和2。
作用:在一些對(duì)數(shù)據(jù)格式有要求的地方使用,使得數(shù)據(jù)更加規(guī)范。
6.主鍵
主鍵:primary key用來唯一約束該字段里面的數(shù)據(jù),不能重復(fù),不能為空,一張表最多只能有一個(gè)主鍵,主鍵所在的列通常是整數(shù)類型
案例:
給學(xué)生的id添加主鍵,用id唯一標(biāo)識(shí)一個(gè)學(xué)生
//創(chuàng)建表,指定id為主鍵 mysql> create table if not exists student( -> id int primary key comment '學(xué)號(hào)', -> name varchar(20) not null, -> age tinyint default 18 -> ); Query OK, 0 rows affected (0.04 sec) //插入數(shù)據(jù) mysql> insert into student values(1,'張三',20); Query OK, 1 row affected (0.01 sec) mysql> insert into student values(2,'張三',20); Query OK, 1 row affected (0.00 sec) //當(dāng)id值出現(xiàn)重復(fù)或者為空時(shí)不能向表中插入數(shù)據(jù) mysql> insert into student values(2,'張三',20); ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY' mysql> insert into student values(1,'張三',20); ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' mysql> insert into student (name,age)values('張三',20); ERROR 1364 (HY000): Field 'id' doesn't have a default value
當(dāng)表創(chuàng)建好以后但是沒有主鍵的時(shí)候,可以再次追加主鍵
alter table 表名 add primary key(字段列表);
刪除主鍵
alter table 表名 drop primary key;
復(fù)合主鍵
在創(chuàng)建表的時(shí)候,有多個(gè)屬性字段作為主鍵,這里的多個(gè)屬性字段作為主鍵不是說一張表中有多個(gè)主鍵,而是多個(gè)主鍵共同約束作為一個(gè)主鍵
案例:
創(chuàng)建一張表,該表中有多個(gè)屬性字段作為主鍵
mysql> create table if not exists t9( -> id int unsigned, -> course char(10) comment '課程代碼', -> score tinyint default 60 comment '成績(jī)', -> primary key(id,score) --id和score共同作為復(fù)合主鍵 -> ); Query OK, 0 rows affected (0.03 sec) mysql> desc t9; +--------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+------------------+------+-----+---------+-------+ | id | int(10) unsigned | NO | PRI | NULL | | | course | char(10) | YES | | NULL | | | score | tinyint(4) | NO | PRI | 60 | | +--------+------------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> insert into t9 values(1,'數(shù)學(xué)',65); Query OK, 1 row affected (0.00 sec) mysql> insert into t9 values(2,'數(shù)學(xué)',65); Query OK, 1 row affected (0.00 sec) mysql> insert into t9 values(2,'數(shù)學(xué)',65); ERROR 1062 (23000): Duplicate entry '2-65' for key 'PRIMARY' --主鍵沖突
7.自增長(zhǎng)
auto_increment:當(dāng)對(duì)應(yīng)的字段不給值,會(huì)自動(dòng)的被系統(tǒng)觸發(fā),系統(tǒng)從當(dāng)前字段中已經(jīng)有的最大值+1操作,得到一個(gè)新的不同的值。通常和主鍵搭配使用,作為邏輯主鍵
自增長(zhǎng)的特點(diǎn):
任何一個(gè)字段要做自增長(zhǎng),前提本身是一個(gè)索引;
自增長(zhǎng)字段必須是整數(shù);
一張表最多只能有一個(gè)自增長(zhǎng)
案例:
mysql> system clear; mysql> create table if not exists t10( -> id int unsigned primary key auto_increment, -> name varchar(20) not null -> ); Query OK, 0 rows affected (0.03 sec) mysql> insert into t10 (name) values('張三'); Query OK, 1 row affected (0.01 sec) mysql> insert into t10 (name) values('李四'); Query OK, 1 row affected (0.01 sec) //默認(rèn)從1開始自增長(zhǎng) mysql> select* from t10; +----+--------+ | id | name | +----+--------+ | 1 | 張三 | | 2 | 李四 | +----+--------+ 2 rows in set (0.00 sec)
自增長(zhǎng)實(shí)現(xiàn)的原理:
獲取上次插入的auto_increment的值
mysql> select last_insert_id(); +------------------+ | last_insert_id() | +------------------+ | 2 | +------------------+ 1 row in set (0.00 sec)
8.唯一鍵
一張表中往往有很多字段需要唯一性,數(shù)據(jù)不能重復(fù),但是一張表中只能有一個(gè)主鍵,而唯一鍵的存在可以解決表中有很多字段需要唯一性約束的問題。
唯一鍵和主鍵不同在于,唯一鍵允許為空,而主鍵不允許為空。另外主鍵更多的是標(biāo)識(shí)唯一性的,而唯一鍵更多是保證在業(yè)務(wù)上,不要和別的信息產(chǎn)生沖突。
mysql> create table if not exists t11( -> id tinyint primary key, -> name varchar(20) not null, -> class_name varchar(20) unique comment '班級(jí)名,不能為空' -> ); Query OK, 0 rows affected (0.03 sec) //唯一鍵約束不能重復(fù) mysql> insert into t11 values (1,'zhangsan','A'); Query OK, 1 row affected (0.00 sec) mysql> insert into t11 values (2,'zhangsan','A'); ERROR 1062 (23000): Duplicate entry 'A' for key 'class_name' //可以為空 mysql> insert into t11 (id,name) values (2,'zhangsan'); Query OK, 1 row affected (0.00 sec) mysql> select* from t11; +----+----------+------------+ | id | name | class_name | +----+----------+------------+ | 1 | zhangsan | A | | 2 | zhangsan | NULL | +----+----------+------------+ 2 rows in set (0.00 sec)
9.外鍵
MySQL是關(guān)系型數(shù)據(jù)庫(kù),一般表跟表之間是有關(guān)聯(lián)關(guān)系的,舉個(gè)簡(jiǎn)單的例子,有兩張表,一張表是班級(jí)表,另一張是學(xué)生表,因?yàn)閷W(xué)生是屬于班級(jí)的,所以一般將班級(jí)表稱為是主表,而學(xué)生表稱為是從表。
外鍵就是用于定義主表和從表之間的關(guān)系:外鍵約束主要定義在從表上,主表則必須是主鍵約束或者是唯一鍵約束。當(dāng)定義外鍵之后,要求外鍵列數(shù)據(jù)必須在主表的主鍵列存在或?yàn)閚ull。
語法:
foreign key 字段名 references 主表(列)
案例:
a.創(chuàng)建主表:
mysql> create table if not exists myclass( -> id int primary key, -> name varchar(20) not null comment '班級(jí)名' -> ); Query OK, 0 rows affected (0.03 sec)
b.創(chuàng)建從表:
mysql> create table if not exists stu( -> id int primary key, -> name varchar(20) not null comment '學(xué)生名', -> class_id int, -> foreign key (class_id) references myclass(id) -> ); Query OK, 0 rows affected (0.06 sec)
c.正常插入數(shù)據(jù):
mysql> insert into myclass values (10,'C++大牛班'),(20,'java大神班'); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into stu values (100,'張三',10); Query OK, 1 row affected (0.01 sec) mysql> insert into stu values (200,'李四',20); Query OK, 1 row affected (0.01 sec) mysql> insert into stu values (300,'王五',null); Query OK, 1 row affected (0.01 sec)
d.插入一個(gè)班級(jí)號(hào)為30的同學(xué),因?yàn)闆]有這個(gè)班級(jí),所以插入不成功
mysql> insert into stu values (400,'趙六',30);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass` (`id`))
e.數(shù)據(jù)顯示
mysql> select* from stu; +-----+--------+----------+ | id | name | class_id | +-----+--------+----------+ | 100 | 張三 | 10 | | 200 | 李四 | 20 | | 300 | 王五 | NULL | +-----+--------+----------+ 3 rows in set (0.00 sec) mysql> select* from myclass; +----+---------------+ | id | name | +----+---------------+ | 10 | C++大牛班 | | 20 | java大神班 | +----+---------------+ 2 rows in set (0.00 sec)
總結(jié)
本篇文章為大家介紹了MySQL中約束相關(guān)的話題,總結(jié)為一句話,約束是在建表的時(shí)候進(jìn)行的,目的是為了防止在后續(xù)數(shù)據(jù)插入的時(shí)候出現(xiàn)不合法的數(shù)據(jù),實(shí)現(xiàn)這個(gè)目的方法就是上面介紹的這些規(guī)則,相信掌握了這些規(guī)則之后,對(duì)數(shù)據(jù)庫(kù)的操作又有了一個(gè)不小的提升。
到此這篇關(guān)于MySQL表約束的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MySQL表約束內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL生產(chǎn)環(huán)境CPU使用率過高的排查與解決方案
在生產(chǎn)環(huán)境中,MySQL作為一個(gè)關(guān)鍵的數(shù)據(jù)庫(kù)組件,其性能對(duì)整個(gè)系統(tǒng)的穩(wěn)定性至關(guān)重要,有時(shí)候我們可能會(huì)遇到MySQL CPU使用率過高的問題,本文將詳細(xì)介紹如何排查和解決MySQL CPU過高的問題,幫助您迅速恢復(fù)正常的數(shù)據(jù)庫(kù)性能,需要的朋友可以參考下2024-03-03windows系統(tǒng)mysql5.7.18安裝圖文教程
這篇文章主要為大家詳細(xì)介紹了windows系統(tǒng)下mysql5.7.18安裝圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03MySQL的時(shí)間差函數(shù)(TIMESTAMPDIFF、DATEDIFF)、日期轉(zhuǎn)換計(jì)算函數(shù)(date_add、day、da
這篇文章主要介紹了MySQL的時(shí)間差函數(shù)(TIMESTAMPDIFF、DATEDIFF)、日期轉(zhuǎn)換計(jì)算函數(shù)(date_add、day、date_format、str_to_date),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12MySQL數(shù)據(jù)庫(kù)表修復(fù) MyISAM
這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)表修復(fù) MyISAM ,需要的朋友可以參考下2014-06-06mysql優(yōu)化取隨機(jī)數(shù)據(jù)慢的方法
mysql取隨機(jī)數(shù)據(jù)慢,怎么辦?下面小編與大家一起來看看mysql取隨機(jī)數(shù)據(jù)慢優(yōu)化的過程。2013-11-11