為了簡化複雜SQL語句編寫以及提高資料庫安全性,MySQL資料庫提供了視圖特性。視圖是一張虛擬表,不以資料庫中儲存的數據值形式存在。在開發中,開發者往往只對某些特定數據和所負責的特定任務感興趣,只需要看到這一部分數據即可。這時候就可以用到視圖來完成。 ...
1 引言
為了簡化複雜SQL語句編寫,以及提高資料庫安全性,MySQL資料庫視圖特性。視圖是一張虛擬表,不在資料庫中以儲存的數據值形式存在。在開發中,開發者往往只對某些特定數據和所負責的特定任務感興趣,只需要看到這一部分數據即可。這時候就可以用到視圖來完成。
2 視圖簡介
2.1 什麼是視圖
資料庫中的視圖是一個虛擬表,但它同真實表一樣,包含一系列帶有名稱的行和列數據。行和列數據來自由定義視圖查詢所引用的表,並且在應用視圖時動態生成。另外,視圖還可以在已經存在的視圖的基礎上定義。
視圖一經定義變存儲在資料庫中,與其相對應的數據並沒有像表那樣在資料庫中再存儲一份,通過視圖看到的數據只是存儲在基本表中的數據。對視圖的操作與對標的操作一樣,可以對其進行查詢、修改和刪除。當對通過視圖看到的數據進行修改時,相應的基本表中的數據也會發生變化;同時,若是基本表的數據發生變化,則這種變化也會自動地反映在視圖上。
2.2 視圖的作用
與直接從真實數據表中進行數據操作相比,視圖具有以下的有點:
(1)簡單化
看到的就是需要的。視圖不僅可以簡化用戶對數據的理解,也可以簡化他們的操作。那些被經常使用的查詢可以被定義為視圖,從而用戶不必為以後的每一次操作指定全部的條件。
(2)安全性
通過視圖用戶只能查詢和修改他們所能看到的數據。資料庫中的其他數據則既看不見也娶不到。資料庫授權命令可以使每個用戶對資料庫的檢索限制到特定的資料庫對象上,但不能限制到特定行和特定列上。但通過視圖,用戶可以被限制到資料庫的行列級別的子集上。
(3)邏輯數據獨立性
視圖可以幫助用戶屏蔽真實表結構變化帶來的影響。
3 創建視圖
視圖包含了SELECT查詢結果,因此屬兔的創建基於SELECT語句和已存在的資料庫,視圖可以建立在一張表上,也可以建立在多張表上。
本篇博文中,所有操作基於以下兩張數據表(emp表、dept表)進行:
emp表:
emp表sql語句如下:
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for emp -- ---------------------------- DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` ( `empno` int(4) NOT NULL, `ename` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, `job` varchar(9) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, `mgr` int(4) NULL DEFAULT NULL, `hiredate` date NULL DEFAULT NULL, `sal` float(7, 2) NULL DEFAULT NULL, `comm` float(7, 2) NULL DEFAULT NULL, `deptno` int(2) NULL DEFAULT NULL, PRIMARY KEY (`empno`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of emp -- ---------------------------- INSERT INTO `emp` VALUES (7369, 'SMITH', 'CLERK', 7902, '1998-12-17', 800.00, NULL, 20); INSERT INTO `emp` VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600.00, 300.00, 30); INSERT INTO `emp` VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250.00, 500.00, 30); INSERT INTO `emp` VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975.00, NULL, 20); INSERT INTO `emp` VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250.00, 1400.00, 30); INSERT INTO `emp` VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850.00, NULL, 30); INSERT INTO `emp` VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450.00, NULL, 10); INSERT INTO `emp` VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1981-11-17', 3000.00, NULL, 20); INSERT INTO `emp` VALUES (7839, 'KING', 'PRESIDENT', NULL, '1981-11-17', 5000.00, NULL, 10); INSERT INTO `emp` VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500.00, 0.00, 30); INSERT INTO `emp` VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100.00, NULL, 20); INSERT INTO `emp` VALUES (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950.00, NULL, 30); INSERT INTO `emp` VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000.00, NULL, 20); INSERT INTO `emp` VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-02-23', 1300.00, NULL, 10); INSERT INTO `emp` VALUES (8888, 'CHB', 'CLERK', 7369, '2018-12-10', 8000.00, 100.00, NULL); SET FOREIGN_KEY_CHECKS = 1;emp表SQL語句
dept表:
dept表SQL語句如下:
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for dept -- ---------------------------- DROP TABLE IF EXISTS `dept`; CREATE TABLE `dept` ( `deptno` int(2) NOT NULL, `dname` varchar(14) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, `loc` varchar(13) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, PRIMARY KEY (`deptno`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of dept -- ---------------------------- INSERT INTO `dept` VALUES (10, 'ACCOUNTING', 'NEW YORK'); INSERT INTO `dept` VALUES (20, 'RESEARCH', 'DALLAS'); INSERT INTO `dept` VALUES (30, 'SALES', 'CHICAGO'); INSERT INTO `dept` VALUES (40, 'OPERATIONS', 'BOSTON'); SET FOREIGN_KEY_CHECKS = 1;demp表SQL語句
3.1 創建視圖的基本格式
創建視圖的基本格式如下:
CREATE VIEW <視圖名稱> [(column_list)] AS SELECT語句;
雖然還有更加完整的詳細語法格式,但一般情況下,使用上述基本格式就夠用了。
(1)基於單個數據表建立視圖
在使用emp表時,如果需要查詢查詢empno(編號)、ename(姓名)、job(職位)、hiredate(雇用日期)、sal(月薪)等欄位,並指定中文拼音別名,SQL語句如下:
select empno bianhao , ename xinmin, job zhiwei, hiredate guyongriqi, sal yuexin from emp;
如果需要頻繁得進行該語句查詢,那麼每次都要重寫這一行語句。使用視圖可以簡化操作,對empno、ename、job、hiredate、sal創建視圖:
create view view_01 as select empno , ename , job , hiredate , sal from emp;
執行完上述語句即可創建名為view_01的視圖,如果你是通過Navicat等圖形界面工具創建視圖,在左側視圖欄下可找到view_01視圖。
在剛創建好的view_01視圖進行查詢:
select * from view_01 ;
查詢結果如下:
可以發現,我們並未指定查詢的欄位,但查詢效果卻與直接在真實數據表上指定欄位查詢效果一樣。但view_01視圖並未實現欄位別名,繼續創建一個view_02為每個列添加別名:
create view view_02 (bianhao , xinmin , zhiwei , guyongriqi , yuexin) as select empno , ename , job , hiredate , sal from emp;
查看view_02:
select * from view_02 ;
結果如下:
可以看到,每一個列的列名都是我們在創建視圖時自己重新指定的。
(2)創建基於多個表上視圖
創建一個視圖,視圖中包含每個員工編號(empno)、姓名(ename)、職位(job)、領導編號(mgr)、領導姓名(empno)、部門名稱(dname)、部門位置(loc),在真實數據表中查詢語句如下:
select e1.empno bianhao, e1.ename xingming, e1.job zhiwei, e1.mgr lindaobianhao, e2.ename lindaoxingming, d.dname bumenmingchen, d.loc bumenweizhi from emp e1 , emp e2 , dept d where e1.mgr=e2.empno and e1.deptno=d.deptno ;
創建視圖:
create view view_03 as select e1.empno bianhao, e1.ename xingming, e1.job zhiwei, e1.mgr lindaobianhao, e2.ename lindaoxingming,
d.dname bumenmingchen, d.loc bumenweizhi from emp e1 , emp e2 , dept d where e1.mgr=e2.empno and e1.deptno=d.deptno ;
對剛建立的view_03視圖進行查詢:
select * from view_03 ;
查詢結果如下:
可以發現,在select中指定別名與在view視圖中指定別名效果是一樣的。
4 查看視圖
(1)查看視圖基本信息:describe 視圖名;
查看上一章節創建的視圖view_03的基本信息:
describe view_03 ;
describe一般情況下都寫成desc,兩者是完全等效的。
另外還可以通過“show create view 視圖名;”來查看視圖詳細信息。
(2)查看所有視圖
在MySQL中,information_schema資料庫下的views表中存儲了所有視圖的定義,通過對views表的查詢,可以查看資料庫中說喲視圖的詳細信息,查詢語句如下:
select * FROM information_schema.views ;
部分查詢結果如下所示:
5 修改視圖
(1)使用create or replace view語句修改視圖
create or replace view語句從字面上也可以理解:既可以創建視圖,也可以修改視圖(存在的話就修改,不存在就創建)。create or replace view語句的語法結構與創建視圖的create語句語法結構是完全一樣的。
修改上文中創建的視圖view_01,添加一個部門編號欄位(deptno):
create or replace view view_02 (bianhao , xinmin , zhiwei , guyongriqi , yuexin , bumenbiaohao) as select empno , ename , job , hiredate , sal ,
deptno from emp;
再次查詢view_02,發現確實多了部門編號這一列:
select * from view_02 ;
(2)使用alter語句修改視圖
alter語句是MySQL提供的另一種修改視圖的方法,其語法結果與create or replace語句也是基本一樣的。
繼續修改視圖view_02,添加一個獎金欄位(comm):
alter view view_02 (bianhao , xinmin , zhiwei , guyongriqi , yuexin , bumenbiaohao , jiangjin) as select empno , ename , job , hiredate , sal ,
deptno , comm from emp;
查看view_01視圖:
alter語句與create orreplace語句的區別是當視圖不存在是,alter語句會報錯。
6 更新視圖
更新視圖是指通過視圖來插入、更新、刪除表中的數據,因為視圖是一個虛擬表,其中是沒有數據的。通過視圖更新的時候都是轉到真實表上進行的。對視圖的更新操作也包括update、insert和delete。
(1)update
通過視圖將員工編號為7369的員工月薪改為1000,在更新前,其數據為:
select * from view_02 where bianhao=7369;
用update語句進行更新
update view_02 set yuexin=1000 where bianhao=7369;
再次通過視圖查看數據,發現數據確實已更新:
再看看真實表中數據有沒有更新:
select * from emp where empno=7369;
可以看出,真實表中的數據也一起更新了,說明對視圖的更新操作本質上是對真實表的更新。
(2)insert
先創建一個視圖view_04,該視圖結果與emp表一樣:
create view view_04 as select * from emp ;
使用insert語句向view_04視圖中插入一條數據:
insert into view_04 values(8002 , 'MARK' , 'CLERK' , 7902 , '1998-12-12' , 1100 , 20 ,500 ) ;
查看真實emp表中是否添加這麼一條數據:
select * from emp where empno =8002 ;
證明在視圖進行insert操作是可以添加數據到真實表的。但一般來說,視圖的表結構與視圖的表結構可能不一樣,若真實表中存在非空等約束,這通過視圖的insert操作就回失敗。所以,insert操作一般不會通過視圖來進行。
(3)delete
通過視圖刪除剛創建的empno為8002的記錄:
delete from view_04 where empno =8002 ;
查看真實表中數據是否刪除:
select * from emp where empno =8002 ;
返回的是一個空表,證明真實表中的這條記錄也已經被刪除了。
最後總結一下視圖的更新操作,當視圖中包含如下內容時,視圖的更新操作將不能被執行:
(1)視圖中不包含真實表中被定義為非空的列(視圖中沒有,但真實表中為非空約束)。
(2)在定義視圖的select語句後的欄位列表中使用了數學表達式。
(3)在定義視圖的select語句後的欄位列表中使用了聚合函數。
(4)在定義視圖的select語句中使用了distinct,union,top, group by,或having子句。
7 總結
本文是對MySQL數據中視圖的詳細總結,包括了對視圖概念、特性的介紹,然後通過實際示例展示了對視圖的增刪改查操作。