二十、二十一天MySql數據庫、jdbc
1 數據約束 1.1 簡介 給表添加數據約束,從而約束用戶操作表數據的行為。 1.2 默認值約束 註意: 當前沒有插入默認值字段的時候,默認值才會起作用 -- 1.1 默認值(default)CREATE TABLE test( NAME VARCHAR(20), gender VARCHAR(2) DEFAULT ‘男‘) INSERT INTO test(NAME) VALUES(‘張三‘);INSERT INTO test(NAME,gender) VALUES(‘張三‘,NULL); SELECT * FROM test; -- 需求:當不插入gender的時候,分配一個‘男’的默認值-- 註意: 1)當沒有插入gender字段的時候,分配一個默認值 1.3 非空約束 -- 1.2 非空(not null)CREATE TABLE test( NAME VARCHAR(20) NOT NULL, gender VARCHAR(2))-- 需求: name字段一定要有值(不能不插入數據,不能是null),這是給name添加非空約束-- 1)非空約束,不能不插入值INSERT INTO test(gender) VALUES(‘男‘); -- ERROR 1364 (HY000): Field ‘NAME‘ doesn‘t have a default value -- 2)非空約束,不能插入nullINSERT INTO test(NAME,gender) VALUES(NULL,‘男‘); -- ERROR 1048 (23000): Column ‘NAME‘ cannot be null 1.4 唯一約束 CREATE TABLE test( id INT UNIQUE, NAME VARCHAR(20))-- 需求: id的值不能出現重復值。這時就要給id添加一個唯一約束。INSERT INTO test(id,NAME) VALUES(1,‘張三‘);-- 1)不能插入重復的值INSERT INTO test(id,NAME) VALUES(1,‘李四‘); -- Duplicate entry ‘1‘ for key ‘id‘INSERT INTO test(id,NAME) VALUES(2,‘李四‘);-- 2)唯一約束,可以插入多個null。所以唯一約束不能約束nullINSERT INTO test(id,NAME) VALUES(NULL,‘王五‘);INSERT INTO test(id,NAME) VALUES(NULL,‘陳六‘); 1.5 主鍵約束 -- 1.4 主鍵約束(primary key)(唯一+非空)-- 註意:-- 1)通常情況下,我們會給每張表都會設置一個主鍵字段,用來標記記錄的唯一性-- 2)但是不建議把業務含義字段作為主鍵,因為隨著業務的變化,業務字段可能會出現重復。-- 3)建議給每張張獨立添加一個叫id的字段,把這個id字段設置成主鍵,用來作為記錄的唯一性。 -- 創建表給id字段施加主鍵CREATE TABLE test( id INT PRIMARY KEY, NAME VARCHAR(20)) -- 1)唯一性INSERT INTO test(id,NAME) VALUES(1,‘張三‘);INSERT INTO test(id,NAME) VALUES(1,‘張三‘); -- Duplicate entry ‘1‘ for key ‘PRIMARY‘ -- 2)非空性INSERT INTO test(id,NAME) VALUES(NULL,‘張三‘); -- ERROR 1048 (23000): Column ‘id‘ cannot be null 1.6 自增長約束(auto_increment) -- 1.5 自增長約束(auto_increment)-- 創建表給id字段添加主鍵自增長約束CREATE TABLE test( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20))-- 自增長約束:初始值為0,每次遞增1-- 需求:id的值不需要我們開發者管理,交給數據庫維護,這時給id添加自增長約束。INSERT INTO test(NAME) VALUES(‘張三‘);INSERT INTO test(NAME) VALUES(‘李四‘);INSERT INTO test(NAME) VALUES(‘王五‘); -- 刪除數據-- delete from test where id=2;-- 使用truncate table刪除數據的時候,可以把自增長的初始值置為0TRUNCATE TABLE test; SELECT * FROM test; 1.7 外鍵約束 外鍵約束:約束兩種表的情況 問題:什麽情況下會出現兩種表? 答案:員工表中出現部門名稱的冗余字段!!!! 如何解決部門名稱冗余問題? 答案:獨立設計一張部門表,把部門名稱放到部門表中,這是員工表只需要關聯部門的id即可!! 問題:當插入員工表的部門id的時候,可能會出現不存在的部門id!!這是非法數據!!!如何防止非法數據的插入? 答案:這是可以把員工表的部門id設置為外鍵約束。 當有了外鍵約束之後,操作數據的順序如下: 插入數據:先插入主表的數據,再插入副表數據 修改數據:先修改主表數據,再修改副表數據 刪除數據:先刪除副表數據,再刪除主表數據 -- 1.6 外鍵約束-- 外鍵作用: 約束兩種表的數據-- 問題: 約束哪種情況下的兩種表呢?-- 員工表CREATE TABLE employee( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), deptName VARCHAR(20)) INSERT INTO employee(NAME,deptName) VALUES(‘張三‘,‘軟件開發部‘);INSERT INTO employee(NAME,deptName) VALUES(‘李四‘,‘軟件維護部‘);INSERT INTO employee(NAME,deptName) VALUES(‘王五‘,‘軟件開發部‘);INSERT INTO employee(NAME,deptName) VALUES(‘陳六‘,‘軟件開發部‘); -- 問題:每次插入員工數據時,部門名稱數據會出現重復(冗余),如果數據出現冗余,那麽會浪費數據庫存儲空間。-- 如何解決部門名稱數據冗余的問題? 這時就可以設計一張獨立的 部門表,把部門名稱放到部門表中。 -- 員工表CREATE TABLE employee( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), deptId INT) -- 部門表CREATE TABLE dept( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20)) SELECT * FROM employee;SELECT * FROM dept; INSERT INTO dept(NAME) VALUES(‘軟件開發部‘);INSERT INTO dept(NAME) VALUES(‘軟件維護部‘);INSERT INTO employee(NAME,deptId) VALUES(‘陳六‘,1);INSERT INTO employee(NAME,deptId) VALUES(‘王五‘,1); INSERT INTO employee(NAME,deptId) VALUES(‘張三‘,3); -- 問題:在插入員工表的部門id的時候,插入了不存在的部門id,如何防止這種非法數據的插入,這時就添加外鍵約束了。 -- 添加外鍵約束(foreign key)-- 需求:deptId字段值來自於dept表的id字段的值,這時可以給deptId字段添加外鍵約束。-- 員工表(副表: 被別的表約束。外鍵設置在副表)CREATE TABLE employee( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), deptId INT, CONSTRAINT employee_dept_fk FOREIGN KEY(deptId) REFERENCES dept(id) -- 外鍵名稱 外鍵字段 參考 ) -- 部門表(主表:約束別人的表)CREATE TABLE dept( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20)) SELECT * FROM employee;SELECT * FROM dept; INSERT INTO employee(NAME,deptId) VALUES(‘陳六‘,1);INSERT INTO employee(NAME,deptId) VALUES(‘王五‘,1);-- 插入數據INSERT INTO employee(NAME,deptId) VALUES(‘張三‘,3); -- 違反外鍵約束:a foreign key constraint fails-- 修改數據UPDATE employee SET deptId=5 WHERE id=2; -- a foreign key constraint fails-- 刪除數據DELETE FROM dept WHERE id=1; -- a foreign key constraint fails -- 外鍵約束在什麽情況下,會其作用?-- 插入數據:當往副表插入了主表不存在的數據時,外鍵起作用-- 修改數據:當往副表修改為主表不存在的數據時,外鍵起作用-- 刪除數據: 副表中有關聯主表的數據的時候,當刪除主表數據,外鍵其作用 -- 當有了外鍵之後,應該如何管理數據呢?-- 插入數據: 先插入主表的數據,再插入副表數據-- 修改數據: 先修改主表數據,再修改副表數據UPDATE employee SET deptId=3 WHERE id=5;UPDATE dept SET id=3 WHERE id=2;-- 刪除數據:先刪除副表數據,再刪除主表數據DELETE FROM dept WHERE id=3;DELETE FROM employee WHERE deptId=3; 1.8 級聯技術 級聯:當有了外鍵的時候,我們希望修改或刪除數據的時候,修改或刪除了主表的數據,同時能夠影響副表的數據,這時就可以使用級聯。 CREATE TABLE employee( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), deptId INT, -- 添加級聯修改: ON UPDATE CASCADE -- 添加級聯刪除: ON DELETE CASCADE CONSTRAINT employee_dept_fk FOREIGN KEY(deptId) REFERENCES dept(id) ON UPDATE CASCADE ON DELETE CASCADE -- 外鍵名稱 外鍵字段 參考 ) 2 數據庫設計 2.1 引入 需求分析:原始需求 -> 業務需求 客戶 業務模型:客戶(姓名 登記時間郵箱 微信號) 需求設計: 業務模型(客戶業務模型): -》 抽取實體模型: classCustomer{name email weixin} 業務模型(客戶業務模型) -> 數據模型:設計數據庫表(customer表:字段) 2.2 數據庫設計的三大範式 第一範式: 要求表的每個字段必須獨立的不可分割的單元 學生表: student name --違反第一範式 張三|狗娃 王含|張小含 查詢:現用名中包含‘張’的學生 select* from student where name like ‘%張%‘; 學生表: student name old_name --符合第一範式 張三 狗娃 王含 張小含 第二範式:在第一範式的基礎上,要求表的除主鍵以外的字段都和主鍵有依賴關系的。 一張表應該只表達一個意思!!!! 員工表:employee 員工編號 員工姓名 部門名稱 訂單名稱 --違反第二範式 員工表:employee 員工編號 員工姓名 部門名稱 --符合第二範式 訂單表: 訂單編號 訂單名稱 第三範式:在第二範式基礎上,要求表的除主鍵外的字段都只能和主鍵有直接決定的依賴關系。 員工表:employee --不符合第三範式(出現數據冗余) 員工編號 員工姓名 部門編號部門名稱 1 張三 1 軟件開發部 2 李四 1 軟件開發部 員工表:employee --符合第三範式(降低數據冗余) 員工編號 員工姓名 部門編號 1 張三 1 2 李四 1 部門表: dept 部門編號 部門名稱 1 軟件開發部 數據庫存儲空間 和數據查詢效率 3 多表查詢 -- 1.1 交叉連接查詢(笛卡爾乘積: 4*3=12,產生笛卡爾積的原因是沒有足夠的連接條件)-- 需求: 員工及其部門SELECT employee.name,dept.name FROM employee,dept; -- 多表查詢的步驟: 1)確定查詢哪些表 2)確定查詢哪些字段 3)確定連接條件(規則: 表數量-1)-- 內連接效果:只有滿足連接條件的數據才會顯示出來-- 1.2內連接查詢(使用最多)SELECT e.name,d.name FROM employee e,dept d WHERE e.deptId=d.id; -- 另一種語法SELECT e.name,d.name FROM employee e INNER JOIN dept d ON e.deptId=d.id; -- 1.3 左外連接查詢(其次)-- 需求: 查詢部門及其部門的員工(部門全部顯示)-- 左外連接查詢效果: 左表(部門表)的數據全部顯示,右表(員工)的數據當滿足連接條件的時候, -- 就顯示滿足條件的的數據,但是如果不滿足連接條件,則顯示null-- 預期結果: -- 軟件開發部 張三 -- 軟件開發部 王五 -- 軟件維護部 李四 -- 軟件維護部 陳六 -- 秘書部 nullSELECT d.name,e.name FROM dept d LEFT OUTER JOIN employee e ON d.id=e.deptId; -- 1.4 右外連接查詢-- 右外連接查詢效果: 右表(部門表)的數據全部顯示,左表(員工)的數據當滿足連接條件的時候, -- 就顯示滿足條件的數據,但是如果不滿足連接條件,則顯示nullSELECT d.name,e.name FROM employee e RIGHT OUTER JOIN dept d ON d.id=e.deptId; -- 1.5 自連接查詢-- 需求: 查詢員工姓名及其上司姓名(沒有上司的員工也顯示)-- 預期結果: 員工 上司 -- 張三 null -- 李四 張三 -- 王五 李四 -- 陳六 王五SELECT e.name AS ‘員工‘,b.name AS ‘上司‘ FROM employee e LEFT OUTER JOIN employee b ON e.bossId=b.id; 4 mysql存儲過程 4.1 引入 存儲過程,其實就是帶邏輯的(多個)sql語句。也是sql編程。 4.2 存儲過程的特點 1)存儲過程保存到數據庫服務器端,通過數據庫客戶端工具調用存儲過程 2)存儲過程的效率會非常高!因為存儲過程是在數據庫服務器端執行。 3)存儲過程的移植性非常差的! 4.3 存儲過程語法 創建存儲過程-- 定義結束符號DELIMITER 結束符號CREATE PROCEDURE 存儲過程名稱 (形式參數列表)BEGIN 多個sql語句END 結束符號 -- 調用存儲過程CALL 存儲過程名稱(實際參數列表); 參數類型:IN: 輸入參數,可以攜帶數據到存儲過程中OUT: 輸出參數,可以攜帶數據到存儲過程外面。INOUT: 輸入輸出參數。 -- 3.1 帶有輸入參數的存儲過程-- 需求: 傳入員工id查詢對應的員工DELIMITER $CREATE PROCEDURE pro_testByIn(IN eid INT) -- 參數類型(IN) 參數名稱 數據類型(int)BEGIN SELECT * FROM employee WHERE id=eid;END $ -- 調用CALL pro_testByIn(2); -- 3.2 帶有輸出參數的存儲過程DELIMITER $CREATE PROCEDURE pro_testByOut(OUT n VARCHAR(20))BEGIN -- 修改變量n SET n = ‘輸出參數‘;END $ -- 問題: 如何接收存儲過程的輸出參數???-- 定義變量去接收輸出參數數據。 -- mysql數據庫三種變量: -- 1)全局變量。mysql內置的變量,mysql程序關閉的時候全局變量才會失效!! -- show variables:產看全局變量 -- character_set_client: mysql接收的客戶端的數據編碼 -- character_set_results: mysql使用什麽編碼輸出給客戶端數據 -- 查看某個全局變量: select @@變量名 -- 修改某個全局變量: set @@變量名=值 -- 2) 會話變量。變量只在某次登錄的會話中有效!退出連接,會話變量數據失效!! -- 查看某個會話變量: select @變量名 -- 修改/定義某個會話變量: set @變量名=值 -- 案例:演示查詢和更改會話變量 -- 3) 局部變量:在存儲過程中定義的變量。存儲過程結束局部變量失效!! -- 查看某個局部變量: select 變量名 -- 修改某個局部變量: set 變量名=值 -- 定義某個局部變量: declare 變量名 數據類型; -- 定義會話變量去接收輸出參數數據 -- set @n=‘eric‘;CALL pro_testByOut(@n);-- 查看會話變量nSELECT @n; -- 3.3 帶有輸入輸出參數的存儲過程DELIMITER $CREATE PROCEDURE pro_testByInOut(INOUT n VARCHAR(20))BEGIN -- 查看n變量 SELECT n; -- 修改n變量 SET n = ‘500‘;END $ -- 定義會話變量調用存儲過程SET @n=‘100‘;CALL pro_testByInOut(@n);-- 查看nSELECT @n; -- 3.4 帶有判斷條件的存儲過程-- 需求: 輸入一個num整數,num=1 ,輸出‘星期一’,num=2,輸出‘星期二’,num=3,輸出‘星期三’,否則,輸出‘錯誤參數’DELIMITER $CREATE PROCEDURE pro_testByIf(IN num INT,OUT str VARCHAR(20))BEGIN IF num=1 THEN SET str = ‘星期一‘; ELSEIF num= 2 THEN SET str =‘星期二‘; ELSEIF num=3 THEN SET str = ‘星期三‘; ELSE SET str = ‘錯誤參數‘; END IF;END $ CALL pro_testByIf(5,@str);SELECT @str; -- 3.5 帶有循環條件的存儲過程-- 需求: 輸入一個num,計算從1到num的總和。DELIMITER $CREATE PROCEDURE pro_testByWhile(IN num INT,OUT score INT)BEGIN -- int result =0; -- for(int i=1;i<=100;i++){ -- result += i; -- } -- 定義局部變量 DECLARE i INT DEFAULT 1; DECLARE result INT DEFAULT 0; WHILE i<=num DO SET result = result + i; SET i = i+1; END WHILE; SET score = result;END $ CALL pro_testByWhile(200,@score);SELECT @score; -- 3.6 攜帶數據庫的數據給輸出參數(INTO)-- 需求: 傳入員工id,查詢對應的員工,輸出員工姓名DELIMITER $CREATE PROCEDURE pro_testByData(IN eid INT,OUT sname VARCHAR(20))BEGIN SELECT NAME INTO sname FROM employee WHERE id=eid;END $ CALL pro_testByData(2,@sname);SELECT @sname;ss -- 練習存儲過程練習在student表的數據基礎上,設計一個存儲過程: 1)計算出所有學生的英語平均分 2) 如果平均分,大於80分,且小於等於100分,輸出‘優秀‘ 如果平均分,大於等於60分,且小於等於80分,輸出‘良好‘ 如果平均分,小於60分,輸出‘不及格‘USE day14; SELECT * FROM student2; DELIMITER $CREATE PROCEDURE pro_testByAvg(OUT str VARCHAR(20),OUT tavg FLOAT)BEGIN DECLARE savg FLOAT DEFAULT 0.0; SELECT AVG(english) INTO savg FROM student2; IF savg>80 AND savg<=100 THEN SET str = ‘優秀‘; ELSEIF savg>=60 AND savg<=80 THEN SET str = ‘良好‘; ELSE SET str = ‘不及格‘; END IF; SET tavg = savg; END $ -- 刪除存儲過程DROP PROCEDURE pro_testByAvg; CALL pro_testByAvg(@str,@tavg);SELECT @str;SELECT @tavg; 5 觸發器 5.1 簡介 當往員工表插入/修改/刪除一條數據的時候,同時往日誌表記錄下來,這時就要使用觸發器完成。 5.2 觸發器語法 -- 員工日誌表CREATE TABLE emp_log( id INT PRIMARY KEY AUTO_INCREMENT, content VARCHAR(20)) -- 需求: 當往員工表插入一條數據時,往員工日誌插入一條記錄。-- 創建增加觸發器CREATE TRIGGER tri_empAdd AFTER INSERT ON employee FOR EACH ROW INSERT INTO emp_log(content) VALUES(‘員工被插入了一條記錄‘);-- 創建修改觸發器CREATE TRIGGER tri_empUpd AFTER UPDATE ON employee FOR EACH ROW INSERT INTO emp_log(content) VALUES(‘員工被修改了一條記錄‘);-- 創建刪除觸發器CREATE TRIGGER tri_empDel AFTER DELETE ON employee FOR EACH ROW INSERT INTO emp_log(content) VALUES(‘員工被刪除了一條記錄‘); DROP TRIGGER tri_empAdd; SELECT * FROM employee;SELECT * FROM emp_log; INSERT INTO employee(NAME,deptId,bossId) VALUES(‘李七‘,5,1);UPDATE employee SET NAME=‘張三‘ WHERE id=10;DELETE FROM employee WHERE id=10; 5.3 數據庫的權限問題 -- 五、mysql權限問題-- root用戶: 超級管理員。 權限: 增刪改查(數據庫,表,數據)-- 給mysql數據庫分配不同權限的不同用戶 -- mysql數據庫:存放mysql配置信息,包括用戶信息USE mysql;-- 用戶表SELECT * FROM USER; -- 加密函數(md5算法--單向加密)SELECT PASSWORD(‘root‘); -- *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B -- 修改用戶密碼UPDATE USER SET PASSWORD=PASSWORD(‘123456‘) WHERE USER=‘root‘; -- 分配權限給不同的用戶-- 需求: 分配查詢day15數據庫的employee表的權限給eric用戶,密碼為‘123456’GRANT SELECT ON day15.employee TO [email protected]
二十、二十一天MySql數據庫、jdbc