MySQL 拓展
視圖
本身是一個虛擬表,它的數據來自於表,通過執行時動態生成,佔用較小,只保存了sql邏輯,不保存查詢結果。臨時表
場景:多個地方用到同樣的查詢結果;該查詢結果使用的sql語句較複雜
create view 視圖名
as
查詢語句;
create or replace view 視圖名
as
查詢語句;
alter view 視圖名
as
查詢語句
drop view 視圖1,視圖2,...;
desc 視圖名;
show create view 視圖名;
CREATE VIEW my_v1
AS
SELECT studentname,majorname
FROM student s
INNER JOIN major m
ON s.majorid=m.majorid
WHERE s.majorid=1;
注意:視圖一般用於查詢的,而不是更新的,所以具備以下特點的視圖都不允許更新
- 包含分組函數、group by、distinct、having、union、
- join
- 常量視圖
- where 後的子查詢用到了 from 中的表
- 用到了不可更新的視圖
變量
系統變量
變量由系統提供的,不用自定義
全局變量:服務器層面上的,必須擁有super權限才能爲系統變量賦值,作用域爲整個服務器,也就是針對於所有連接(會話)有效
查看所有全局變量
SHOW GLOBAL VARIABLES;
查看滿足條件的部分系統變量
SHOW GLOBAL VARIABLES LIKE '%char%';
查看指定的系統變量的值
SELECT @@global.autocommit;
爲某個系統變量賦值
SET @@global.autocommit=0;
SET GLOBAL autocommit=0;
會話變量:服務器爲每一個連接的客戶端都提供了系統變量,作用域爲當前的連接(會話)
查看所有會話變量
SHOW SESSION VARIABLES;
查看滿足條件的部分會話變量
SHOW SESSION VARIABLES LIKE '%char%';
查看指定的會話變量的值
SELECT @@autocommit;
SELECT @@session.tx_isolation;
爲某個會話變量賦值
SET @@session.tx_isolation='read-uncommitted';
SET SESSION tx_isolation='read-committed';
如果沒有顯式聲明 global 還是 session,則默認是 session
自定義變量
用戶變量
- 作用域:針對於當前連接(會話)生效
- 位置:begin end裏面,也可以放在外面
①聲明並賦值:
set @變量名=值;或
set @變量名:=值;或
select @變量名:=值;
②更新值
方式一:
set @變量名=值;或
set @變量名:=值;或
select @變量名:=值;
方式二:
select xx into @變量名 from 表;
③使用
select @變量名;
局部變量:
- 作用域:僅僅在定義它的 begin end中有效
- 位置:只能放在 begin end中,而且只能放在第一句
①聲明
declare 變量名 類型 【default 值】;
②賦值或更新
方式一:
set 變量名=值;或
set 變量名:=值;或
select @變量名:=值;
方式二:
select xx into 變量名 from 表;
③使用
select 變量名;
作用域 | 定義位置 | 語法 | |
---|---|---|---|
用戶變量 | 當前會話 | 會話的任何地方 | 加@符號,不用指定類型 |
局部變量 | 定義它的BEGIN END中 | BEGIN END的第一句話 | 一般不用加@,需要指定類型 |
數據庫存儲過程
數據庫存儲過程:就是一組SQL語句集,功能強大,可以實現一些比較複雜的邏輯功能,類似於JAVA語言中的方法。
存儲過程跟觸發器有點類似,都是一組SQL集,但是存儲過程是主動調用的,且功能比觸發器更加強大,觸發器是某件事觸發後自動調用;
創建:
create procedure 存儲過程名(參數模式 參數名 參數類型)
begin
存儲過程體
end
注意:
- 參數模式:in、out、inout,其中in可以省略
- 存儲過程體的每一條sql語句都需要用分號結尾
- in、out、inout都可以在一個存儲過程中帶多個
結束標記
使用 delimiter 指定新的結束標記
delimiter $
調用:
call 存儲過程名(實參列表)
舉例:
調用in模式的參數:call sp1(‘值’);
調用out模式的參數:set @name; call sp1(@name);select @name;
調用inout模式的參數:set @name=值; call sp1(@name); select @name;
查看
show create procedure 存儲過程名;
刪除
drop procedure 存儲過程名;
下面創建一個名爲num_from_employee的存儲過程.
CREATE PROCEDURE num_from_employee (IN emp_id INT, OUT count_num INT )
READS SQL DATA
BEGIN
SELECT COUNT(*) INTO count_num
FROM employee
WHERE d_id=emp_id ;
END
#調用
SET @cnum ; # 不定義直接用也可以
CALL num_from_employee(123,@cnum);
存儲過程名稱爲 num_from_employee
;輸入變量爲emp_id
;輸出變量爲count_num
。SELECT語句從employee
表查詢d_id
值等於emp_id
的記錄,並用COUNT(*)
計算d_id
值相同的記錄的條數,最後將計算結果存入count_num
中。
函數
創建
create function 函數名(參數名 參數類型) returns 返回類型
begin
函數體
end
注意:函數體中肯定需要有return語句
#案例1:根據員工名,返回它的工資;有參有返回
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
SET @sal=0;#定義用戶變量
SELECT salary INTO @sal #賦值
FROM employees
WHERE last_name = empName;
RETURN @sal;
END $
SELECT myf2('k_ing') $
調用
select 函數名(實參列表);
查看
show create function 函數名;
刪除
drop function 函數名;
關鍵字 | 調用語法 | 返回值 | 應用場景 | |
---|---|---|---|---|
函數 | FUNCTION | SELECT 函數() | 只能是一個 | 一般用於查詢結果爲一個值並返回時 |
存儲過程 | PROCEDURE | CALL 存儲過程() | 可以有0個或多個 | 一般用於更新 |
流程控制
順序結構:程序從上往下依次執行
分支結構:程序按條件進行選擇執行,從兩條或多條路徑中選擇一條執行
循環結構:程序滿足一定條件下,重複執行一組語句
分支結構
if 函數
- 功能:實現簡單雙分支
- 語法:
if(條件,值1,值2)
- 位置:可以作爲表達式放在任何位置
case 結構
- 功能:實現多分支
- 位置:可以放在任何位置,
- 如果放在begin end 外面,作爲表達式結合着其他語句使用
- 如果放在begin end 裏面,一般作爲獨立的語句使用
語法1:
case 表達式或字段
when 值1 then 語句1;
when 值2 then 語句2;
..
else 語句n;
end [case];
語法2:
case
when 條件1 then 語句1;
when 條件2 then 語句2;
..
else 語句n;
end [case];
if 結構
- 功能:實現多分支
- 位置:只能放在begin end中
if 條件1 then 語句1;
elseif 條件2 then 語句2;
...
else 語句n;
end if;
循環結構
while
名稱可以不寫,寫了就成對使用,記得冒號
【名稱:】while 循環條件 do
循環體
end while 【名稱】;
loop
注意死循環
【名稱:】loop
循環體
end loop 【名稱】;
repeat
【名稱:】repeat
循環體
until 結束條件
end repeat 【名稱】;
比較
位置:只能放在begin end中
特點:都能實現循環結構
對比:
- 這三種循環都可以省略名稱,但如果循環中添加了循環控制語句(leave或iterate)則必須添加名稱
- loop 一般用於實現簡單的死循環
- while 先判斷後執行
- repeat 先執行後判斷,無條件至少執行一次
循環控制語句
- leave:類似於break,用於跳出所在的循環
- iterate:類似於continue,用於結束本次循環,繼續下一次
/*一、已知表stringcontent
其中字段:
id 自增長
content varchar(20)
向該表插入指定個數的,隨機的字符串
*/
DROP TABLE IF EXISTS stringcontent;
CREATE TABLE stringcontent(
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(20)
);
DELIMITER $
CREATE PROCEDURE test_randstr_insert(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE str VARCHAR(26) DEFAULT 'abcdefghijklmnopqrstuvwxyz';
DECLARE startIndex INT;#代表初始索引
DECLARE len INT;#代表截取的字符長度
WHILE i<=insertcount DO
SET startIndex=FLOOR(RAND()*26+1);#代表初始索引,隨機範圍1-26
SET len=FLOOR(RAND()*(20-startIndex+1)+1);#代表截取長度,隨機範圍1-(20-startIndex+1)
INSERT INTO stringcontent(content) VALUES(SUBSTR(str,startIndex,len));
SET i=i+1;
END WHILE;
END $
CALL test_randstr_insert(10)$
觸發器
觸發器(TRIGGER)是由事件來觸發某個操作。這些事件包括INSERT語句、UPDATE語句和DELETE語句。當數據庫系統執行這些事件時,會激活促發其執行相應的操作。參考
CREATE TRIGGER 觸發器名 BEFORE|AFTER 觸發事件
ON 表名 FOR EACH ROW
BEGIN
執行語句列表
END
觸發事件:
- INSERT 型觸發語句:INSERT,LOAD DATA,REPLACE
- UPDATE 型觸發語句:UPDATE
- DELETE 型觸發語句:DELETE,REPLACE
當在users中插入一條數據,就會在logs中生成一條日誌信息。
DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;#後面發現中文字符編碼出現亂碼,這裏設置字符集
SET s2 = " is created";
SET s1 = CONCAT(NEW.name,s2); #函數CONCAT可以將字符串連接
INSERT INTO logs(log) values(s1);
END $
DELIMITER ;
定時任務
mysql5.1.6 增加了一個事件調度器(Event Scheduler),可以做定時任務(定時刪除記錄,定時數據統計),取代之前系統的計劃任務。mysql事件調度器可以精確到每秒執行一個任務。參考
事件調度器與觸發器的區別:事件調度器是基於特定時間週期來觸發執行某些任務,觸發器是基於某個表產生的事件來觸發。
查看是否開啓
show variables like 'event_scheduler';
開啓事件調度器
set global event_scheduler = on;
當mysql重啓後,會自動關閉。如果需要一直開啓,需要在my.ini
中配置如下:event_scheduler = on
創建事件語法
CREATE EVENT [IF NOT EXISTS ] event_name
ON SCHEDULE schedule
[ ON COMPLETION [ NOT ] PRESERVE ]
[ ENABLE | DISABLE ]
[ COMMENT '註釋' ]
DO SQL語句;
schedule : AT TIMESTAMP [+ INTERVAL interval ] | EVERY interval [ STARTS TIMESTAMP ] [ ENDS TIMESTAMP ]
interval : quantity { YEAR | QUARTER | MONTH | DAY |
HOUR | MINUTE | WEEK | SECOND |
YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND |
HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND }
關閉事件
ALTER EVENT event_name DISABLE;
開啓事件
ALTER EVENT event_name ENABLE;
刪除事件
DROP EVENT [IF EXISTS ] event_name;
查看所有事件
SHOW EVENTS;
查看定期任務
SELECT event_name,event_definition,interval_value,interval_field,status
FROM information_schema.EVENTS;
定時規則
- 週期執行–關鍵字 EVERY
- 在具體某個時間執行–關鍵字 AT
- 在某個時間段執行–關鍵字 STARTS ENDS
示例
事件類型有兩種,一種是間隔觸發,一種是特定時間觸發
DROP EVENT IF EXISTS event_test;
CREATE EVENT event_test
ON SCHEDULE EVERY 1 SECOND STARTS '2017-08-22 11:57:00' ENDS '2017-08-22 12:00:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT '每隔一秒向test表插入記錄'
DO INSERT INTO test VALUES(NULL, now());
DROP EVENT IF EXISTS event_test2;
CREATE EVENT event_test2
ON SCHEDULE AT '2017-08-22 12:01:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT '指定時間向test表插入記錄'
DO INSERT INTO test VALUES(999999, now());
on schedule every 1 week //每週執行1次
on schedule at current_timestamp()+interval 5 day //5天后執行
on schedule at '2019-01-01 00:00:00' //在2019年1月1日,0點整執行
on schedule every 1 day starts current_timestamp()+interval 5 day ends current_timestamp()+interval 1 month //5天后開始每天都執行執行到下個月底
on schedule every 1 day ends current_timestamp()+interval 5 day //從現在起每天執行,執行5天