sql語句規范
sql是Structured Query Language(結構化查詢語言)的縮寫。SQL是專為數據庫而建立的操作命令集,是一種功能齊全的數據庫語言。
在使用它時,只需要發出“做什么”的命令,“怎么做”是不用使用者考慮的。SQL功能強大、簡單易學、使用方便,已經成為了數據庫操作的基礎,並且現在幾乎所有的數據庫均支持sql。
<1> 在數據庫系統中,SQL語句不區分大小寫(建議用大寫) 。但字符串常量區分大小寫。建議命令大寫,表名庫名小寫;
<2> SQL語句可單行或多行書寫,以“;”結尾。關鍵詞不能跨多行或簡寫。
<3> 用空格和縮進來提高語句的可讀性。子句通常位於獨立行,便於編輯,提高可讀性。
1
2
|
SELECT
*
FROM
tb_table
WHERE
NAME
=
"YUAN"
;
|
<4> 注釋:單行注釋:--
多行注釋:/*......*/
<5>sql語句可以折行操作
數據類型
數值類型
作用:存儲年齡,等級,id,手機號,身高,薪水等數字
無符號類型

=========有符號和無符號tinyint========== #tinyint默認為有符號 MariaDB [db1]> create table t1(x tinyint); #默認為有符號,即數字前有正負號 MariaDB [db1]> desc t1; MariaDB [db1]> insert into t1 values -> (-129), -> (-128), -> (127), -> (128); MariaDB [db1]> select * from t1; +------+ | x | +------+ | -128 | #-129存成了-128 | -128 | #有符號,最小值為-128 | 127 | #有符號,最大值127 | 127 | #128存成了127 +------+ #設置無符號tinyint MariaDB [db1]> create table t2(x tinyint unsigned); MariaDB [db1]> insert into t2 values -> (-1), -> (0), -> (255), -> (256); MariaDB [db1]> select * from t2; +------+ | x | +------+ | 0 | -1存成了0 | 0 | #無符號,最小值為0 | 255 | #無符號,最大值為255 | 255 | #256存成了255 +------+
顯示長度和存儲字節
mysql> create table test(id int); Query OK, 0 rows affected (0.01 sec) mysql> desc test; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 1 row in set (0.00 sec)
int(11)是默認的顯示寬度,因為int是用4個字節存儲,所以能存儲的最大數就是4294967295,是一個十位數字,對於無符號類型,所以默認顯示寬度就是11;
同理:tinyint的默認顯示寬度是4位。
decimal類型
float:浮點型,含字節數為4,32bit, 數值范圍為-3.4E38~3.4E38(7個有效位) double:雙精度實型,含字節數為8,64bit 數值范圍-1.7E308~1.7E308(15個有效位) decimal:數字型,128 數值范圍 ±1.0 × E28 to ±7.9 × E28(28個有效位)
decimal的精度比double大,所能儲存的最大數卻比double要小 。decimal是存在精度損失的,只不過較小而已!
BIT
BIT(M)可以用來存放多位二進制數,M范圍從1~64,如果不寫默認為1位。
注意:對於位字段需要使用函數讀取
bin()顯示為二進制
hex()顯示為十六進制
mysql> create table t(id bit); Query OK, 0 rows affected (0.03 sec) mysql> desc t; +-------+--------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------+------+-----+---------+-------+ | id | bit(1) | YES | | NULL | | +-------+--------+------+-----+---------+-------+ 1 row in set (0.00 sec) mysql> insert t values (1); Query OK, 1 row affected (0.00 sec) mysql> select * from t; +------+ | id | +------+ | | +------+ 1 row in set (0.00 sec)
mysql> select bin(id) from t;
+---------+
| bin(id) |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec)
mysql> alter table t modify id bit(5); Query OK, 1 row affected (0.02 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> insert into t values(8); Query OK, 1 row affected (0.00 sec) mysql> select bin(id),hex(id) from t; +---------+---------+ | bin(id) | hex(id) | +---------+---------+ | 1 | 1 | | 1000 | 8 | +---------+---------+ 2 rows in set (0.00 sec)
字符串類型
存儲字符串:
CHAR系列 :CHAR VARCHAR
TEXT系列 : TINYTEXT TEXT MEDIUMTEXT LONGTEXT
存儲二進制數據:
BINARY系列: BINARY VARBINARY
BLOB 系列 : TINYBLOB BLOB MEDIUMBLOB LONGBLOB
解析:

char (m) CHAR列的長度固定為創建表時聲明的長度: 0 ~ 255。其中m代表字符串的長度。 PS: 即使數據小於m長度,也會占用m長度 varchar(m) VARCHAR列中的值為可變長字符串,長度: 0 ~ 65535。其中m代表該數據類型所允許保存的字符串 的最大長度,只要長度小於該最大值的字符串都可以被保存在該數據類型中。 注:雖然varchar使用起來較為靈活,但是從整個系統的性能角度來說,char數據類型的處理速度 更快,有時甚至可以超出varchar處理速度的50%。因此,用戶在設計數據庫時應當綜合考慮各方面的因素,以求達到最佳的平衡 text text數據類型用於保存變長的大字符串,可以組多到65535 (2**16 − 1)個字符。 mediumtext A TEXT column with a maximum length of 16,777,215 (2**24 − 1) characters. longtext A TEXT column with a maximum length of 4,294,967,295 or 4GB (2**32 − 1) characters.
注意:
在查詢的時候,CHAR列刪除了尾部的空格,而VARCHAR則保留這些空格。 mysql> create table t1(x char(5),y varchar(5)); mysql> insert into t1 values('你瞅啥 ','瞅你妹 '); mysql> select x,length(x),y,length(y) from t1; +--------+-----------+----------+-----------+ | x | length(x) | y | length(y) | +--------+-----------+----------+-----------+ | 你瞅啥 | 9 | 瞅你妹 | 11 | +--------+-----------+----------+-----------+
日期類型
表示時間值的日期和時間類型為DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每個時間類型有一個有效值范圍和一個"零"值,當指定不合法的MySQL不能表示的值時使用"零"值。
作用:存儲用戶注冊時間,文章發布時間,員工入職時間,出生時間,過期時間等
year
===========year===================
create table t_year(born_year year); insert into t_year values (1901), (2155); select * from t_year; +-----------+ | born_year | +-----------+ | 1901 | | 2155 | +-----------+ 2 rows in set (0.00 sec)
date time datetime
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2017-08-01 19:38:54 |
+---------------------+
1 row in set (0.00 sec)
============date,time,datetime===========
create table t_mul(d date,t time,dt datetime);
insert into c07(1901,"1901-08-07", "2017-08-01 19:42:22"); # 注意:date和datetime類型插入數據時需要加引號,year 類型不用 insert into t_mul values(now(),now(),now()); select * from t_mul; mysql> select * from t_mul; +------------+----------+---------------------+ | d | t | dt | +------------+----------+---------------------+ | 2017-08-01 | 19:42:22 | 2017-08-01 19:42:22 | +------------+----------+---------------------+ 1 row in set (0.00 sec)
timestamp
create table t_stamp(t TIMESTAMP); insert into t_stamp values(); insert into t_stamp values(NULL ); select * from t_stamp; +---------------------+ | t | +---------------------+ | 2017-08-01 19:46:24 | | 2017-08-01 19:46:24 | +---------------------+ 2 rows in set (0.00 sec)

在實際應用的很多場景中,MySQL的這兩種日期類型都能夠滿足我們的需要,存儲精度都為秒, 但在某些情況下,會展現出他們各自的優劣。下面就來總結一下兩種日期類型的區別。 1.DATETIME的日期范圍是1001——9999年,TIMESTAMP的時間范圍是1970——2038年。 2.DATETIME存儲時間與時區無關,TIMESTAMP存儲時間與時區有關,顯示的值也依賴於時區。 在mysql服務器,操作系統以及客戶端連接都有時區的設置。 3.DATETIME使用8字節的存儲空間,TIMESTAMP的存儲空間為4字節。因此,TIMESTAMP比DATETIME的 空間利用率更高。 4.DATETIME的默認值為null;TIMESTAMP的字段默認不為空(not null),默認值為當前時間 (CURRENT_TIMESTAMP),如果不做特殊處理,並且update語句中沒有指定該列的更新值,則默 認更新為當前時間。
枚舉類型與集合類型
字段的值只能在給定范圍中選擇,如單選框,多選框
enum 單選 只能在給定的范圍內選一個值,如性別 sex 男male/女female
set 多選 在給定的范圍內可以選擇一個或一個以上的值(愛好1,愛好2,愛好3...)
解析:

枚舉類型(enum) An ENUM column can have a maximum of 65,535 distinct elements. (The practical limit is less than 3000.) 示例: CREATE TABLE shirts ( name VARCHAR(40), size ENUM('x-small', 'small', 'medium', 'large', 'x-large') ); INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'), ('polo shirt','small'); 集合類型(set) A SET column can have a maximum of 64 distinct members. 示例: CREATE TABLE myset (col SET('a', 'b', 'c', 'd')); INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
數據庫操作
-- 1.創建數據庫(在磁盤上創建一個對應的文件夾) create database [if not exists] db_name [character set xxx] -- 2.查看數據庫 show databases;查看所有數據庫 show create database db_name; 查看數據庫的創建方式 -- 3.修改數據庫 alter database db_name [character set xxx] -- 4.刪除數據庫 drop database [if exists] db_name; -- 5.使用數據庫 切換數據庫 use db_name; -- 注意:進入到某個數據庫后沒辦法再退回之前狀態,但可以通過use進行切換 查看當前使用的數據庫 select database();
數據表操作
創建表
-- 語法 CREATE TABLE tab_name( field1 type[完整性約束條件], field2 type, ... fieldn type )[character set xxx];
示例:
CREATE TABLE employee( id int primary key auto_increment , name varchar(20), gender bit default 1, birthday date, department varchar(20), salary double(8,2) unsigned, resume text );
查看表信息
desc tab_name 查看表結構 show columns from tab_name 查看表結構 show tables 查看當前數據庫中的所有的表 show create table tab_name 查看當前數據庫表建表語句
修改表結構
-- (1)增加列(字段) alter table tab_name add [column] 列名 類型[完整性約束條件][first|after 字段名]; #添加多個字段 alter table users2 add addr varchar(20), add age int first, add birth varchar(20) after name; -- (2)修改一列類型 alter table tab_name modify 列名 類型 [完整性約束條件][first|after 字段名]; -- (3)修改列名 alter table tab_name change [column] 列名 新列名 類型 [完整性約束條件][first|after 字段名]; -- (4)刪除一列 alter table tab_name drop [column] 列名;-- (5)修改表名 rename table 表名 to 新表名; -- (6)修該表所用的字符集 alter table student character set utf8;
刪除表
drop table tab_name;
表記錄操作
增加表記錄
/* <1>插入一條記錄: insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......); <2>插入多條記錄: insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......), (value1,value2,.......), ... ; <3>set插入: insert [into] tab_name set 字段名=值 */
INSERT employee (name,gender,birthday,salary,department) VALUES ("grace",1,"1985-12-12",8000,"保潔部"), ("egon",1,"1987-08-08",5000,"保安部"), ("yuan",1,"1990-06-06",20000,"教學部"); INSERT employee VALUES (8,"女神",0,"1992-02-12","教學部",7000,""); INSERT employee SET name="wusir",birthday="1990-11-11";
修改表記錄
1
|
update
tab_name
set
field1=value1,field2=value2,......[
where
語句]
|
示例:
update employee_new set birthday="1989-10-24" WHERE id=1; --- 將yuan的薪水在原有基礎上增加1000元。 update employee_new set salary=salary+4000 where name='yuan';
刪除表記錄
方式1: delete from tab_name [where ....] 方式2: truncate table emp_new; /* 如果不跟where語句則刪除整張表中的數據 delete只能用來刪除一行記錄 delete語句只能刪除表中的內容,不能刪除表本身,想要刪除表,用drop TRUNCATE TABLE也可以刪除表中的所有數據,詞語句首先摧毀表,再新建表。此種方式刪除的數據不能在 事務中恢復。 */
示例:
-- 刪除表中名稱為’alex’的記錄。 delete from employee_new where name='grace'; -- 刪除表中所有記錄。 delete from employee_new; -- 注意auto_increment沒有被重置:alter table employee auto_increment=1;
-- 查詢語法: SELECT *|field1,filed2 ... FROM tab_name WHERE 條件 GROUP BY field HAVING 篩選 ORDER BY field LIMIT 限制條數
-- Mysql在執行sql語句時的執行順序: -- from where group by having select order by
准備表和數據

CREATE TABLE emp( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), gender ENUM("male","female","other"), age TINYINT, dep VARCHAR(20), city VARCHAR(20), salary DOUBLE(7,2) ); INSERT INTO emp (name,gender,age,dep,city,salary) VALUES ("yuan","male",24,"教學部","河北省",8000), ("egon","male",34,"保安部","山東省",8000), ("alex","male",28,"保潔部","山東省",10000), ("景麗陽","female",22,"教學部","北京",9000), ("張三", "male",24,"教學部","河北省",6000), ("李四", "male",32,"保安部","北京",12000), ("王五", "male",38,"教學部","河北省",7000), ("趙六", "male",19,"保安部","河北省",9000), ("豬七", "female",24,"保潔部","北京",9000); SELECT * FROM emp;
mysql> SELECT * FROM emp; +----+-----------+--------+------+-----------+-----------+----------+ | id | name | gender | age | dep | city | salary | +----+-----------+--------+------+-----------+-----------+----------+ | 1 | yuan | male | 24 | 教學部 | 河北省 | 8000.00 | | 2 | egon | male | 34 | 保安部 | 山東省 | 8000.00 | | 3 | grace | male | 28 | 保潔部 | 山東省 | 10000.00 | | 4 | 景麗陽 | female | 22 | 教學部 | 北京 | 9000.00 | | 5 | 張三 | male | 24 | 教學部 | 河北省 | 6000.00 | | 6 | 李四 | male | 32 | 保安部 | 北京 | 12000.00 | | 7 | 王五 | male | 38 | 教學部 | 河北省 | 7000.00 | | 8 | 趙六 | male | 19 | 保安部 | 河北省 | 9000.00 | | 9 | 豬七 | female | 24 | 保潔部 | 北京 | 9000.00 | +----+-----------+--------+------+-----------+-----------+----------+ 9 rows in set (0.00 sec)
where子句: 過濾查詢
-- where字句中可以使用: -- 比較運算符: > < >= <= != <> between 80 and 100 值在10到20之間 in(80,90,100) 值是80或90或100 like 'yuan%' /* pattern可以是%或者_, 如果是%則表示任意多字符,此例如唐僧,唐國強 如果是_則表示一個字符唐_,只有唐僧符合。兩個_則表示兩個字符:__ */ -- 邏輯運算符 在多個條件直接可以使用邏輯運算符 and or not
示例:
-- 查詢年紀大於24的員工 SELECT * FROM emp WHERE age>24; -- 查詢教學部的男老師信息 SELECT * FROM emp WHERE dep="教學部" AND gender="male";
order:排序
按指定的列進行,排序的列即可是表中的列名,也可以是select語句后指定的別名。
-- 語法: select *|field1,field2... from tab_name order by field [Asc|Desc] -- Asc 升序、Desc 降序,其中asc為默認值 ORDER BY 子句應位於SELECT語句的結尾。
示例:
-- 按年齡從高到低進行排序 SELECT * FROM emp ORDER BY age DESC ; -- 按工資從低到高進行排序 SELECT * FROM emp ORDER BY salary;
group by:分組查詢(*****)
GROUP BY 語句根據某個列對結果集進行分組。在分組的列上我們可以使用 COUNT, SUM, AVG等函數進行相關查詢。
-- 語法: SELECT column_name, function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name;
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
-- 查詢男女員工各有多少人
SELECT
gender 性別,
count
(*) 人數
FROM
emp5
GROUP
BY
gender;
-- 查詢各個部門的人數
SELECT
dep 部門,
count
(*) 人數
FROM
emp5
GROUP
BY
dep;
-- 查詢每個部門最大的年齡
SELECT
dep 部門,
max
(age) 最大年紀
FROM
emp5
GROUP
BY
dep;
-- 查詢每個部門年齡最大的員工姓名
SELECT
*
FROM
emp5
WHERE
age
in
(
SELECT
max
(age)
FROM
emp5
GROUP
BY
dep);
-- 查詢每個部門的平均工資
SELECT
dep 部門,
avg
(salary) 最大年紀
FROM
emp
GROUP
BY
dep;
-- 查詢教學部的員工最高工資:
SELECT
dep,
max
(salary)
FROM
emp11
GROUP
BY
dep
HAVING
dep=
"教學部"
;
-- 查詢平均薪水超過8000的部門
SELECT
dep,
AVG
(salary)
FROM
emp
GROUP
BY
dep
HAVING
avg
(salary)>8000;
-- 查詢每個組的員工姓名
SELECT
dep,group_concat(
name
)
FROM
emp
GROUP
BY
dep;
-- 查詢公司一共有多少員工(可以將所有記錄看成一個組)
SELECT
COUNT
(*) 員工總人數
FROM
emp;
-- KEY: 查詢條件中的每個后的詞就是分組的字段
|
limit記錄條數限制
SELECT * from ExamResult limit 1; SELECT * from ExamResult limit 2,5; -- 跳過前兩條顯示接下來的五條紀錄 SELECT * from ExamResult limit 2,2;
正則表達式
SELECT * FROM employee WHERE emp_name REGEXP '^yu'; SELECT * FROM employee WHERE emp_name REGEXP 'yun$'; SELECT * FROM employee WHERE emp_name REGEXP 'm{2}';
多表查詢
創建表

CREATE TABLE emp( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), salary DOUBLE(7,2), dep_id INT ); INSERT INTO emp (name,salary,dep_id) VALUES ("張三",8000,2), ("李四",12000,1), ("王五",5000,2), ("趙六",8000,3), ("豬七",9000,1), ("周八",7000,4), ("蔡九",7000,2); CREATE TABLE dep( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) ); INSERT INTO dep (name) VALUES ("教學部"), ("銷售部"), ("人事部");
mysql> select * from emp; +----+--------+----------+--------+ | id | name | salary | dep_id | +----+--------+----------+--------+ | 1 | 張三 | 8000.00 | 2 | | 2 | 李四 | 12000.00 | 1 | | 3 | 王五 | 5000.00 | 2 | | 4 | 趙六 | 8000.00 | 3 | | 5 | 豬七 | 9000.00 | 1 | | 6 | 周八 | 7000.00 | 4 | | 7 | 蔡九 | 7000.00 | 2 | +----+--------+----------+--------+ 7 rows in set (0.00 sec)
mysql> select * from dep;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 教學部 |
| 2 | 銷售部 |
| 3 | 人事部 |
+----+-----------+
3 rows in set (0.00 sec)
1.笛卡爾積查詢
1
|
select
*
from
emp,dep;
|
mysql> select * from emp,dep; +----+--------+----------+--------+----+-----------+ | id | name | salary | dep_id | id | name | +----+--------+----------+--------+----+-----------+ | 1 | 張三 | 8000.00 | 2 | 1 | 教學部 | | 1 | 張三 | 8000.00 | 2 | 2 | 銷售部 | | 1 | 張三 | 8000.00 | 2 | 3 | 人事部 | | 2 | 李四 | 12000.00 | 1 | 1 | 教學部 | | 2 | 李四 | 12000.00 | 1 | 2 | 銷售部 | | 2 | 李四 | 12000.00 | 1 | 3 | 人事部 | | 3 | 王五 | 5000.00 | 2 | 1 | 教學部 | | 3 | 王五 | 5000.00 | 2 | 2 | 銷售部 | | 3 | 王五 | 5000.00 | 2 | 3 | 人事部 | | 4 | 趙六 | 8000.00 | 3 | 1 | 教學部 | | 4 | 趙六 | 8000.00 | 3 | 2 | 銷售部 | | 4 | 趙六 | 8000.00 | 3 | 3 | 人事部 | | 5 | 豬七 | 9000.00 | 1 | 1 | 教學部 | | 5 | 豬七 | 9000.00 | 1 | 2 | 銷售部 | | 5 | 豬七 | 9000.00 | 1 | 3 | 人事部 | | 6 | 周八 | 7000.00 | 4 | 1 | 教學部 | | 6 | 周八 | 7000.00 | 4 | 2 | 銷售部 | | 6 | 周八 | 7000.00 | 4 | 3 | 人事部 | | 7 | 蔡九 | 7000.00 | 2 | 1 | 教學部 | | 7 | 蔡九 | 7000.00 | 2 | 2 | 銷售部 | | 7 | 蔡九 | 7000.00 | 2 | 3 | 人事部 | +----+--------+----------+--------+----+-----------+ 21 rows in set (0.00 sec)
2、內連接
查詢兩張表中都有的關聯數據,相當於利用條件從笛卡爾積結果中篩選出了正確的結果。
1
|
SELECT
*
FROM
emp,dep
WHERE
emp.dep_id=dep.id;
|
OR
1
|
SELECT
*
FROM
emp
INNER
JOIN
dep
ON
emp.dep_id=dep.id;
|
查詢結果:
+----+--------+----------+--------+----+-----------+ | id | name | salary | dep_id | id | name | +----+--------+----------+--------+----+-----------+ | 1 | 張三 | 8000.00 | 2 | 2 | 銷售部 | | 2 | 李四 | 12000.00 | 1 | 1 | 教學部 | | 3 | 王五 | 5000.00 | 2 | 2 | 銷售部 | | 4 | 趙六 | 8000.00 | 3 | 3 | 人事部 | | 5 | 豬七 | 9000.00 | 1 | 1 | 教學部 | | 7 | 蔡九 | 7000.00 | 2 | 2 | 銷售部 | +----+--------+----------+--------+----+-----------+ 6 rows in set (0.00 sec)
這時,我們就可以利用兩張表中所有的字段進行查詢了
示例:
-- 查詢李四所在的部門名稱 SELECT emp.name,dep.name FROM emp INNER JOIN dep ON emp.dep_id=dep.id WHERE emp.name="李四"; -- 查詢銷售部所有員工姓名以及部門名稱 -- SELECT name FROM emp WHERE dep_id in (SELECT id FROM dep WHERE name="銷售部"); SELECT emp.name,dep.name FROM emp INNER JOIN dep ON emp.dep_id=dep.id WHERE dep.name="銷售部";
3、外連接
1
2
3
|
--(1)左外連接:在內連接的基礎上增加左邊有右邊沒有的結果
SELECT
*
FROM
emp
LEFT
JOIN
dep
ON
dep.id=emp.dep_id;
|
+----+--------+----------+--------+------+-----------+ | id | name | salary | dep_id | id | name | +----+--------+----------+--------+------+-----------+ | 2 | 李四 | 12000.00 | 1 | 1 | 教學部 | | 5 | 豬七 | 9000.00 | 1 | 1 | 教學部 | | 1 | 張三 | 8000.00 | 2 | 2 | 銷售部 | | 3 | 王五 | 5000.00 | 2 | 2 | 銷售部 | | 7 | 蔡九 | 7000.00 | 2 | 2 | 銷售部 | | 4 | 趙六 | 8000.00 | 3 | 3 | 人事部 | | 6 | 周八 | 7000.00 | 4 | NULL | NULL | +----+--------+----------+--------+------+-----------+ 7 rows in set (0.00 sec)
1
2
3
|
--(1)外右連接:在內連接的基礎上增加右邊有左邊沒有的結果
SELECT
*
FROM
emp
RIGHT
JOIN
dep
ON
dep.id=emp.dep_id;
|
mysql> SELECT * FROM emp RIGHT JOIN dep ON dep.id=emp.dep_id; +------+--------+----------+--------+----+-----------+ | id | name | salary | dep_id | id | name | +------+--------+----------+--------+----+-----------+ | 1 | 張三 | 8000.00 | 2 | 2 | 銷售部 | | 2 | 李四 | 12000.00 | 1 | 1 | 教學部 | | 3 | 王五 | 5000.00 | 2 | 2 | 銷售部 | | 4 | 趙六 | 8000.00 | 3 | 3 | 人事部 | | 5 | 豬七 | 9000.00 | 1 | 1 | 教學部 | | 7 | 蔡九 | 7000.00 | 2 | 2 | 銷售部 | +------+--------+----------+--------+----+-----------+ 6 rows in set (0.00 sec)
完整性約束
完整性約束是對字段進行限制,從而符合該字段達到我們期望的效果比如字段含有默認值,不能是NULL等 。直觀點說:如果插入的數據不滿足限制要求,數據庫管理系統就拒絕執行操作
唯一約束
唯一約束可以有多個但索引列的值必須唯一,索引列的值允許有空值。
如果能確定某個數據列將只包含彼此各不相同的值,在為這個數據列創建索引的時候就應該使用關鍵字UNIQUE。
CREATE TABLE t5( id INT AUTO_INCREMENT, name VARCHAR(20) DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY UK_t5_name (name) ); -- 建表后添加約束: alter table t5 add constraint UK_t5_name unique (name); -- 如果不需要唯一約束,則可以這樣刪除 ALTER TABLE t5 DROP INDEX UK_t5_name;
添加約束和刪除約束
1
2
3
4
5
6
7
8
9
10
|
-- 創建唯一約束:
create
unique
index
UK_t5_name
on
t5 (
name
);
-- 建表后添加約束:
alter
table
t5
add
constraint
UK_t5_name
unique
(
name
);
-- 如果不需要唯一約束,則可以這樣刪除
ALTER
TABLE
t5
DROP
INDEX
UK_t5_name;
|
自增約束
MySQL 每張表只能有1個自動增長字段,這個自動增長字段通常作為主鍵,也可以用作非主鍵使用,但是請注意將自動增長字段當做非主鍵使用時必須必須為其添加唯一索引,否則系統將會報錯。
mysql> CREATE TABLE t4( -> id INT NOT NULL, -> name VARCHAR(20), -> age INT AUTO_INCREMENT -> );
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a ke
可以改為
mysql> CREATE TABLE t4( -> id INT NOT NULL, -> name VARCHAR(20), -> age INT UNIQUE AUTO_INCREMENT -> ); Query OK, 0 rows affected (0.13 sec)
主鍵約束
主鍵是用於唯一標識一條記錄的約束,如同身份證。
主鍵有兩個約束:非空且唯一!
創建主鍵
-- 方式1 CREATE TABLE t1( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) ); -- 方式2 CREATE TABLE t2( id INT NOT NULL, name VARCHAR(20) );
注意:
1、一張表中最多只能有一個主鍵
2、表中如果沒有設置主鍵,默認設置NOT NULL的字段為主鍵;此外,表中如果有多個NOT NULL的字段,則按順序將第一個設置NOT NULL的字段設為主鍵。
結論:主鍵一定是非空且唯一,但非空且唯一的字段不一定是主鍵。
3、主鍵類型不一定必須是整型
添加主鍵和刪除主鍵
1
2
|
-- 添加主鍵<br>alter table tab_name add primary key(字段名稱,...) <br>
-- 刪除主鍵<br>alter table users drop primary key;
|
注意,如果主鍵是AUTO_INCREMENT,需要先取消AUTO_INCREMENT,因為AUTO_INCREMENT只能加在KEY上。
1
2
3
4
|
CREATE
TABLE
test(num
INT
PRIMARY
KEY
AUTO_INCREMENT);<br>
-- 思考,如何刪除主鍵?
ALTER
TABLE
test
modify
id
int
;
-- auto_increment沒了,但這樣寫主鍵依然存在,所以還要加上下面這句
ALTER
TABLE
test
drop
primary
key
;
-- 僅僅用這句也無法直接刪除主鍵
|
復合主鍵
所謂的復合主鍵 就是指你表的主鍵含有一個以上的字段。
如果一列不能唯一區分一個表里的記錄時,可以考慮多個列組合起來達到區分表記錄的唯一性,形式
①創建時:
1
2
3
4
5
6
|
create
table
sc (
studentid
int
,
courseid
int
,
score
int
,
primary
key
(studentno,courseid)
);
|
②修改時:
1
|
alter
table
tb_name
add
primary
key
(字段1,字段2,字段3);
|
外鍵約束
外鍵語法
1
2
3
4
5
|
外鍵的定義語法:
[
CONSTRAINT
symbol]
FOREIGN
KEY
[id] (index_col_name, ...)
REFERENCES
tbl_name (index_col_name, ...)
[
ON
DELETE
{
RESTRICT
|
CASCADE
|
SET
NULL
|
NO
ACTION
|
SET
DEFAULT
}]
[
ON
UPDATE
{
RESTRICT
|
CASCADE
|
SET
NULL
|
NO
ACTION
|
SET
DEFAULT
}]
|
該語法 可以在 CREATE TABLE 和 ALTER TABLE 時使用,如果不指定CONSTRAINT symbol,MYSQL會自動生成一個名字。
准備表和數據
-- 子表 CREATE TABLE emp( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), dep_id INT
-- CONSTRAINT emp_fk_emp FOREIGN KEY (dep_id) REFERENCES dep(id) -- 注意外鍵字段的數據類型必須與關聯字段一致 ); -- 主表 CREATE TABLE dep( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) ); INSERT emp (name,dep_id) VALUES ("grace",1), ("egon",2), ("alvi",2), ("莎莎",1), ("wusir",2), ("女神",2), ("冰冰",3), ("姍姍",3); INSERT dep (name) VALUES ("市場部"), ("教學部"), ("銷售部");
添加外鍵
現在,刪除市場部:
1
2
|
mysql>
DELETE
FROM
dep
WHERE
name
=
"市場部"
;
Query OK, 1 row affected (0.01 sec)
|
居然刪除成功了,不可思議,現在問題來了: alex和莎莎兩個人怎么辦?
所以,為了避免類似操作,我們需要給兩張表建立約束,這種約束稱為外鍵約束。外鍵的好處:可以使得兩張表關聯,保證數據的一致性和實現一些級聯操作
1
2
3
4
5
6
|
INSERT
dep (id,
name
)
VALUES
(1,
"市場部"
);
-- 思考為什么加這一句?
ALTER
TABLE
emp
ADD
CONSTRAINT
dep_fk_emp
FOREIGN
KEY
(dep_id)
REFERENCES
dep(id);
<br><br>mysql>
DELETE
FROM
dep
WHERE
name
=
"市場部"
;<br><br>ERROR 1451 (23000): Cannot
delete
or
update
a parent row: a
foreign
key
constraint
fail
|
INNODB支持的ON語句
外鍵約束對子表的含義: 如果在主表中(比如dep)找不到候選鍵,則不允許在子表(比如emp)上進行insert/update
外鍵約束對父表的含義: 在主表上進行update/delete以更新或刪除在子表中有一條或多條應匹配行的候選鍵時,父表的行為取決於:在定義子表的外鍵時指定的 -- on update/on delete子句
-- ------------------------innodb支持的四種方式--------------------------------- cascade方式 在父表上update/delete記錄時,同步update/delete掉子表的匹配記錄外鍵的級聯刪除:如果父表中的記錄被刪除,則子表中對應的記錄自動被刪除 FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) ON DELETE CASCADE; set null方式 在父表上update/delete記錄時,將子表上匹配記錄的列設為null ; 要注意子表的外鍵列不能為not null FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) ON DELETE SET NULL; Restrict方式 :拒絕對父表進行刪除更新操作(了解) No action方式 在mysql中同Restrict,如果子表中有匹配的記錄,則不允許對父表對應候選鍵 ;
進行update/delete操作(了解)