MySQL - 存儲對象

視圖

視圖(View)是一種虛擬存在的表,視圖中的數據並不在數據庫中實際存在,行和列數據來自定義視圖的查詢中使用的表,並且是在使用視圖時自動生成的。

  • 創建視圖:create [or replace] view 視圖名稱[(列名列表)] as select查詢語句;

  • 查詢視圖:
    1、查看創建視圖的語句:show create view 視圖名稱;
    2、查看視圖數據:select * from 視圖名稱;

  • 修改視圖:
    1、create [or replace] view 視圖名稱[(列名列表)] as select查詢語句;
    2、alter view 視圖名稱[(列名列表)] as select查詢語句;

  • 刪除視圖:drop view [if exist] 視圖名稱 [,視圖名稱...];

  • 視圖檢查選項:當使用with [cascaded / local] check option字句創建視圖時,在對視圖進行插入、更新、刪除這些操作時,MySQL 會通過視圖檢查來判斷要操作的數據是否符合創建視圖時select查詢語句中的條件,不符合則無法插入。MySQL 允許基於另一個視圖創建視圖,它還會檢查依賴視圖中的規則來保持一致性,cascaded(默認)、local 是 MySQL 用來確定檢查範圍的兩個選項:
    1、cascaded:如果創建視圖指定了該選項,那麼在操作當前視圖時會檢查當前視圖的條件、以及遞歸檢查當前視圖依賴的所有視圖的條件,如果依賴的視圖沒有添加檢查選項,則會給強制添加上,保證所有視圖的檢查條件生效。
    2、local:會檢查當前視圖的條件、以及嘗試遞歸檢查當前視圖依賴的所有視圖的條件,但是如果依賴的視圖沒有添加檢查選項則不檢查它的視圖條件,也就是不會給其強制添加視圖檢查選項,只保證有檢查選項的視圖條件生效。

  • 視圖更新:要讓視圖可以更新,視圖中的行與基礎表中的行之間必須存在一對一關係,如果視圖包含如下內容,則不能更新:
    1、聚合函數
    2、distinct
    3、group by
    4、having
    5、union、union all

  • 視圖的作用:
    1、視圖不僅可以簡化用戶對數據的理解,還可以簡化操作。那些經常使用的查詢可以被定義爲視圖,這樣不用爲以後相同的操作每次指定全部查詢條件,而是直接從視圖查詢。
    2、數據庫可以通過權限管理來指定用戶訪問那些庫那些表,但不能授權用戶只訪問特定的行數據以及列,這些數據可以通過視圖來提供給用戶。
    3、視圖可以幫助用戶屏蔽真實的表結構,用戶只關心需要的數據即可。

存儲過程

存儲過程是事先經過編譯並存儲在數據庫中的一段 SQL 語句的集合,調用存儲過程可以傳遞參數、以及返回結果數據,簡化了開發、減少數據在數據庫和應用服務器之間的傳輸,進而提高數據的處理效率。核心思想就是數據庫 SQL 語言層面的代碼封裝與重用。

基本操作
  • 創建存儲過程
create procedure 存儲過程名稱([參數列表])
begin
    -- sql 語句;
    -- sql 語句;
end;

上邊語句在命令行無法成功執行,因爲 end 之前還有;,導致錯誤的識別 SQL 結束,可以用如下方式:

-- 指定結束限定符,這樣遇到 $$ 才認爲 SQL 結束
delimiter $$
create procedure 存儲過程名稱([in/out/inout 參數名 參數類型, ...])
begin
    -- sql 語句;
    -- sql 語句;
end$$
-- 指定 SQL 結束符爲默認的分號
delimiter ; 
  • 調用存儲過程
call 存儲過程名稱([參數列表]);
  • 查看存儲過程
-- 查詢指定數據庫的存儲過程以及狀態信息
select * from information_schema.routines where routine_schema = '數據庫名稱';
-- 查詢某個存儲過程的定義
show create procedure 存儲過程名稱;
  • 刪除存儲過程
drop procedure [if exists] 存儲過程名稱;
變量
  • 系統變量
-- 查看所有系統變量
show [global | session] variables;
-- 模糊查找系統變量
show [global | session] variables like '';
-- 查看指定系統變量,select @@session.autocommit; select @@autocommit;
select @@[global | session].變量名;

-- 設置系統變量
set  [global | session] 變量名 = 值;
-- set @@session.autocommit = 0; set @@autocommit = 0;
set  @@[global | session].變量名 = 值;

如果不指定 global、session,默認是 session;設置系統變量指定爲 global,MySQL 服務重啓後也會失效。

  • 用戶自定義變量
    用戶自定義變量不用提前聲明,直接用@變量名使用即可,作用域爲當前連接。
-- 給變量賦值,推薦使用 :=
set @var_name = expr [, @var_name = expr]...;
set @var_name := expr [, @var_name := expr]...;
select @var_name := expr [, @var_name := expr]...;
select 字段名 into @var_name from 表名;

-- 使用變量,沒賦值的變量到的值是 null
select @var_name [, @var_name]...;
  • 局部變量
    局部變量在訪問之前,需要使用declare聲明,可以作爲存儲過程內的局部變量和輸入參數,在begin end塊之內有效。
-- 聲明局部變量,類型就是數據庫支持的類型
declare 變量名 變量類型 [default 默認值];

-- 賦值
set 變量名 = 值;
set 變量名 := 值;
select 字段名 into 變量名 from 表名;

-- 取值
select 變量名;
條件判斷
  • if
if 條件1 then
-- 可選
elseif 條件2 then     
-- 可選
else                  
end if;
  • 參數
    1、in,默認的類型,標記參數爲輸入類型的,可以作爲輸入參數
    2、out,標記參數爲輸出類型的,可以作爲返回值
    3、inout,可以作爲輸入參數也可以作爲返回值
create procedure p(in score int, out result varchar(10))
begin
    if score >= 80 then
        set result := '優秀';
    elseif score >= 60 then
        set result := '及格';
    else
        set result := '不及格';
    end if;
end;

-- 調用存儲過程,使用用戶自定義變量接收結果
call p(70, @result);
select @result;
  • case
create procedure p(in month int)
begin
    declare result varchar(10);
    case
        when month >= 1 && month <= 3 then set result = '第一季度';
        when month >= 4 && month <= 6 then set result = '第二季度';
        else set result = '其它';
    end case;
end;
循環
  • while
while 條件 do
    sql 邏輯...
end while;
  • repeat
repeat
    sql 邏輯...
    until 條件
end repeat;
  • loop
[label:]loop
    sql 邏輯...
    [leave [label]; 退出循環 | iterate [lable]; 直接進入下一次循環]
end loop [label];
條件處理程序

用來定義在流程控制結構執行過程中遇到問題時的處理辦法。
declare handler_action handler for condition_value [, condition_value...] statement;

  • handler_action
    1、continue:繼續執行當前程序
    2、exit:終止執行當前程序
  • condition_value
    1、sqlstate 狀態碼
    2、sqlwarning:所有以01開頭的 sqlstate 代碼的簡寫
    3、not found:所有以02開頭的 sqlstate 代碼的簡寫
    4、sqlexception:所有沒被 sqlwarning、not found 捕獲的 sqlstate 代碼的簡寫
遊標

遊標(cursor),用來存儲查詢結果集類型的數據,在存儲過程和函數中可以使用遊標對結果集進行循環處理。

  • 聲明遊標:declare 遊標名稱 cursor for 查詢語句;
  • 打開遊標:open 遊標名稱;
  • 獲取遊標記錄:fetch 遊標名稱 into 變量[, 變量...];
  • 關閉遊標:close 遊標名稱;
create procedure p(in user_age int)
begin
    declare _name varchar(100);
    declare _profession varchar(100);
    -- 聲明遊標,存儲查詢的結果集
    declare u_cursor cursor for select name, profession from user where age >= user_age;
    -- 聲明一個條件處理程序,當狀態碼爲0200時執行退出操作、關閉遊標
    declare exit handler for sqlstate '0200' close u_cursor;
    -- 創建新表
    drop table if exists user2;
    create table user2(
        id int primary key auto_increment,
        name varchar(100),
        profession varchar(100));
    -- 打開遊標
    open u_cursor;
    while true do
        -- 獲取遊標記錄
        fetch u_cursor into _name, _profession;
        -- 插入記錄到新表
        insert into user2 (name, profession) values (_name, _profession);
    end while;
    -- 關閉遊標
    close u_cursor;
end;
存儲函數

存儲函數是有返回值的存儲過程,存儲函數的參數只能是in類型的。

create function 存儲函數名稱([參數列表])
returns type [characteristic...]
begin
    sql語句;
    return ...;
end;
  • type:返回值類型
  • characteristic:
    1、deterministic:相同的輸入參數總是產生相同的結果
    2、no sql:不包含 sql 語句
    3、reads sql data:包含讀取數據的語句,但不包含寫入數據的語句
create function fun_sum(n int)
returns int no sql
begin
    declare total int default 0;
    while n > 0 do
        set total := total + n;
        set n := n - 1;
    end while;
    return total;
end;

select fum_sum(100);

觸發器

觸發器是與表有關的數據庫對象,指在 insert、update、delete 之前(before)或之後(after),觸發並執行觸發器中定義的 SQL 語句集合。觸發器的這種特性可以幫助應用在數據庫端確保數據的完整性、記錄日誌、數據校驗等操作。

使用別名 old、new 來引用觸發器中發生變化的記錄內容,目前只支持行級觸發器(修改多少行記錄就觸發幾次)不支持語句級觸發器。

觸發器類型 new、old
insert new 表示將要或已經新增的數據
update old 表示修改之前的數據,new 表示將要或修改後的數據
delete old 表示將要或已經刪除的數據
  • 創建
create trigger trigger_name
before/after insert/update/delete
on table_name for each row
begin
    trigger_statement;
end;
  • 查看
show triggers;
  • 刪除
-- 如果沒指定schema_name,默認爲當前數據庫
drop trigger [schema_name.]trigger_name;
  • 實例
-- 給 tb_user 表添加數據後,自動給日誌表添加日誌:
create trigger tb_user_insert_trigger
after insert on tb_user for each row
begin
    insert into tb_user_logs(operation, operator, time, content) values ('insert', '張三', now(), new.content);
end;

-- 更新 tb_user 表數據後,自動給日誌表添加日誌:
create trigger tb_user_update_trigger
after update on tb_user for each row
begin
    insert into tb_user_logs(operation, operator, time, content) values ('update', '張三', now(), concat('更新前的數據', old.content, ';', '更新後的數據', new.content));
end;

-- 從 tb_user 表刪除數據後,自動給日誌表添加日誌:
create trigger tb_user_delete_trigger
after delete on tb_user for each row
begin
    insert into tb_user_logs(operation, operator, time, content) values ('delete', '張三', now(), old.content);
end;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章