1、mysql添加記錄
--添加記錄的語法(可添加單條記錄或者多條記錄),INTO是可以省略的,字段名也可以省略的,但是如果省略的話,后面對應的value的值就要全部填寫 INSERT [INTO] tab_name [(col_name,...)] {VALUE|VALUES} (values...); --添加記錄的語法(只可添加一條記錄) INSERT tab_name SET 字段名稱=字段值,...; --從表中查詢記錄進行添加 INSERT tab_name SELECT 字段名稱 FROM tab1_name [WHERE 條件]
注意:通常情況下,以上語句在使用values插入單行數據的時候效率要比value來得高,但是插入多行數據的時候效率value要比values來得高,set與value|values相比效率要來得高,但是set是mysql的擴展,對於其他數據庫是不存在的,所以可移值性比較低,並且set一次只能添加一條數據。
舉例:
--測試用表 CREATE TABLE IF NOT EXISTS test( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '用戶ID', name VARCHAR(20) NOT NULL COMMENT '用戶名', sex ENUM('0','1','2') NOT NULL DEFAULT '0' COMMENT '性別0保密,1男,2女' )ENGINE=INNODB CHARSET=UTF8; --指定值 INSERT INTO test (name,sex) VALUES ('AA','0'); --不指定值,那么所對應的所有的值要全部寫出來 INSERT test VALUES (NULL,'BB','1'); --插入多條記錄,中間用逗號隔開,注意中英文狀下的逗號 INSERT test (name,sex) VALUE ('CC','2'),('DD','1'),('EE','0'),('FF','2'); --應用set來添加數據 INSERT test SET name="GG",sex="2"; --進行批量插入 INSERT user (name,sex) SELECT name,sex FROM test WHERE sex="1"
2、修改記錄
--更改記錄的語法(有點類似INSERT..SET) UPDATE tab_name SET 字段名=字段值,...[WHERE 條件];
注意:如果沒有指定where那么整張表的數據都會被更改。
--在id<3的名字后面加上ok,並且把性別改成默認值(默認值可以用DEFAULT來代替) UPDATE test SET name=CONCAT(name,'ok'),sex=DEFAULT WHERE id<=3; --SELECT * FROM test 輸出 -- +----+------+-----+ -- | id | name | sex | -- +----+------+-----+ -- | 1 | AAok | 0 | -- | 2 | BBok | 0 | -- | 3 | CCok | 0 | -- | 4 | DD | 2 | -- | 5 | EE | 1 | -- | 6 | FF | 0 | -- | 7 | GG | 2 | -- +----+------+-----+
批量更新數據表
使用MYSQL自帶語句進行批量更新
-- 使用update set 進行批量更新,注意:如果是多個條件的時候,每個條件的長度應該要相等 UPDATE tab_name SET 需修改的字段=CASE 參照字段 WHEN 參數字段值 THEN 修改字段值 ... END,...END [WHERE 條件]; -- 舉例,根據id修改名字和年齡 UPDATE user SET name = CASE id WHEN 1 THEN "AA" WHEN 2 THEN "BB" END,age=CASE id WHEN 1 THEN 18 WHEN 2 THEN 22 END WHERE id IN (1,2); -- 查詢修改記錄,當查詢到目標記錄的時候進行修改,如果沒有查詢到則進行插入 INSERT INTO tab_name (字段名,...) VALUE (值,...) ON DUPLICATE KEY UPDATE 字段名=VALUES(字段名); -- 舉例,注意:需要更改的字段放在ON DUPLICATE KEY UPDATE 后面 INSERT INTO `user` (id,name,age) VALUES (1,"小A",8),(2,"小B",18),(3,"小C",28),(4,"小D",38) ON DUPLICATE KEY UPDATE `name`=VALUES(name),age=VALUES(age); --謹慎使用 使用replace into 進行批量更新,注意該操作本質是對重復的記錄先delete 后insert,如果更新的字段不全會將缺失的字段置為缺省值 REPLACE INTO tab_name (字段名,...) VALUE (值,...); -- 舉例,如果在表中的唯一值里能匹配到相關的數據,那么會進行修改操作,否則會進行添加操作 REPLACE INTO user (id,name,age) VALUE (1,"CC",12),(2,"DD",27);
3、刪除記錄
--刪除記錄的語法,如果不添加條件,那么會刪除全部記錄 DELETE FROM tab_name [WHERE 條件]; --刪除記錄,同時也可以重置AUTO_INCREMENT的值 TRUNCATE [TABLE] tab_name
注意:如果不添加條件,那么會刪除全部記錄,但是通過delete刪除的全部記錄,不會重置AUTO_INCREMENT的值,但是可以通過ALTER TABLE tab_name AUTO_INCREMENT=1 進行設置
--刪除所有ID大於3的記錄 DELETE FROM test WHERE id>3; --SELECT * FROM test 輸出 -- +----+------+-----+ -- | id | name | sex | -- +----+------+-----+ -- | 1 | AAok | 0 | -- | 2 | BBok | 0 | -- | 3 | CCok | 0 | -- +----+------+-----+
4、查詢記錄

--查詢記錄的基本語法 SELECT select_expr,...FROM tab_name [WHERE 條件] [GROUP BY {col_name | position} HAVING 二次篩選] [ORDER BY {col_name |position|expr} [ASC | DESC]] [LIMIT 限制結果集的顯示條數]
[OFFSET 偏移量]
--可以使用庫名.表名的形式查詢數據(即可以不指定當前數據庫的情況下進行表查詢) SELECT select_expr,...FROM db_name.tab_name --可以給字段或者表名起別名(可以通過AS或者空隔對表名或者字段名進行起別名) SELECT col_name AS col_rename,... FROM tab_name AS tab_rename --建議要用AS來分隔,這個比較容易區分 SELECT col_name col_rename,... FROM tab_name tab_rename
注意:建議在起別名的時候,要加上AS以免引起混亂,並且在起別名的時候,要在字段上加上別名.字段,以免在以后在多表聯查時避免錯誤。
select distinct * from `表名`;
--以上面建的表為例 SELECT * FROM ytest.test; -- 輸出 -- +----+------+-----+ -- | id | name | sex | -- +----+------+-----+ -- | 1 | AAok | 0 | -- | 2 | BBok | 0 | -- | 3 | CCok | 0 | -- +----+------+-----+ --給字段起別名 SELECT t.name AS text,t.sex AS ss FROM ytest.test AS t; -- 輸出 -- +------+----+ -- | text | ss | -- +------+----+ -- | AAok | 0 | -- | BBok | 0 | -- | CCok | 0 | -- +------+----+
distinct與sum,count一起使用
-- 原數組 -- +----+------+-------+-----+-------+ -- | id | name | score | sex | class | -- +----+------+-------+-----+-------+ -- | 1 | aaa | 80 | 女 | 二班 | -- | 2 | bbb | 30 | 男 | 二班 | -- | 3 | ccc | 40 | 女 | 二班 | -- | 4 | ddd | 50 | 男 | 一班 | -- | 5 | eee | 80 | 男 | 一班 | -- | 6 | fff | 70 | 女 | 一班 | -- | 1 | aaa | 80 | 女 | 二班 | -- +----+------+-------+-----+-------+ SELECT SUM(DISTINCT `score`), COUNT(DISTINCT `score`) FROM `worker`; -- 輸出 -- +-----------------------+-------------------------+ -- | SUM(DISTINCT `score`) | COUNT(DISTINCT `score`) | -- +-----------------------+-------------------------+ -- | 270 | 5 | -- +-----------------------+-------------------------+
5、WHERE 的條件篩選(WHERE 條件會查詢篩選出符合條件的記錄,如果沒有符合條件的記錄,那么就會返回空記錄)
a、where條件的比較運算符:= > >= < <= != <> <=>
--為原表添加一個字段 ALTER TABLE test ADD tDesc VARCHAR(30) COMMENT "描述"; --查詢id=2的記錄,其他用法也是一樣的 SELECT id,name,sex FROM test WHERE id=2; --查詢是否為空值 SELECT id,name FROM test WHERE tDesc IS NULL; SELECT id,name FROM test WHERE tDesc <=> NULL; --查詢不為空值 SELECT id,name FROM test WHERE tDesc IS NOT NULL;
注意:<=>與=的用法基本一樣,但是<=>是可以檢測是否為NULL值,但是=不可以檢測,同時<=>是MYSQL獨有的語法,在其他語言不可以使用,而=可以通用
b、邏輯運算符:AND(邏輯與) OR(邏輯或) NOT(邏輯非) BETWEEN...AND...(介於兩者之間)
-- 舉例 SELECT id,name FROM test WHERE id<=2 AND sex='0'; -- 注意這個BETWEEN...AND...是包含1和2的 SELECT id,name FROM test WHERE id BETWEEN 1 AND 2; -- NOT 舉例 SELECT id,name FROM test WHERE NOT (id = 1);
c、模糊查詢like和 not like的使用
通配符%表示匹配0個1個或者多個字符,通配符_表示匹配一個字符
-- 匹配A前后有任意個字符的情況 SELECT id,name FROM test WHERE name LIKE "%A%"; -- 匹配A前有一個字付,后面任意個字符的情況 SELECT id,name FROM test WHERE name LIKE "_A%"; -- 匹配A前有一個字付,后面至少一個字符的情況 SELECT id,name FROM test WHERE name LIKE "_A_%";
6、GROUP BY 分組
group by 把值相同的放到一個組中,最終查詢出的結果只會顯示組中的一條記錄
--舉例 --的按照性別分組,group by 的值段可以沒有在SELECT 里面 SELECT id,name,sex FROM test GROUP BY sex; --展示效果 -- +----+------+-----+ -- | id | name | sex | -- +----+------+-----+ -- | 10 | CC | 0 | -- | 8 | AA | 1 | -- | 9 | BB | 2 | -- +----+------+-----+
注意,如果 需要看組中的成員,那么可以用到函數GROUP_CONCAT
--查看組中的成員 SELECT id,GROUP_CONCAT(name),GROUP_CONCAT(sex) FROM test Group BY sex; --輸出 -- +----+--------------------+-------------------+ -- | id | GROUP_CONCAT(name) | GROUP_CONCAT(sex) | -- +----+--------------------+-------------------+ -- | 10 | CC,EE | 0,0 | -- | 8 | AA,DD,GG | 1,1,1 | -- | 9 | BB,FF | 2,2 | -- +----+--------------------+-------------------+
GROUP BY 配合聚合函數使用
COUNT() 計數 SUM()求和 MAX() 最大值 MIN()最小值 AVG() 平均值
COUNT(col_name)與COUNT(*)的最大區別是,前者如果遇到值為null的時候,則不會計入范圍,而后者會。所以后者可以作為統計總數用。
GROUP BY 與COUNT(*)結合的例子
--查看組中的成員,同時統計數量 SELECT sex,GROUP_CONCAT(name),COUNT(*) FROM test GROUP BY(sex); --輸出 -- +-----+--------------------+----------+ -- | sex | GROUP_CONCAT(name) | COUNT(*) | -- +-----+--------------------+----------+ -- | 0 | CC,EE | 2 | -- | 1 | AA,DD,GG | 3 | -- | 2 | BB,FF | 2 | -- +-----+--------------------+----------+
GROUP BY 與SUM() , MAX() , MIN() , AVG() ,COUNT() 配合使用
--按性別分組,查看組中成員,個數,年齡總和,平均年齡,最小年齡,最大年齡 SELECT GROUP_CONCAT(name),COUNT(*),SUM(age),AVG(age),MAX(age),MIN(age) FROM test GROUP BY sex; --輸出 -- +--------------------+----------+----------+----------+----------+----------+ -- | GROUP_CONCAT(name) | COUNT(*) | SUM(age) | AVG(age) | MAX(age) | MIN(age) | -- +--------------------+----------+----------+----------+----------+----------+ -- | CC,EE | 2 | 85 | 42.5000 | 47 | 38 | -- | AA,DD,GG | 3 | 103 | 34.3333 | 78 | 7 | -- | BB,FF | 2 | 48 | 24.0000 | 26 | 22 | -- +--------------------+----------+----------+----------+----------+----------+
SELECT COUNT(IF(`score`>50,1,NULL)) FROM `worker`; -- 輸出 -- +------------------------------+ -- | COUNT(IF(`score`>50,1,NULL)) | -- +------------------------------+ -- | 2 | -- +------------------------------+
sum 函數在對單列進行求和時如果有Null值,是不影響值,當對多列進行sum統計時,就會有錯誤。
注意:如果GROUP BY 在和WHERE 使用的時候,WHERE 應該要放在GROUP BY 前面,不然會報錯的。
--先查詢年齡大小20歲的並按性別分組,查看組中成員,個數,年齡總和,平均年齡,最小年齡,最大年齡 SELECT GROUP_CONCAT(name),COUNT(*),SUM(age),AVG(age),MAX(age),MIN(age) FROM test WHERE age>20 GROUP BY sex; --輸出 -- +--------------------+----------+----------+----------+----------+----------+ -- | GROUP_CONCAT(name) | COUNT(*) | SUM(age) | AVG(age) | MAX(age) | MIN(age) | -- +--------------------+----------+----------+----------+----------+----------+ -- | CC,EE | 2 | 85 | 42.5000 | 47 | 38 | -- | GG | 1 | 78 | 78.0000 | 78 | 78 | -- | BB,FF | 2 | 48 | 24.0000 | 26 | 22 | -- +--------------------+----------+----------+----------+----------+----------+
注意:如果對分組后的數據進行二次篩選,那么可以使用HAVING,並且HAVING要放在GROUP BY 后面,不然會報錯的,HAVING與WHERE的不同之處在於后者不能對AS后的字段不能選擇,而前者不能對未SELECT的字段進行選擇。
--按性別分組,查看組中成員,個數,年齡總和,平均年齡,最小年齡,最大年齡,並且篩選年齡總和大於50的組 SELECT GROUP_CONCAT(name),COUNT(*),SUM(age) AS total,AVG(age),MAX(age),MIN(age) FROM test GROUP BY sex HAVING total>50; --輸出 -- +--------------------+----------+-------+----------+----------+----------+ -- | GROUP_CONCAT(name) | COUNT(*) | total | AVG(age) | MAX(age) | MIN(age) | -- +--------------------+----------+-------+----------+----------+----------+ -- | CC,EE | 2 | 85 | 42.5000 | 47 | 38 | -- | AA,DD,GG | 3 | 103 | 34.3333 | 78 | 7 | -- +--------------------+----------+-------+----------+----------+----------+
在GROUP BY 后面 WITH ROLLUP 進行數據匯總,相當於把上面的值按一組情況進行統計
--按性別分組,查看組中成員,個數,年齡總和,平均年齡,最小年齡,最大年齡,並且進行全部數據的匯總 SELECT GROUP_CONCAT(name),COUNT(*),SUM(age),AVG(age),MAX(age),MIN(age) FROM test GROUP BY sex WITH ROLLUP; --輸出 -- +----------------------+----------+----------+----------+----------+----------+ -- | GROUP_CONCAT(name) | COUNT(*) | SUM(age) | AVG(age) | MAX(age) | MIN(age) | -- +----------------------+----------+----------+----------+----------+----------+ -- | CC,EE | 2 | 85 | 42.5000 | 47 | 38 | -- | AA,DD,GG | 3 | 103 | 34.3333 | 78 | id 7 | -- | BB,FF | 2 | 48 | 24.0000 | 26 | 22 | -- | CC,EE,AA,DD,GG,BB,FF | 7 | 236 | 33.7143 | 78 | 7 | -- +----------------------+----------+----------+----------+----------+----------+
GROUP BY 也是可以進行多個分組統計的(中間用逗號隔開)
-- 數據源 +----+------+-------+-----+-------+ | id | name | score | sex | class | +----+------+-------+-----+-------+ | 1 | aaa | 80 | 女 | 二班 | | 2 | bbb | 30 | 男 | 二班 | | 3 | ccc | 40 | 女 | 二班 | | 4 | ddd | 50 | 男 | 一班 | | 5 | eee | 80 | 男 | 一班 | +----+------+-------+-----+-------+ SELECT `sex`, `class`, AVG(`score`) FROM `worker` GROUP BY `sex`, `class`; -- 輸出 -- +-----+-------+------------+ -- | sex | class | avg(score) | -- +-----+-------+------------+ -- | 男 | 一班 | 65.0000 | -- | 男 | 二班 | 30.0000 | -- | 女 | 二班 | 60.0000 | -- +-----+-------+------------+
SELECT GROUP_CONCAT(`name`) AS "name",GROUP_CONCAT(`score`) AS "score",GROUP_CONCAT(`sex`) AS "sex",GROUP_CONCAT(`class`) AS "class",MAX(`score`),AVG(`score`) FROM `worker` GROUP BY `sex`,`class`; -- 輸出 -- +---------+-------+-------+-----------+--------------+--------------+ -- | name | score | sex | class | MAX(`score`) | AVG(`score`) | -- +---------+-------+-------+-----------+--------------+--------------+ -- | ddd,eee | 50,80 | 男,男 | 一班,一班 | 80 | 65.0000 | -- | bbb | 30 | 男 | 二班 | 30 | 30.0000 | -- | aaa,ccc | 80,40 | 女,女 | 二班,二班 | 80 | 60.0000 | -- +---------+-------+-------+-----------+--------------+--------------+
7、ORDER BY 進行排序
ORDER BY 對數據進行排序 語法:ORDER BY 字段名 ASC|DESC 默認是ASC 升序,DESC 降序,同時也可以按照多個字段排序(如果兩個字段相等的情況下)兩個排序有逗號隔開,如果按照隨機排序,那么用ORDER BY RAND() 即可
--按照年齡降序排序,如果有相同的情況下按照ID升序排序 SELECT * FROM test ORDER BY age DESC,id ASC; -- 輸出 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 14 | GG | 1 | 78 | -- | 12 | EE | 0 | 47 | -- | 10 | CC | 0 | 38 | -- | 13 | FF | 2 | 26 | -- | 9 | BB | 2 | 22 | -- | 8 | AA | 1 | 18 | -- | 11 | DD | 1 | 7 | -- +----+------+-----+-----+ -- 按照年齡隨機排序 SELECT * FROM test ORDER BY RAND(); -- 輸出 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 8 | AA | 1 | 18 | -- | 14 | GG | 1 | 78 | -- | 10 | CC | 0 | 38 | -- | 11 | DD | 1 | 7 | -- | 9 | BB | 2 | 22 | -- | 12 | EE | 0 | 47 | -- | 13 | FF | 2 | 26 | -- +----+------+-----+-----+
8、LIMIT , OFFSET 限制結果集顯示條數
LIMIT+一個值 => 顯示結果集的前幾條數據;
LIMIT+offset+row_count=> 從offset開始,顯示row_count條數據
LIMIT +row_count OFFSET +offset => 意思同上(注意:offset要放在limit的后面,否則會報錯)
--數據正常顯示 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 8 | AA | 1 | 18 | -- | 9 | BB | 2 | 22 | -- | 10 | CC | 0 | 38 | -- | 11 | DD | 1 | 7 | -- | 12 | EE | 0 | 47 | -- | 13 | FF | 2 | 26 | -- | 14 | GG | 1 | 78 | -- +----+------+-----+-----+ --用LIMIT+數值 SELECT * FROM test ORDER BY id DESC LIMIT 3; -- 輸出 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 14 | GG | 1 | 78 | -- | 13 | FF | 2 | 26 | -- | 12 | EE | 0 | 47 | -- +----+------+-----+-----+ --用LIMIT+offset+row_count SELECT * FROM test ORDER BY id LIMIT 3,2; -- 輸出 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 11 | DD | 1 | 7 | -- | 12 | EE | 0 | 47 | -- +----+------+-----+-----+ --利用LIMIT+row_count OFFSET+offset SELECT * FROM test ORDER BY id ASC LIMIT 2 OFFSET 3; -- 輸出 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 11 | DD | 1 | 7 | -- | 12 | EE | 0 | 47 | -- +----+------+-----+-----+
利用limit與update ,delete進行配合使用
limit 與 update,delete 進行配合使用的時候只能用LIMIT+數值的模式,表示更新或者刪除前幾條數據
--limit 與 update 配合使用 UPDATE test SET age=22 LIMIT 3; -- 輸出 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 8 | AA | 1 | 22 | -- | 9 | BB | 2 | 22 | -- | 10 | CC | 0 | 22 | -- | 11 | DD | 1 | 7 | -- | 12 | EE | 0 | 47 | -- | 13 | FF | 2 | 26 | -- | 14 | GG | 1 | 78 | -- +----+------+-----+-----+ -- limit 與 delete 配合使用 DELETE FROM test LIMIT 1; -- 輸出 -- +----+------+-----+-----+ -- | id | name | sex | age | -- +----+------+-----+-----+ -- | 9 | BB | 2 | 22 | -- | 10 | CC | 0 | 22 | -- | 11 | DD | 1 | 7 | -- | 12 | EE | 0 | 47 | -- | 13 | FF | 2 | 26 | -- | 14 | GG | 1 | 78 | -- +----+------+-----+-----+
9、多表查詢
多表連接查詢主要分成三部份,笛卡爾積的形式,內連接,外連接三種形式。
新建測試表
--員工表 CREATE TABLE IF NOT EXISTS user( id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT "用戶ID", pid TINYINT UNSIGNED NOT NULL, name VARCHAR(20) NOT NULL, sex ENUM('0','1','2') DEFAULT "0" NOT NULL, age TINYINT UNSIGNED NOT NULL DEFAULT 0 )ENGINE=INNODB CHARSET=UTF8; --創建部門表 CREATE TABLE IF NOT EXISTS part( id TINYINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '部門id', name VARCHAR(20) NOT NULL )ENGINE='INNODB' CHARSET=UTF8; --插入數據 INSERT part (name) VALUE ('html'),('css'),('javascript'),('php'),('java'); INSERT user (pid,name,sex,age) VALUE ('1','AA','2',22),('1','BB','2',21),('2','CC','1',24),('4','DD','1',24),('5','EE','1',28),('3','FF','2',25),('4','GG','0',23),('2','EE','1',18),('3','FF','2',27);
笛卡爾積的形式(進行多表查詢是篩選語句不能少於n-1個)
-- 笛卡爾積連接 SELECT * FROM `emp`, `dept` WHERE emp.deptno = dept.deptno; -- 輸出 -- +-------+--------+-----------+------+------------+---------+---------+--------+--------+------------+----------+ -- | empno | ename | job | mgr | hiredate | sal | comm | deptno | deptno | dname | loc | -- +-------+--------+-----------+------+------------+---------+---------+--------+--------+------------+----------+ -- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | 20 | RESEARCH | DALLAS | -- | 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 | 30 | SALES | CHICAGO | -- | 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 | 30 | SALES | CHICAGO | -- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | 20 | RESEARCH | DALLAS | -- | 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 | 30 | SALES | CHICAGO | -- | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 | 30 | SALES | CHICAGO | -- | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 | 10 | ACCOUNTING | NEW YORK | -- | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 | 20 | RESEARCH | DALLAS | -- | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 | 10 | ACCOUNTING | NEW YORK | -- | 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | NULL | 30 | 30 | SALES | CHICAGO | -- | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 | 30 | SALES | CHICAGO | -- | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 | 20 | RESEARCH | DALLAS | -- | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 | 10 | ACCOUNTING | NEW YORK | -- +-------+--------+-----------+------+------------+---------+---------+--------+--------+------------+----------+
SELECT emp.*, dept.dname FROM `emp`, `dept` WHERE emp.deptno = dept.deptno;
自連接 :在同一張表的連接查詢(就是給本表取個別名進行連接)
SELECT worker.ename, boss.ename FROM emp AS worker,emp AS boss WHERE worker.mgr=boss.empno; -- 輸出 -- +--------+-------+ -- | ename | ename | -- +--------+-------+ -- | SCOTT | JONES | -- | FORD | JONES | -- | ALLEN | BLAKE | -- | WARD | BLAKE | -- | MARTIN | BLAKE | -- | TURNER | BLAKE | -- | JAMES | BLAKE | -- | MILLER | CLARK | -- | JONES | KING | -- | BLAKE | KING | -- | CLARK | KING | -- | SMITH | FORD | -- +--------+-------+ -- 查詢和SMITH同一部門的員工 SELECT * FROM `emp` WHERE `deptno` = (SELECT `deptno` FROM `emp` WHERE `ename`="SMITH"); -- 輸出 -- +-------+-------+---------+------+------------+---------+------+--------+ -- | empno | ename | job | mgr | hiredate | sal | comm | deptno | -- +-------+-------+---------+------+------------+---------+------+--------+ -- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | -- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | -- | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 | -- | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 | -- +-------+-------+---------+------+------------+---------+------+--------+ -- 查詢10號部門都有哪些崗位,並且都有哪些員工在從事相關工作 SELECT * FROM `emp` WHERE `job` in (SELECT DISTINCT `job` FROM `emp` WHERE `deptno`=10); -- 輸出 -- +-------+--------+-----------+------+------------+---------+------+--------+ -- | empno | ename | job | mgr | hiredate | sal | comm | deptno | -- +-------+--------+-----------+------+------------+---------+------+--------+ -- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | -- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | -- | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 | -- | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 | -- | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 | -- | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 | -- | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 | -- +-------+--------+-----------+------+------------+---------+------+--------+ -- 查詢和小明數學,語文,英語成績一樣的學生 SELECT * FROM `student` WHERE (`chinese`,`english`,`math`) = (SELECT `chinese`,`english`,`math` FROM `student` WHERE `name`='小明'); -- 表emp -- +-------+--------+-----------+------+------------+---------+---------+--------+ -- | empno | ename | job | mgr | hiredate | sal | comm | deptno | -- +-------+--------+-----------+------+------------+---------+---------+--------+ -- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | -- | 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 | -- | 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 | -- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | -- | 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 | -- | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 | -- | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 | -- | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 | -- | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 | -- | 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | NULL | 30 | -- | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 | -- | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 | -- | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 | -- +-------+--------+-----------+------+------------+---------+---------+--------+ -- 需求:顯示高於自己部門平均工次的員工(名字,工資,部門平均工資) SELECT emp.ename,emp.sal,temp.avgSal FROM `emp`, (SELECT AVG(`sal`) AS 'avgSal', `deptno` FROM `emp` GROUP BY `deptno`) AS `temp` WHERE emp.deptno=temp.deptno AND emp.sal>temp.avgSal; -- 以上語句等價於下以語句 SELECT emp.ename,emp.sal,temp.avgSal FROM `emp` INNER JOIN (SELECT AVG(`sal`) AS avgSal, `deptno` FROM `emp` GROUP BY `deptno`) AS temp on emp.deptno=temp.deptno WHERE emp.deptno=temp.deptno AND emp.sal>temp.avgSal; -- 輸出 -- +-------+---------+-------------+ -- | ename | sal | avgSal | -- +-------+---------+-------------+ -- | ALLEN | 1600.00 | 1566.666667 | -- | JONES | 2975.00 | 2443.750000 | -- | BLAKE | 2850.00 | 1566.666667 | -- | SCOTT | 3000.00 | 2443.750000 | -- | KING | 5000.00 | 2916.666667 | -- | FORD | 3000.00 | 2443.750000 | -- +-------+---------+-------------+
內連接:表示查詢兩個表中符合連接條件的記錄(實際上就是利用where子句對兩張(多表)形成的笛卡爾積進行篩選)
-- 語法,表示只顯示兩個表之間的公共部分 SELECT 字段名稱,...FROM tab_name INNER JOIN tab_name2 ON 連接條件 -- 舉例 SELECT u.id,u.name,u.sex,u.age,p.name FROM user AS u INNER JOIN part AS p ON u.pid=p.id; -- 輸出 -- +----+------+-----+-----+------------+ -- | id | name | sex | age | name | -- +----+------+-----+-----+------------+ -- | 1 | AA | 2 | 22 | html | -- | 2 | BB | 2 | 21 | html | -- | 3 | CC | 1 | 24 | css | -- | 8 | EE | 1 | 18 | css | -- | 6 | FF | 2 | 25 | javascript | -- | 9 | FF | 2 | 27 | javascript | -- | 4 | DD | 1 | 24 | php | -- | 7 | GG | 0 | 23 | php | -- | 5 | EE | 1 | 28 | java | -- +----+------+-----+-----+------------+
外連接:外連接主要分為兩種連接方式,左外連接與右外連接
左外連接:先顯示左表中的全部記錄,再去右表中查詢復合條件的記錄,不符合的以NULL值代替;
右外連接:先顯示右表中的全部記錄,再去左表中查詢復合條件的記錄,不符合的以NULL 值代替;
-- 語法 SELECT 字段名稱,...FROM tab_name LEFT|RIGHT JOIN tab_name2 ON 連接條件
-- 左外邊接 SELECT u.id,u.name,u.age,p.name FROM user AS u LEFT JOIN part AS p on u.pid=p.id; -- 右外邊接 SELECT u.id,u.name,u.age,p.name FROM user AS u RIGHT JOIN part AS p on u.pid=p.id;
10、外鍵約束(保證表的一致性,完整性)
目錄只有innodb的存儲引擎支持外鍵,並且指向的主表的值是primary key 或者是 unique
表示當添加從表數據或者修改從表數據時,所關聯的主表的外鍵指向的值是已經存在的
創建外鍵約束的方法有兩個,一個是在建表的時候指定外鍵約束,一個是動態創建外鍵約束
-- 建表時創建外鍵約束語法(注意:子表的外鍵字段和主表的字段的類型要一致),如果外鍵字段沒有創建索引,mysql會自動創建索引,后面表示是否設置級聯操作 [CONSTRAINT 外鍵名稱] FOREIGN KEY (字段名稱) REFERENCES 主表(字段名稱) [ON DELETE CASCADE ON UPDATE CASCADE];
注意:當外鍵子表下有數據的情況下,主表所對應的字段是不允許更改的,除非把子表所對應的數據刪除。
CREATE TABLE IF NOT EXISTS job( id TINYINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'JOB ID', name VARCHAR(20) NOT NULL )ENGINE=INNODB CHARSET=UTF8; CREATE TABLE IF NOT EXISTS user( id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '用戶ID', name VARCHAR(20) NOT NULL, age TINYINT UNSIGNED NOT NULL DEFAULT 0, jid TINYINT UNSIGNED NOT NULL, CONSTRAINT user_fk_job FOREIGN KEY (jid) REFERENCES job(id) )ENGINE=INNODB CHARSET=UTF8; --如果有問題輸入SET NAMES gbk; INSERT job (name) VALUE ("行政"),("人事"),("設計"),("編程"),("銷售"); INSERT user (name,age,jid) VALUE ("小明",20,1),('小紅',23,2),('小陳',34,3),('小剛',27,4),('小列',18,5),('小小',26,4); -- 提示刪除失敗,因為有外鍵約束 DELETE FROM job WHERE id=2;
動態添加和刪除外鍵限制
-- 動態刪除外鍵 ALTER TABLE tab_name DROP FOREIGN KEY foreign_name; -- 舉例 ALTER TABLE user DROP FOREIGN KEY user_fk_job; -- 動態添加外鍵限制不指定外鍵名稱 ALTER TABLE tab_name ADD FOREIGN KEY (字段名) REFERENCES 主表(字段名稱) [ON DELETE CASCADE ON UPDATE CASCADE]; -- 動態添加外鍵限制並且指定外鍵名稱 ALTER TABLE tab_name ADD CONSTRAINT 外鍵名稱 FOREIGN KEY (字段名) REFERENCES 主表(字段名稱) [ON DELETE CASCADE ON UPDATE CASCADE];
-- 舉例
ALTER TABLE user ADD FOREIGN KEY (jid) REFERENCES job (id);
注意:設置級聯操作,即主表進行刪除或者更新之后,所對應的子表也會相對應的更新或者刪除操作(CASCADE)
11、子查詢(是指嵌入在其他sql查詢語句的select語名,也叫嵌套查詢)
單行子查詢=》表示只返回一行數據的子查詢語句
-- 查詢和SMITH同一部門的員工 SELECT * FROM `emp` WHERE `deptno` = (SELECT `deptno` FROM `emp` WHERE `ename`="SMITH"); -- 輸出 -- +-------+-------+---------+------+------------+---------+------+--------+ -- | empno | ename | job | mgr | hiredate | sal | comm | deptno | -- +-------+-------+---------+------+------------+---------+------+--------+ -- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | -- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | -- | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 | -- | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 | -- +-------+-------+---------+------+------------+---------+------+--------+
多行子查詢=》表示返回多行數據的子查詢語句(使用關鍵字In)
-- 查詢10號部門都有哪些崗位,並且都有哪些員工在從事相關工作 SELECT * FROM `emp` WHERE `job` in (SELECT DISTINCT `job` FROM `emp` WHERE `deptno`=10); -- 輸出 -- +-------+--------+-----------+------+------------+---------+------+--------+ -- | empno | ename | job | mgr | hiredate | sal | comm | deptno | -- +-------+--------+-----------+------+------------+---------+------+--------+ -- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | -- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | -- | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 | -- | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 | -- | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 | -- | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 | -- | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 | -- +-------+--------+-----------+------+------------+---------+------+--------+
內層語句的查詢結果可以作為外層語句的查詢結果,這種情況就稱作為子查詢。(注意子子查詢要放在括號里面)
由IN,NOT IN,運算符,EXISTS等引發的子查詢,以及由運算符引發的子查詢
-- 由 IN 與 NOT IN 引發的子查詢 SELECT id,name,age FROM user WHERE jid IN (SELECT id FROM job); SELECT id,name,age FROM user WHERE jid NOT IN (SELECT id FROM job); -- 由運算符引發的子查詢 SELECT id,name,age FROM user WHERE jid=(SELECT id FROM job WHERE name ="編程"); -- 由EXISTS引發的子查詢,表示當子查詢的記錄存在的情況下,才執行主查詢的語句 SELECT id,name,age FROM user WHERE EXISTS (SELECT id FROM job WHERE id=20);
由 ANY SOME ALL 引發的子查詢(下圖表示的是右側所對應的值在全組中的狀態)

-- 數據展示 -- +----+------+-----+-----+ -- | id | name | age | jid | -- +----+------+-----+-----+ -- | 1 | 小明 | 20 | 1 | -- | 2 | 小紅 | 23 | 2 | -- | 3 | 小陳 | 34 | 3 | -- | 4 | 小剛 | 27 | 4 | -- | 5 | 小列 | 18 | 5 | -- | 6 | 小小 | 26 | 4 | -- +----+------+-----+-----+ SELECT name,age FROM user WHERE age>ANY(SELECT age FROM user); -- 輸出所有的結果 SELECT name,age FROM user WHERE age>=ALL(SELECT age FROM user); -- 輸出小陳 34 SELECT name,age FROM user WHERE age = ANY(SELECT age FROM user); -- 輸出全部記錄,因為全部都能找到匹配的 SELECT id, name,age FROM user WHERE id<3 AND age !=ALL(SELECT age FROM user WHERE id>2); -- 輸出id為1和2的記錄
多列子查詢 =》 如果我們的一個子查詢,返回的結果是多列的,那我們就把這個子查詢叫做多列子查詢
-- 查詢和小明數學,語文,英語成績一樣的學生 SELECT * FROM `student` WHERE (`chinese`,`english`,`math`) = (SELECT `chinese`,`english`,`math` FROM `student` WHERE `name`='小明');
括號里的字段和值是一一對應的關系
在from子句中使用的子查詢
在from子句中出現在子查詢,我們通常在會把在from中構建的臨時表當作正常表來使用
-- 表emp -- +-------+--------+-----------+------+------------+---------+---------+--------+ -- | empno | ename | job | mgr | hiredate | sal | comm | deptno | -- +-------+--------+-----------+------+------------+---------+---------+--------+ -- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 | -- | 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 | -- | 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 | -- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 | -- | 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 | -- | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 | -- | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 | -- | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 | -- | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 | -- | 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | NULL | 30 | -- | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 | -- | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 | -- | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 | -- +-------+--------+-----------+------+------------+---------+---------+--------+ -- 需求:顯示高於自己部門平均工次的員工(名字,工資,部門平均工資) SELECT emp.ename,emp.sal,temp.avgSal FROM `emp`, (SELECT AVG(`sal`) AS 'avgSal', `deptno` FROM `emp` GROUP BY `deptno`) AS `temp` WHERE emp.deptno=temp.deptno AND emp.sal>temp.avgSal; -- 輸出 -- +-------+---------+-------------+ -- | ename | sal | avgSal | -- +-------+---------+-------------+ -- | ALLEN | 1600.00 | 1566.666667 | -- | JONES | 2975.00 | 2443.750000 | -- | BLAKE | 2850.00 | 1566.666667 | -- | SCOTT | 3000.00 | 2443.750000 | -- | KING | 5000.00 | 2916.666667 | -- | FORD | 3000.00 | 2443.750000 | -- +-------+---------+-------------+
12、聯合查詢
UNION 語法:SELECT col_name,... FROM tab_name1 UNION SELECT col_name,...FROM tab_name2
UNION ALL 語法:SELECT col_name,... FROM tab_name1 UNION ALL SELECT col_name,...FROM tab_name2
注意:UNION 會去掉兩個表中重復的值,而UNION ALL 只是簡單的兩個表的合並,並且UNION 或者 UNION ALL 前后的col_name的列數要一致,而且列名會以第一個SELECT 的列作為字段名稱。
-- 舉例,下面的名稱就是第一個SELECT的AS后面的名稱 SELECT name AS count FROM user UNION SELECT id FROM job -- 輸出 -- +-------+ -- | count | -- +-------+ -- | 小明 | -- | 小紅 | -- | 小陳 | -- | 小剛 | -- | 小列 | -- | 小小 | -- | 編程 | -- | 1 | -- | 2 | -- | 3 | -- | 4 | -- | 5 | -- | 7 | -- +-------+
13、正則表達式查詢
使用方式,用 REGEXP "匹配方式" 就可以了,相當於JS里面的test 的功能。正則的寫法同JS或者PHP一樣。
語法: SELECT 字段名稱,...FROM tab_name WHERE 字段名稱 REGEXP "匹配模式"
-- 以小開始的數據 SELECT id,name FROM user WHERE name REGEXP '^小'; -- 以程結尾的數據 SELECT id,name FROM user WHERE name REGEXP '程$'; -- 包含明,紅,剛的數據 SELECT id,name FROM user WHERE name REGEXP '明|紅|剛';
14、mysql的三元運算符與IFNULL語句
CASE WHEN 條件 THEN 結果1 ELSE 結果2 END 語句
-- 與SUM合用 SELECT SUM(CASE WHEN c.checkresult= '合格' THEN 1 ELSE 0 END) AS qualified, SUM(CASE WHEN c.checkresult = '不合格' THEN 1 ELSE 0 END) AS disqualification, COUNT(*) AS count FROM tab_name WHERE [條件]; -- sql中ifnull用法: SELECT IFNULL(x,0,1) from tab_name; -- 解釋:如果表a中x字段是null,輸出為0,否則輸出1 -- 擴展用法:select ifnull(SUM(x),0) from a;
ifnull(express1,express2) 當express1為空時返回express2函數,當express1不為空時返回express1函數,eg sum(ifnull(x,0));
15、mysql 常用函數表(部份函數解析祥見函數那篇博客)

16、mysql 事務性操作
事務用於保證數據的一致性,它由一組相關的dml(增刪改)語句組成,該組的dml語句要么全部成功,要么全部失敗。
(注意:要引用支持事務的引擎如innodb)
mysql 事務的關鍵詞
start transaction => 開始一個事務
savepoint => 保存點
rollback to => 回滾到某個保存點
rollback => 回滾
commit => 提交
在mysql 控制台實現事務控制
-- 插入案例表 CREATE TABLE IF NOT EXISTS `account` ( id INT UNSIGNED NOT NULL PRIMARY KEY, name VARCHAR(30) NOT NULL DEFAULT '', money DECIMAL(10,2) UNSIGNED NOT NULL DEFAULT 0.0 )CHARSET=utf8 COLLATE=utf8_general_ci ENGINE=innodb; INSERT INTO `account` (id, name, money) VALUES (111111, 'jim', 20000),(222222, 'jack', 32000);
實現事務的步驟
-- 開始一個事務 START TRANSACTION -- 聲明一個保存點 SAVEPOINT first -- 執行增刪改操作 -- 進行回退的操作 ROLLBACK TO first -- 如果操作完,沒有問題,那么就可以正式提交 COMMIT
注意:當開啟事務的時候系統自動設置了一個匿名的保存點,當需要回退的時候只需要用rollback就可以了,如果設置了多個保存點,進行回退的時候,當退到前面的保存點時,那么這個保存點后面的保存點就消失了
17、mysql 視圖的增刪查改
(1) 創建視圖
create view 視圖名 as select 語句;
(2) 視圖的顯示
show create view 視圖名;
(3) 視圖的修改
alter view 視圖名 as 新的select 語句 ;
(4) 視圖的刪除
drop view 視圖名1, 視圖名2;
視圖案例說明
l 以emp表為例
只讓人查詢emp的名稱,job, 其它的信息不能查詢? 這時我們就可以創建視圖來解決這個問題 。
(1) 創建視圖
create view myview as select ename, job from emp;
(2) 使用視圖和使用一個普通表示一樣樣的.

(3) 對視圖或者表的dml操作,會相互的影響
在視圖中所有的操作可以和正常的表一樣進行操作,如果要查看是否是視圖表可以用show create table `視圖表`
查看數據庫中都有哪些視圖用語句:show table status where comment='view'
例子=》 創建一個test的視圖
CREATE VIEW `test` AS SELECT `account`.`name`, `account`.`money` FROM `account` WHERE `account`.`money`= (SELECT MAX(`money`) FROM `account`);
使用視圖的好處
1.安全性
一些數據表有着重要的信息。有些字段是保密的,不能讓用戶直接看到。這時就可以創建一個視圖,在這張視圖中只保留一部分字段。這樣,用戶就可以查詢自己需要的字段,不能查看保密的字段。
2.性能提升
關系數據庫的數據常常會分表存儲,使用外鍵建立這些表的之間關系。這時,數據庫查詢通常會用到連接(JOIN)。這樣做不但麻煩,效率相對也比較低。如果建立一個視圖,將相關的表和字段組合在一起,就可以避免使用JOIN查詢數據。
3.靈活性提升
如果系統中有一張舊的表,這張表由於設計的問題,即將被廢棄。然而,很多應用都是基於這張表,不易修改。這時就可以建立一張視圖,視圖中的數據直接映射到新建的表。這樣,就可以少做很多改動,也達到了升級數據表的目的.
