前言:當一個大型系統在建立時,會發現,數據庫雖然可以存儲海量的數據,可是一旦數據關系復雜,比如學生表(學號、姓名、年齡),學生成績表(學號、科目、成績),如需要姓名、科目、成績組成關系,這樣的情況我們選擇創建一個新表是非常浪費資源的動作,為此,視圖誕生了!
本系列:demo下載
(一)MySQL優化筆記(一)--庫與表基本操作以及數據增刪改
(二)MySQL優化筆記(二)--查找優化(1)(非索引設計)
(三)MySQL優化筆記(二)--查找優化(2)(外連接、多表聯合查詢以及查詢注意點)
(四) MySQL優化筆記(三)--索引的使用、原理和設計優化
(五) MySQL優化筆記(四)--表的設計與優化(單表、多表)
(六)MySQL優化筆記(五)--數據庫存儲引擎
(七)MySQL優化筆記(六)--存儲過程和存儲函數
(八)MySQL優化筆記(七)--視圖應用詳解
(九) MySQL優化筆記(八)--鎖機制超詳細解析(鎖分類、事務并發、引擎并發控制)
文章結構:(1)視圖概述;(2)視圖的操作;(3)視圖使用注意點。
一、視圖概述:
(1)什么是視圖?
視圖是基于 SQL 語句的結果集的可視化的表。
視圖包含行和列,就像一個真實的表。視圖中的字段就是來自一個或多個數據庫中的真實的表中的字段。視圖并不在數據庫中以存儲的數據值集形式存在,而是存在于實際引用的數據庫表中,視圖的構成可以是單表查詢,多表聯合查詢,分組查詢以及計算(表達式)查詢等。行和列數據來自由定義視圖的查詢所引用的表,并且在引用視圖時動態生成。
(2)視圖的優點:
1)簡化用戶操作:
視圖不僅可以簡化用戶對數據的理解,也可以簡化他們的操作。
視圖機制使用戶可以將注意力集中在所關心地數據上。如果這些數據不是直接來自基本表,則可以通過定義視圖,使數據庫看起來結構簡單、清晰,并且可以簡化用戶的的數據查詢操作。
2)用戶能以多種角度看待同一數據:
使不同的用戶以不同的方式看待同一數據,當許多不同種類的用戶共享同一個數據庫時,這種靈活性是非常必要的。
3)對重構數據庫提供了一定程度的邏輯獨立性:
視圖可以使應用程序和數據庫表在一定程度上獨立。
數據的物理獨立性是指用戶的應用程序不依賴于數據庫的物理結構。數據的邏輯獨立性是指當數據庫重構造時,如增加新的關系或對原有的關系增加新的字段,用戶的應用程序不會受影響。層次數據庫和網狀數據庫一般能較好地支持數據的物理獨立性,而對于邏輯獨立性則不能完全的支持。
4)安全性,對機密數據提供安全保護:
通過視圖用戶只能查詢和修改他們所能見到的數據。
(3)視圖的缺點:
1)性能差:
把視圖查詢轉化成對基本表的查詢,如果這個視圖是由一個復雜的多表查詢所定義,那么,即使是視圖的一個簡單查詢,sql server也要把它變成一個復雜的結合體,需要花費一定的時間。
2)修改限制:
當用戶試圖修改試圖的某些信息時,數據庫必須把它轉化為對基本表的某些信息的修改,對于簡單的試圖來說,這是很方便的,但是,對于比較復雜的試圖,可能是不可修改的。
(4)視圖使用場景:
1) 權限控制的時候。當用戶需要查詢未授權的數據表且又需要部分數據表的部分列進行邏輯處理,不希望用戶訪問表中某些含敏感信息的列。
2)關鍵信息來源于多個復雜關聯表,可以創建視圖提取我們需要的信息,簡化操作;
(5)視圖的分類:
1)關系視圖:
它屬于數據庫對象的一種,也就是最常見的一種關聯查詢;
2)內嵌視圖:
它不屬于任何用戶,也不是對象,創建方式與普通視圖完全不同,不具有可復用性,不能通過數據字典獲取數據;
3)對象視圖:
它是基于表對象類型的視圖,特性是繼承、封裝等可根據需要構建對象類型封裝復雜查詢(官方:為了迎合對象類型而重建數據表是不實現的);
4)物化視圖:
它主要用于數據庫的容災(備份),實體化的視圖可存儲和查詢,通過DBLink連接在主數據庫物化視圖中復制,當主庫異常備庫接管實現容災;
二、視圖的操作:
使用里面多對多關系的例子
準備數據:
//課程表
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `course` VALUES ('1', 'java', 'JAVA課程');
INSERT INTO `course` VALUES ('2', '數學', '數學課程');
INSERT INTO `course` VALUES ('3', '英語', '英語課程');
//學生表:
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`account` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES ('1', '123', '小符', '中國');
INSERT INTO `student` VALUES ('2', '456', '小張', '美國');
INSERT INTO `student` VALUES ('3', '789', '小王', '英國');
//多對多關系必須一張中間表:
DROP TABLE IF EXISTS `student_course`;
CREATE TABLE `student_course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`studentid` bigint(20) NOT NULL,
`courseid` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
INSERT INTO `student_course` VALUES ('1', '1', '2');
INSERT INTO `student_course` VALUES ('2', '1', '3');
INSERT INTO `student_course` VALUES ('3', '2', '1');
INSERT INTO `student_course` VALUES ('4', '2', '2');
INSERT INTO `student_course` VALUES ('5', '2', '3');
INSERT INTO `student_course` VALUES ('6', '3', '2');
(1)創建視圖:
1. helloworld視圖:
2. 業務中的復雜視圖:
先明確視圖需求:我們要查詢出一個人的所有課程信息,并且以一門課程一條記錄顯示(也就是這種復雜的需求要用視圖而已)?;維QL如下:
SELECT
uc.id AS id,
s.name AS name,
c.name AS coursename
FROM
student s
LEFT JOIN student_course uc ON (s.id = uc.studentid)
LEFT JOIN course c ON (uc.courseid = c.id)
WHERE
s.`name` = '小符'
然后創建視圖:
DROP VIEW
IF EXISTS `view_student_course`;
CREATE ALGORITHM = UNDEFINED
DEFINER = `root`@`localhost`
SQL SECURITY DEFINER
VIEW `view_student_course` AS (
SELECT
uc.id AS id,
s.name AS name,
c.name AS coursename
FROM
student s
LEFT JOIN student_course uc ON (s.id = uc.studentid)
LEFT JOIN course c ON (uc.courseid = c.id)
);
測試視圖:
SELECT
test.name,
test.coursename
FROM
view_student_course test
WHERE
test.name = '小符'
這里寫圖片描述
MySQL的視圖功能拓展:
ALGORITHM=UNDEFINED:指定視圖的處理算法;
DEFINER=root
@localhost
:指定視圖創建者;
SQL SECURITY DEFINER:指定視圖查詢數據時的安全驗證方式;
(2)修改視圖SQL:
已經創建的視圖,有時會需要修改其查詢字段或查詢條件
ALTER VIEW 視圖名 AS SELECT 查詢語句;
到頭來還是要控制SQL,不過窗口話了,我們調用面向的是視圖,不是面向原始數據表了。
(3)增刪改視圖數據:
先嘗試在我們的視圖上修改數據:結果如下:
update view_student_course set name='test',coursename='前端' where id=3;
這里寫圖片描述
因為不能在一張由多張關聯表連接而成的視圖上做同時修改兩張表的操作;
那么,我們在視圖上可以做哪些視圖數據操作呢??
在這之前,我們必須明確!增刪改最終都是修改到基礎表。
1)視圖與表是一對一關系情況:如果沒有其它約束(如視圖中沒有的字段,在基本表中是必填字段情況),是可以進行增刪改數據操作;
//注意是view_helloworld 視圖
//插入
INSERT INTO view_helloworld VALUES ('5', '321', '小柱', '中國');
//更新:
UPDATE view_helloworld SET name = '小成' WHERE id = 5;
//刪除
DELETE FROM view_helloworld WHERE name = '小柱';
2)視圖與表是一對多關系情況:如果只修改一張表的數據,且沒有其它約束(如視圖中沒有的字段,在基本表中是必填字段情況),是可以進行改數據操作。而且,只能做修改操作。
update view_student_course set coursename='Java' where id=1;
上面的具體是修改怎樣的數據呢?我們來看一下原來的數據是這樣:
這里寫圖片描述
執行修改語句后:可以看到,修改的都是叫數學的課程。原因是??
這里寫圖片描述
where id=1指向的是視圖第一條記錄,而視圖第一條中coursename是數學,指向的是course表name叫數學的記錄。也就是說最終修改的是course表的記錄中name叫數學的記錄,把數學改成了Java。--也就是修改了課程名稱。所以,最終課程名稱原來叫數學的都變成了Java。
這里寫圖片描述
下面這些操作是不可以的:
delete from view_student_course where id=3;
insert into view_student_course (username, coursename) VALUES('2','3');
(4)刪除視圖:
與刪除表的語法類似:
DROP VIEW 視圖名;
(5)查看視圖狀態:
DESCRIBE view_helloworld
分別是是字段,字段類型,允許空,索引,補充
這里寫圖片描述
show CREATE view view_helloworld
分別是視圖名,創建語句,字符編碼
這里寫圖片描述
三、視圖使用注意點:
(1)修改操作時要非常非常小心,不然不經意間你已經修改了基本表里的多條數據;
(2)視圖中的查詢語句性能要調到最優;
(3)雖說上面講到,視圖有些是可以修改的。但是更多的是禁止修改視圖。
對于可更新的視圖,在視圖中的行和基表中的行之間必須具有一對一的關系或者特殊的沒有約束的一對多字段。還有一些特定的其他結構,這類結構會使得視圖不可更新。
不可更改的情況如下:視圖中含有以下的都不可被修改了。
(一)聚合函數(SUM(), MIN(), MAX(), COUNT()等)。
(二)DISTINCT。如下錯誤。
這里寫圖片描述