一,mysql中表的約束
為了防止不符合規范的數據進入數據庫,在用戶對數據進行插入、修改、刪除等操作時,DBMS自動按照一定的約束條件對數據進行監測,使不符合規范的數據不能進入數據庫,以確保數據庫中存儲的數據正確、有效、相容。
約束條件與數據類型的寬度一樣,都是可選參數,主要分為以下幾種:
-
NOT NULL :非空約束,指定某列不能為空;
-
是否可空,null表示空,非字符串
-
not null - 不可空
-
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 | | +-------+---------+------+-----+---------+-------+ 1 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)
-
-
DEFAULT: 我們約束某一列不為空,如果這一列中經常有重復的內容,就需要我們頻繁的插入,這樣會給我們的操作帶來新的負擔,於是就出現了默認值的概念。默認值,創建列時可以指定默認值,當插入數據時如果未主動設置,則自動添加默認值
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 | | +-------+---------+------+-----+---------+-------+ 2 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 | +-----+-----+ 1 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 | +-----+-----+ 2 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" -
UNIQUE : 唯一約束,指定某列或者幾列組合不能重復
-
unique示例
方法一: 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' -
not null 和 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 | | +-------+---------+------+-----+---------+-------+ 1 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'
-
-
PRIMARY KEY :
-
主鍵,指定該列的值可以唯一地標識該列記錄
-
主鍵可以包含一個字段或多個字段。當主鍵包含多個欄位時,稱為組合鍵 (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 | | +---------+--------------+------+-----+---------+-------+ 3 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 | | +---------+--------------+------+-----+---------+-------+ 3 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 | | +--------------+-------------+------+-----+---------+-------+ 3 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'
-
-
-
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 | | +----------+-------------+------+-----+---------+-------+ 2 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 | | +----------+-------------+------+-----+---------+-------+ 2 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 | | +----------+-------------+------+-----+---------+-------+ 2 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,'yuan',1), (2,'nezha',2), (3,'egon',2), (4,'alex',2), (5,'wusir',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 | yuan | 1 | | 5 | wusir | 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 | yuan | 1 | | 5 | wusir | 2 | | 6 | 李沁洋 | 2 | | 7 | 皮卡丘 | 2 | | 8 | 程咬金 | 2 | | 9 | 程咬銀 | 2 | +----+-----------+--------+ rows in set (0.00 sec) 外鍵操作示例
-
AUTO_INCREMENT : 約束字段為自動增長,被約束的字段必須同時被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)
二,表結構的查詢
-
單表查詢
-
單表查詢語法
SELECT DISTINCT 字段1,字段2... FROM 表名 WHERE 條件 GROUP BY field HAVING 篩選 ORDER BY field LIMIT 限制條數 -
關鍵字執行的優先級
關鍵字 作用 from 找到表 where 拿着where指定的約束條件,去文件/表中取出一條條記錄 group by 將取出的一條條記錄進行分組group by,如果沒有group by,則整體作為一組 select distinct 執行select(去重) having 將分組的結果進行having過濾 order by 將結果按條件排序:order by limit 限制結果的顯示條數 -
簡單查詢
SELECT id,emp_name,sex,age,hire_date,post,post_comment,salary,office,depart_id FROM employee; SELECT * FROM employee; SELECT emp_name,salary FROM employee; #避免重復DISTINCT SELECT DISTINCT post FROM employee; #通過四則運算查詢 SELECT emp_name, salary*12 FROM employee; SELECT emp_name, salary*12 AS Annual_salary FROM employee; SELECT emp_name, salary*12 Annual_salary FROM employee; #定義顯示格式 CONCAT() 函數用於連接字符串 SELECT CONCAT('姓名: ',emp_name,' 年薪: ', salary*12) AS Annual_salary FROM employee; CONCAT_WS() 第一個參數為分隔符 SELECT CONCAT_WS(':',emp_name,salary*12) AS Annual_salary FROM employee; 結合CASE語句: SELECT ( CASE WHEN emp_name = 'jingliyang' THEN emp_name WHEN emp_name = 'alex' THEN CONCAT(emp_name,'_BIGSB') ELSE concat(emp_name, 'SB') END ) as new_name FROM employee; -
where約束
select 字段名 from 表名 where 條件
類型 用法 比較運算符 > < >= <= <> != between 80 and 100 值在80到100之間(包含80,100) in(80,90,100) 值是80或90或100 like 'e%' 通配符可以是%或_,%表示任意多字符, _表示一個字符 regexp 正則匹配 is / is not is null / is not null 邏輯運算符 and or not #1:單條件查詢 SELECT emp_name FROM employee WHERE post='sale'; #2:多條件查詢 SELECT emp_name,salary FROM employee WHERE post='teacher' AND salary>10000; #3:關鍵字BETWEEN AND SELECT emp_name,salary FROM employee WHERE salary BETWEEN 10000 AND 20000; SELECT emp_name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000; #4:關鍵字IS NULL(判斷某個字段是否為NULL不能用等號,需要用IS) SELECT emp_name,post_comment FROM employee WHERE post_comment IS NULL; SELECT emp_name,post_comment FROM employee WHERE post_comment IS NOT NULL; SELECT emp_name,post_comment FROM employee WHERE post_comment=''; 注意''是空字符串,不是null ps: 執行 update employee set post_comment='' where id=2; 再用上條查看,就會有結果了 #5:關鍵字IN集合查詢 SELECT emp_name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ; SELECT emp_name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ; SELECT emp_name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ; #6:關鍵字LIKE模糊查詢 通配符’%’ SELECT * FROM employee WHERE emp_name LIKE 'eg%'; 通配符’_’ SELECT * FROM employee WHERE emp_name LIKE 'al__';
三,表結構
- 刪除表
drop table 表名;
- 多表結構的創建和分析
分析步驟:
# 1,先站在左表的角度去找
是否左表的多條記錄可以對應右表的一條記錄,如果是,則證明左表的一個字段foreign key 右表一個字段(通常是id)
# 2,再站在右表的角度去找
是否右表的多條記錄可以對應左表的一條記錄,如果是,則證明右表的一個字段foreign key 左表一個字段(通常是id)
# 3,總結:
# 多對一:
如果只有步驟1成立,則是左表多對一右表
如果只有步驟2成立,則是右表多對一左表
# 多對多
如果步驟1和2同時成立,則證明這兩張表時一個雙向的多對一,即多對多,需要定義一個這兩張表的關系表來專門存放二者的關系
# 一對一:
如果1和2都不成立,而是左表的一條記錄唯一對應右表的一條記錄,反之亦然.這種情況很簡單,就是在左表foreign key右表的基礎上,將左表的外鍵字段設置成unique即可
# 一對多或多對一 示例
mysql> create table press(
-> id int primary key auto_increment,
-> name varchar(20)
-> );
mysql> create table book(
-> id int primary key auto_increment,
-> name varchar(20),
-> press_id int not null,
-> foreign key(press_id) references press(id)
-> on delete cascade
-> on update cascade
-> );
mysql> insert into press(name) values
-> ('北京工業地雷出版社'),
-> ('人民音樂不好聽出版社'),
-> ('知識產權沒有用出版社');
mysql> insert into book(name,press_id) values
-> ('九陽神功',1),
-> ('九陰真經',2),
-> ('九陰白骨爪',2),
-> ('獨孤九劍',3),
-> ('降龍十巴掌',2),
-> ('葵花寶典',3);
mysql> select * from book;
+----+-----------------+----------+
| id | name | press_id |
+----+-----------------+----------+
| 1 | 九陽神功 | 1 |
| 2 | 九陰真經 | 2 |
| 3 | 九陰白骨爪 | 2 |
| 4 | 獨孤九劍 | 3 |
| 5 | 降龍十巴掌 | 2 |
| 6 | 葵花寶典 | 3 |
+----+-----------------+----------+
# 多對多
# 三張表:作者,書,對應關系
# 多對多:一個作者可以寫多本書,一本書也可以有多個作者,雙向的一對多,即多對多
# 關聯方式:foreign key+一張新的表
# 作者表
mysql> create table author(
-> id int primary key auto_increment,
-> name varchar(20)
-> );
# 這張表就存放作者表與書表的關系,即查詢二者的關系查這表就可以了
mysql> create table author_book(
-> id int primary key auto_increment,
-> author_id int not null,
-> book_id int not null,
-> constraint fk_author foreign key(author_id) references author(id)
-> on delete cascade on update cascade,
-> constraint fk_book foreign key(book_id) references book(id)
-> on delete cascade on update cascade,
-> unique(author_id,book_id)
-> );
mysql> insert into author(name) values
-> ('孫悟空'),('豬八戒'),('唐僧'),('沙和尚');
mysql> insert into author_book(author_id,book_id) values
-> (1,4),(1,2),(1,3),(2,1),(2,6),(3,5),(4,2),(4,6);
mysql> select * from book;
+----+-----------------+----------+
| id | name | press_id |
+----+-----------------+----------+
| 1 | 九陽神功 | 1 |
| 2 | 九陰真經 | 2 |
| 3 | 九陰白骨爪 | 2 |
| 4 | 獨孤九劍 | 3 |
| 5 | 降龍十巴掌 | 2 |
| 6 | 葵花寶典 | 3 |
+----+-----------------+----------+
mysql> select * from author;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 孫悟空 |
| 2 | 豬八戒 |
| 3 | 唐僧 |
| 4 | 沙和尚 |
+----+-----------+
mysql> select * from author_book;
+----+-----------+---------+
| id | author_id | book_id |
+----+-----------+---------+
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 1 | 1 | 4 |
| 4 | 2 | 1 |
| 5 | 2 | 6 |
| 6 | 3 | 5 |
| 7 | 4 | 2 |
| 8 | 4 | 6 |
+----+-----------+---------+
# 一對一
# 兩張表:用戶表和博客表
# 一對一:一個用戶只有一個博客
# 關聯方式:foreign key+unique
# 用戶表
mysql> create table user(
-> id int primary key auto_increment,
-> name varchar(12));
mysql> insert into user(name) values
-> ('孫悟空'),('豬八戒'),('沙悟凈');
# 博客表
mysql> create table blog(
-> id int primary key auto_increment,
-> url varchar(40) not null unique,
-> name_id int unique,
-> foreign key(name_id) references user(id)
-> on delete cascade on update cascade);
mysql> insert into blog(url,name_id) values
-> ('www.baidu.com',1),('www.sohu.com',3),('www.taobao.com',2);
mysql> select * from user;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 孫悟空 |
| 2 | 豬八戒 |
| 3 | 沙悟凈 |
+----+-----------+
mysql> select * from blog;
+----+----------------+---------+
| id | url | name_id |
+----+----------------+---------+
| 1 | www.baidu.com | 1 |
| 2 | www.sohu.com | 3 |
| 3 | www.taobao.com | 2 |
+----+----------------+---------+
