MySQL數據庫(三)

MySQL數據庫(一):
https://blog.csdn.net/Veer_c/article/details/103844059
MySQL數據庫(二):
https://blog.csdn.net/Veer_c/article/details/103844537
MySQL數據庫(三):
https://blog.csdn.net/Veer_c/article/details/103844739

數據庫的三大範式

-- 第一大範式:要求表中的每一個字段都是一個獨立的不可拆分的字段
-- student表
-- id   姓名(曾用名|現用名)     年齡
-- 1    張翔|張含               30
-- 2    王勇|張剛               40
-- 需求:查詢曾用名中姓張的學生
-- select * from student where name like '張%'-- 爲了遵守第一大範式,我們可以將上面的student表進行修改
-- id   oldName   nowName    age
-- 1    張翔      張晗        30
-- 2    王勇      張剛        40
-- 第二大範式:一張表只能表達一個意思
-- student
-- id     name     age    商品id(商品id)
-- 1      郭德綱   40     1
-- 爲了滿足第二大範式,我們在這裏必須重新創建一個商品表
-- product表
-- 商品id     商品名稱
-- 1          紙尿褲
-- 2          刮鬍刀
-- student表
-- id    name    age
-- 第三大範式:要求表中的每一個字段只能和主鍵有決定性的關係
-- 員工表,這樣做的話不滿足第三大範式
-- 員工id     姓名      部門id      部門名稱
-- 1          郭德綱     1          軟件開發部
-- 2          岳雲鵬     2          軟件維護部
-- 3          劉德華     3          後勤部
-- 上面的表結構不滿足第三大範式,我們對其進行改造,拆分成兩張表
-- 員工表
-- id    name  deptId
-- 部門表
-- id   deptName
-- 當我們降低了數據冗餘之後,就會形成多張表,在我們進行查詢數據的時候,我們是一張表查詢數據快呢?
-- 還是多張表查詢數據快呢?
-- 結論:存儲空間和你的查詢效率之間是一個矛盾的東西,當你降低了數據的冗餘度的時候你的查詢效率就會降低
-- 當數據的存儲空間佔用的比較大的時候,我們不關心數據冗餘這個問題的時候,但是查詢效率比較高

多表查詢

1.交叉連接查詢

 需求:查詢每一個員工的姓名以及對應的部門名稱
-- 預計結果:
-- 姓名    部門名稱
-- 華仔    軟件開發部
-- 郭德綱  軟件維護部
SELECT NAME,deptName 
FROM employee,dept;

分析:實際出現的結果和我們的預想不一樣,實際結果是我們每一個成員都會對應出現每一一部門名稱,這個就是因爲沒有添加多張表的連接條件
出現的結果俗稱笛卡爾乘積,計算公式:每個成員的name字段 乘以 部門表的deptName字段;
多表查詢的條件:
(1):確定需要查詢那些表
(2):確定需要查詢那些字段
(3):需要足夠的連接條件(連接條件的數據量-1)

2.內連接(查詢 用的最多)
查詢時,只有滿足鏈接條件的結果才能顯示出來
需求:查詢員工對應的部門名稱

SELECT e.name,d.deptName
-- 需要查詢的表
FROM employee e,dept d
-- 連接條件
WHERE e.deptId=d.id;
-- 內連接另一種寫法
SELECT NAME,deptName
FROM employee e
INNER JOIN dept d
ON e.deptId=d.id;

3.左外鏈接
優先顯示左表,滿足連接條件就給予顯示,如果不滿足,則顯示結果爲null,LEFT OUTER JOIN 左邊的表就稱之爲左表,右邊的表的爲右表。
需求:查詢員工對應的部門名稱。

SELECT deptName,NAME
FROM dept d
LEFT OUTER JOIN employee e
ON e.deptId=d.id;

**4.右外連接 **
優先顯示右表,如果滿足條件就顯示滿足的結果,不滿足就顯示null,RIGHTER OUTER 左邊的爲左表,右邊的爲右表
需求:查詢員工對應的部門名稱

SELECT deptName,NAME
FROM employee e
RIGHT OUTER JOIN dept d
ON e.deptId=d.id;

5.自連接查詢
需求:給員工表插入bossId這個字段,每一個員工對應一個老闆,查詢每個員工老闆的名字。

ALTER TABLE employee ADD COLUMN bossId INT;
SELECT e.name,b.name   
FROM employee e,employee b
WHERE e.bossId=b.id;
只能查詢出滿足條件的結果

使用內連接的時候:我們本質上使用一張表,爲了滿足鏈接條件,我們會虛擬出來一張表, 即上述代碼的 employee b 。
利用左外鏈接改造上述代碼:

SELECT e.name,b.name
FROM employee e
LEFT OUTER JOIN employee b
ON e.bossId=b.id;

存儲過程(類似於Java中的方法)

存儲過程:多個sql語句組成的具有一定邏輯的語句,即sql編程。
存儲過程的特點:
1.保存在mysql數據庫的服務端
2.我們可以直接在客戶端發送指令,去調用我們在服務端的存儲過程
3.存儲過程的移植性非常差

當我們需要程序一個員工的信息的時候,我們可以:
SELECT * FROM employee WHERE id=2;
SELECT * FROM employee WHERE id=3;
SELECT * FROM employee WHERE id=4;
這樣顯非常麻煩 ,於是我們可以將上述過程抽取成爲一個存儲過程,然後再去調用它

1.存儲過程的語法
	-- delimiter $  -- 聲明一個結束符
	-- create procedure pro_Test(輸入或者輸出參數)
	-- begin
	-- 帶有邏輯的sql語句
	-- end$
	-- 調用存儲過程:
	-- call pro_Test(實參);
	-- 存儲過程的輸入輸出參數如何表示呢?
	-- in 輸入參數的變量名稱 類型
	-- out 輸出參數的名稱 類型
	-- inout 輸入輸出參數名稱 類型
2.創建一個帶有輸出參數的存儲過程,並調用
	DELIMITER $
	CREATE PROCEDURE pro_QueryEmpById(IN eId INT)
	BEGIN
	SELECT * FROM employee WHERE id=eId;
	END$
	-- 調用上面的帶有輸入參數的存儲過程
	-- 需求,查詢id爲4的員工信息
	CALL pro_QueryEmpById(4);
3.當我們在調用一個輸出參數的存儲過程的時候,總會有一個返回值的,我們應該利用什麼來接受這個返回值,數據庫中有哪些變量可以供我們使用?
	-- 1.全局變量(mysql數據庫的系統變量):隨着mysql數據庫的啓動而存在,隨着mysql數據庫的關閉二消失
	-- 查看mysql數據庫的全局變量
	SHOW VARIABLES;
	-- 查看mysql數據庫中全部變量和字符相關的
	SHOW VARIABLES LIKE 'character%';
	-- 如何去查看mysql數據庫的全局變量
	-- select @@+全局變量名
	-- 如何去改變數據庫的全局變量
	-- set @@+全局變量=值
	SELECT @@character_set_client;
	SET @@character_set_client='utf8';
	-- 2.會話變量:存在於某一次會話中,隨着會話的結束而消失
	-- 如何去查看一個會話變量
	-- select @+變量名 
	-- 給會話變量設置值
	-- set @變量名=值
	SET @n='hello';
	SELECT @n;
	-- 3.局部變量:位於存儲過程中,隨着存儲過程而存在,隨着存儲過程的調用完畢二消失
	-- 給局部變量設置值
	-- set 局部變量=-- 查看局部變量
	-- select 局部變量
4.創建一個帶有輸出參數的存儲過程
	DELIMITER $
	CREATE PROCEDURE pro_TestOut(OUT str VARCHAR(20))
	BEGIN
	-- 給輸出參數賦值
	SET str='我是輸出參數';
	END$
	在調用這個存儲過程時,它會返回一個字符串值
	我們應該來定義一個回話變量,用來接受這個值
	CALL pro_TestOut(@nn)
	SELECT @nn;
5.創建一個帶有判斷的存儲過程
	-- 需求: 輸入一個num整數,num=1 ,輸出‘星期一’,num=2,輸出‘星期二’,
	-- num=3,輸出‘星期三’,否則,輸出‘錯誤參數’
	DELIMITER $
	CREATE PROCEDURE pro_TestDay(IN num INT,OUT d VARCHAR(20))
	BEGIN
	    IF num=1 THEN
	        SET d='星期一';
	    ELSEIF num=2 THEN
	        SET d='星期二';
	    ELSEIF num=3 THEN
	        SET d='星期三';
	    ELSE 
	        SET d='參數錯誤';
	    END IF;
	END$
	-- 調用上面的這個帶有輸入和輸出參數的存儲過程
	CALL pro_TestDay(4,@d);
	SELECT @d;
6.創建一個帶有循環過程的存儲過程
	-- 需求: 輸入一個num,計算從1到num的總和。
	DELIMITER $
	CREATE PROCEDURE pro_TestSum(IN num INT,OUT score INT)
	BEGIN
	    DECLARE i INT DEFAULT 1;
	    DECLARE res INT DEFAULT 0;
	    WHILE i<=num DO
	    SET res=res+i;
	    SET i=i+1;
	    END WHILE;
	    -- 將局部變量res的值賦值給score
	    SET score=res;
	END$
	-- 調用上面的存儲過程
	CALL pro_TestSum(200,@score);
	SELECT @score;
7.攜帶數據庫的數據給輸出參數(into),本質上就是把一個給另一個參數的賦值過程
	-- 需求: 傳入員工id,查詢對應的員工,輸出員工姓名
	DELIMITER $
	CREATE PROCEDURE pro_QueryNameById(IN eId INT,OUT eName VARCHAR(20))
	BEGIN
	SELECT NAME INTO eName FROM employee WHERE id=eId;
	END$
	-- 調用這個存儲過程
	CALL pro_QueryNameById(2,@eName);
	SELECT @eName;
8.刪除存儲過程:drop + 存儲過程名
	DROP PROCEDURE pro_QueryEmpById;

觸發器

當我們在向一張表中,插入,刪除,修改數據的時候,我們可以將這些操作記錄在一張表上,這就需要觸發器。

-- 創建一個日誌表
CREATE TABLE empLog(
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(20)
);
-- 創建一個觸發器,當往員工表中插入一條數據的時候,自動往日誌表中添加一條插入的記錄
CREATE TRIGGER tri_empInsert AFTER INSERT ON employee FOR EACH ROW 
INSERT INTO empLog(content) VALUES('員工表中被插入一條數據');
-- 給員工表中插入一條數據
INSERT INTO employee(NAME) VALUES('周華健');
-- 創建一個觸發器,當往員工表中修改一條數據的時候,往日指標中添加一條記錄
CREATE TRIGGER tri_empUpdate AFTER UPDATE ON employee FOR EACH ROW 
INSERT INTO empLog(content) VALUES('員工表中被修改一條數據');
-- 修改員工表中的一條數據
UPDATE employee SET NAME='成龍' WHERE id=7;
-- 創建一個觸發器,當刪除員工表的一條數據的時候,給日誌表中添加一天刪除的記錄
CREATE TRIGGER tri_empDelete AFTER DELETE ON employee FOR EACH ROW 
INSERT INTO empLog(content) VALUES('員工表中被刪除一條數據');
-- 刪除周華健
DELETE FROM employee WHERE id=7;
SELECT * FROM empLog;
SELECT * FROM employee;

注意:每個觸發器的功能是不一樣的,我們必須用不同的觸發器來記錄不同的操作!

數據庫的權限問題

root用戶:
是我們的超級管理員,擁有所有的權限管理,它可以對我們的(數據庫,表,數據)進行增刪改查。

1.查詢mysql數據庫的用戶信息
	SELECT * FROM USER;
2.當我們查看我們的用戶密碼的時候,發現它並不是我們原來的密碼,這個是因爲數據庫對我們的密碼使用了MD5單向加密算法 。
	加密函數是 :password();
	SELECT PASSWORD('root');
3.如何修改我們的密碼信息
	-- 更改root這個用戶名的密碼‘123456’
	UPDATE USER SET PASSWORD=PASSWORD('root') WHERE USER='root';
4. 我們也可以爲一些用戶分配不同的權限,方便管理我們的數據庫
	-- 創建一個新的用戶,並且給新的用戶一些特有的權限呢?
	GRANT SELECT ON day20.employee TO 'eric'@'localhost' IDENTIFIED BY '123456';

注意:第一個password是一個定義的一個變量,第二個password是我門的password函數

MySQL數據庫(一):
https://blog.csdn.net/Veer_c/article/details/103844059
MySQL數據庫(二):
https://blog.csdn.net/Veer_c/article/details/103844537
MySQL數據庫(三):
https://blog.csdn.net/Veer_c/article/details/103844739

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章