數據庫常用sql語句詳解

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)非空約束,不能插入null
INSERT 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。所以唯一約束不能約束null
INSERT 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刪除數據的時候,可以把自增長的初始值置爲0
TRUNCATE 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 引入
需求分析: 原始需求 -> 業務需求
客戶 業務模型:客戶(姓名 登記時間 郵箱 微信號 )
需求設計:
業務模型(客戶業務模型): -》 抽取實體模型: class Customer{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
– 預期結果:
– 軟件開發部 張三
– 軟件開發部 王五
– 軟件維護部 李四
– 軟件維護部 陳六
– 祕書部 null

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

– 1.4 右外連接查詢
– 右外連接查詢效果: 右表(部門表)的數據全部顯示,左表(員工)的數據當滿足連接條件的時候,
– 就顯示滿足條件的數據,但是如果不滿足連接條件,則顯示null

SELECT 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);
– 查看會話變量n
SELECT @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);
-- 查看n
SELECT @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 'eric'@'localhost' IDENTIFIED BY '123456';
GRANT DELETE ON day15.employee TO 'eric'@'localhost' IDENTIFIED BY '123456';

SHOW TABLES;

發佈了28 篇原創文章 · 獲贊 12 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章