MySQL總結(5)

視圖

SELECT cust_name,cust_contact
FROM customers,orders,orderitems
WHERE customers.cust_id=orders.cust_id
	AND orderitems.order_num=orders.order_num
	AND prod_id='TNT2';

假如能夠把整個查詢包裝成一個名爲 productcustomers 的虛擬表mysql

SELECT cust_name,cust_contact
FROM productcustomers #this is a 視圖
WHERE prod_id='TNT2'

productcustomers 是一個視圖,做爲視圖,它不包含表中應該有的任何列或數據,它包含的是一個SQL查詢(與上面用以正確聯結表的相同的查詢)。sql

😁 重用SQL語句。 😁 簡化複雜的SQL操做。在編寫查詢後,能夠方便地重用它而沒必要 知道它的基本查詢細節。 😁 使用表的組成部分而不是整個表。 😁 保護數據。能夠給用戶授予表的特定部分的訪問權限而不是整個 表的訪問權限。 😁 更改數據格式和表示。視圖可返回與底層表的表示和格式不一樣的 數據。數據庫

😘 與表同樣,視圖必須惟一命名(不能給視圖取與別的視圖或表相 同的名字)。 😘 對於能夠建立的視圖數目沒有限制。 😘 爲了建立視圖,必須具備足夠的訪問權限。這些限制一般由數據 庫管理人員授予。 😘 視圖能夠嵌套,便可以利用從其餘視圖中檢索數據的查詢來構造 一個視圖。 😘 ORDER BY 能夠用在視圖中,但若是從該視圖檢索數據 SELECT 中也 含有 ORDER BY ,那麼該視圖中的 ORDER BY 將被覆蓋。 😘 視圖不能索引,也不能有關聯的觸發器或默認值。 😘 視圖能夠和表一塊兒使用。例如,編寫一條聯結表和視圖的 SELECT 語句。安全

使用視圖

❤ 視圖用 CREATE VIEW 語句來建立。 ❤ 使用 SHOW CREATE VIEW viewname ;來查看建立視圖的語句。 ❤ 用 DROP 刪除視圖,其語法爲 DROP VIEW viewname;。 ❤ 更新視圖時,能夠先用DROP再用CREATE,也能夠直接用CREATE OR REPLACE VIEW。若是要更新的視圖不存在,則第 2 條更新語句會建立一個視圖;若是要更新的視圖存在,則第 2 條更新語句會替換原有視圖。函數

CREATE VIEW productcustomers AS
SELECT cust_name, cust_contact, prod_id
FROM customers,orders,orderitems
WHERE customer.cust_id = orders.cust_id
	AND orderitems.order_num = orders.order_num;

WHERE 子句與 WHERE 子句 若是從視圖檢索數據時使用了一條 WHERE 子句,則兩組子句(一組在視圖中,另外一組是傳遞給視圖的)將自動組合。fetch

更新視圖

INSERT UPDATE DELETEthis

若是視圖具備如下操做是不能被更新的 (更新其實更新的是原來的表)  分組(使用 GROUP BY 和 HAVING );  聯結;  子查詢;  並;  彙集函數( Min() 、 Count() 、 Sum() 等);  DISTINCT;  導出(計算)列。spa

存儲過程

0x01 執行存儲過程

call CALL 接受存儲過程的名字以及須要傳遞給它的任意參數。命令行

CALL productpricing(@pricelow,
                   @pricehigh,
                   @priceaverage);

其中,執行名爲 productpricing 的存儲過程,它計算並返回產品的最低、最高和平均價格。指針

0x02 建立存儲過程 procedure

CREATE PROCEDURE pro()
BEGIN 
	SELECT avg(prod_price) AS priceaverage
	FROM products;
END

DELIMITER

DELIMITER // 告訴命令行實用程序使用 // 做爲新的語句結束分隔符,能夠看到標誌存儲過程結束的 END 定義爲 END// 而不是 END;

主要爲了防止命令行模式混淆 出現語法錯誤

DELIMITER //
DELIMITER ;

使用這個存儲過程

CALL pro();

刪除存儲過程

DROP PROCEDURE IF EXISTS pro;

if exists 指定過程不存在時刪除

使用參數

CREATE PROCEDURE productpricing(
	OUT p1 DECIMAL(8,2),
	OUT ph DECIMAL(8,2),
	OUT pa DECIMAL(8,2)
)
BEGIN
	SELECT min(prod_price)
	INTO p1
	FROM products;
	SELECT max(prod_price)
	INTO ph
	FROM products;
	SELECT avg(prod_price)
	INTO pa
	FROM products;
END;
# 此存儲過程接受3個參數: pl 存儲產品最低價格, ph 存儲產品最高價格, pa 存儲產品平均價格。每一個參數必須具備指定的類型,這裏使用十進制值。關鍵字 OUT 指出相應的參數用來從存儲過程傳出一個值(返回給調用者)。MySQL支持 IN (傳遞給存儲過程)、 OUT (從存儲過程傳出,如這裏所用)和 INOUT (對存儲過程傳入和傳出)類型的參數。存儲過程的代碼位於 BEGIN 和 END 語句內,如前所見,它們是一系列SELECT 語句,用來檢索值,而後保存到相應的變量(經過指定 INTO 關鍵字)。
# 調用
CALL productpricing(@pricelow,
                   @pricehigh,
                   @priceaverage)
# mysql 變量必須是@ 開始
# 顯示變量
SELECT @priceaverage,@pricelow,@pricehigh
CREATE PROCEDURE ordertotal(
	IN onumber INT,
    OUT ototal DECIMAL(8,2) # 十進制的(一共多少數,小數位數)
)
BEGIN 
	SELECT sum(item_price*quantity)
	FROM orderitems
	WHERE order_num = onumber
	INTO ototal;
END;
-- 註釋 DECLARE declare 聲明
CALL ordertotal(20005,@total);

智能儲存

image-20191101135704897

image-20191101135753359

IF 語句 這個例子給出了MySQL的 IF 語句的基本用法。 IF 語句還支持 ELSEIF 和 ELSE 子句(前者還使用 THEN 子句,後者不使用)。在之後章節中咱們將會看到 IF 的其餘用法(以及其餘流控制語句)。

此存儲過程有很大的變更。首先,增長了註釋(前面放置 -- )。在存儲過程複雜性增長時,這樣作特別重要。添加了另一個參數taxable ,它是一個布爾值(若是要增長稅則爲真,不然爲假)。在存儲過程體中,用 DECLARE 語句定義了兩個局部變量。DECLARE 要求指定變量名和數據類型,它也支持可選的默認值(這個例子中的 taxrate 的默認被設置爲 6% )。 SELECT 語句已經改變,所以其結果存儲到 total (局部變量)而不是 ototal 。 IF 語句檢查 taxable 是否爲真,若是爲真,則用另外一 SELECT 語句增長營業稅到局部變量 total 。最後,用另外一 SELECT 語句將total (它增長或許不增長營業稅)保存到 ototal 。

COMMENT 關鍵字 本例子中的存儲過程在 CREATE PROCEDURE 語 句中包含了一個 COMMENT 值。它不是必需的,但若是給出,將 在 SHOW PROCEDURE STATUS 的結果中顯示。

檢查儲存過程

SHOW CREATE PROCEDURE ordertotal;

遊標

只能用於存儲過程 不像多數DBMS,MySQL遊標只能用於存儲過程(和函數)。

🙃 在可以使用遊標前,必須聲明(定義)它。這個過程實際上沒有檢索數據,它只是定義要使用的 SELECT 語句。 🙃 一旦聲明後,必須打開遊標以供使用。這個過程用前面定義的SELECT 語句把數據實際檢索出來。 🙃 對於填有數據的遊標,根據須要取出(檢索)各行。 🙃 在結束遊標使用時,必須關閉遊標。

遊標須要declare 聲明

CREATE PROCEDURE processorders()
BEGIN
	DECLARE ordernumbers CURSOR # procedure程序,過程 
	FOR
	SELECT order_num FROM orders;
END;	# cursor 遊標

打開和關閉遊標

OPEN ordernumbers;  -- OPEN CURSOR
CLOSE ordernumbers; -- CLOSE CURSER
-- 隱含關閉 若是你不明確關閉遊標,MySQL將會在到達 END 語句時自動關閉它。

在一個遊標被打開後,可使用 FETCH 語句分別訪問它的每一行。 FETCH 指定檢索什麼數據(所需的列),檢索出來的數據存儲在什麼地方。它還向前移動遊標中的內部行指針,使下一條 FETCH 語句檢索下一行(不重複讀取同一行)。

CREATE PROCEDURE processorders()
BEGIN 
	DECLARE o INT;
	DECLARE ordernumbers CURSOR
	FOR
	SELECT order_num FROM orders;
	OPEN ordernumbers;
	FETCH ordernumbers INTO o;-- fetch 取來,拿
	CLOSE ordernumbers;
END;

DECLARE 語句的次序 DECLARE 語句的發佈存在特定的次序。用 DECLARE 語句定義的局部變量必須在定義任意遊標或句柄以前定義,而句柄必須在遊標以後定義。不遵照此順序將產生錯誤消息。

CREATE PROCEDURE processorders()
BEGIN 
	DECLARE done BOOLEAN DEFAULT 0; -- 默認值爲0
	DECLARE o INT;
	DECLARE ordernumbers CURSOR
	FOR
	SELECT order_num FROM orders;
	DECLARE CONTINUE HANDLER FOR 
	SQLSTATE '02000' SET done=1;
	OPEN ordernumbers;
	-- repeat 重複
	REPEAT
		FETCH ordernumbers INTO o;-- fetch 取來,拿
	UNTIL done END REPEAT;
	CLOSE ordernumbers;
END;
-- 與前一個例子同樣,這個例子使用 FETCH 檢索當前 order_num到聲明的名爲 o 的變量中。但與前一個例子不同的是,這個例子中的 FETCH 是在 REPEAT 內,所以它反覆執行直到 done 爲真(由 UNTILdone END REPEAT; 規定)。爲使它起做用,用一個 DEFAULT 0 (假,不結束)定義變量 done 。那麼, done 怎樣才能在結束時被設置爲真呢?答案是用如下語句:DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 這條語句定義了一個 CONTINUE HANDLER ,它是在條件出現時被執行的代碼。這裏,它指出當 SQLSTATE '02000' 出現時, SET done=1。SQLSTATE'02000' 是一個未找到條件,當 REPEAT 因爲沒有更多的行供循環而不能繼續時,出現這個條件。
CREATE PROCEDURE processorders()
BEGIN 
	DECLARE done BOOLEAN DEFAULT 0; -- 默認值爲0
	DECLARE o INT;
	DECLARE t DECIMAL(8,2);
	DECLARE ordernumbers CURSOR
	FOR
	SELECT order_num FROM orders;
	DECLARE CONTINUE HANDLER FOR 
	SQLSTATE '02000' SET done=1;
	CREATE TABLE IF NOT EXISTS ordertotals
	(order_num INT,total DECIMAL(8,2));
	OPEN ordernumbers;
	-- repeat 重複
	REPEAT
		FETCH ordernumbers INTO o;-- fetch 取來,拿
		CALL ordertotal(o,1,t);
		INSERT IOTO ordertotals(order_num,total)
		VALUES(o,t);
	UNTIL done END REPEAT;
	CLOSE ordernumbers;
END;

使用觸發器

 每當增長一個顧客到某個數據庫表時,都檢查其電話號碼格式是 否正確,州的縮寫是否爲大寫;  每當訂購一個產品時,都從庫存數量中減去訂購的數量;  不管什麼時候刪除一行,都在某個存檔表中保留一個副本。

 DELETE ;  INSERT ;  UPDATE 。

其餘語句不支持觸發器

建立觸發器

保持每一個數據庫的觸發器名惟一 在MySQL 5中,觸發器名必須在每一個表中惟一,但不是在每一個數據庫中惟一。這表示同一數據庫中的兩個表可具備相同名字的觸發器。這在其餘每一個數據庫觸發器名必須惟一的DBMS中是不容許的,並且之後的MySQL版本極可能會使命名規則更爲嚴格。所以,如今最好是在數據庫範圍內使用惟一的觸發器名。

trigger 觸發

CREATE TRIGGER newproduct AFTER INSERT ON products
-- 觸發器在insert以後執行 
FOR EACH ROW SELECT 'Product added'
-- 對每個插入行執行

觸發器按每一個表每一個事件每次地定義,每一個表每一個事件每次只容許一個觸發器。所以,每一個表最多支持6個觸發器(每條 INSERT 、 UPDATE和 DELETE 的以前和以後)。單一觸發器不能與多個事件或多個表關聯,因此,若是你須要一個對 INSERT 和 UPDATE 操做執行的觸發器,則應該定義 兩個觸發器。

若是 BEFORE 觸發器失敗,則MySQL將不執行請求的操做。此外,若是 BEFORE 觸發器或語句自己失敗,MySQL將不執行 AFTER 觸發器(若是有的話)。

刪除觸發器

DROP TRIGGER newproduct;

INSERT 觸發器

 在 INSERT 觸發器代碼內,可引用一個名爲 NEW 的虛擬表,訪問被 插入的行;  在 BEFORE INSERT 觸發器中, NEW 中的值也能夠被更新(容許更改 被插入的值);  對於 AUTO_INCREMENT 列, NEW 在 INSERT 執行以前包含 0 ,在 INSERT執行以後包含新的自動生成值。

CREATE TRIGGER neworder AFTER INSERT ON orders
FOR EACH ROW SELECT NEW.order_num

此代碼建立一個名爲 neworder 的觸發器,它按照 AFTER INSERT ON orders 執行。在插入一個新訂單到 orders 表時,MySQL生成一個新訂單號並保存到order_num 中。觸發器從 NEW. order_num 取得這個值並返回它。此觸發器必須按照 AFTER INSERT 執行,由於在 BEFORE INSERT 語句執行以前,新 order_num 尚未生成。對於 orders 的每次插入使用這個觸發器將老是返回新的訂單號。

DELECT 觸發器

 在 DELETE 觸發器代碼內,你能夠引用一個名爲 OLD 的虛擬表,訪 問被刪除的行。  OLD 中的值全都是隻讀的,不能更新。

create trigger delectorder before delete on orders
FOR each row
begin 
	insert into archive_orders(order_num,order_date,cust_id)
	values(OLD.order_num,OLD.order_date,OLD.cust_id);
end;

使用 BEGIN END 塊的好處是觸發器能容納多條SQL語句(在 BEGIN END塊 中一條挨着一條)。

UPDATA 觸發器

 在 UPDATE 觸發器代碼中,你能夠引用一個名爲 OLD 的虛擬表訪問之前( UPDATE 語句前)的值,引用一個名爲 NEW 的虛擬表訪問新更新的值;  在 BEFORE UPDATE 觸發器中, NEW 中的值可能也被更新(容許更改將要用於 UPDATE 語句中的值);  OLD 中的值全都是隻讀的,不能更新。

CREATE TRIGGER updataorder BEFORE UPDATE ON vendors
FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);

事務處理

並不是全部引擎都支持事務處理 正如第21章所述,MySQL支持幾種基本的數據庫引擎。正如本章所述,並不是全部引擎都支持明確的事務處理管理。 MyISAM 和 InnoDB 是兩種最常使用的引擎。前者不支持明確的事務處理管理,然後者支持。這就是爲何本書中使用的樣例表被建立來使用 InnoDB 而不是更常用的 MyISAM 的緣由。若是你的應用中須要事務處理功能,則必定要使用正確的引擎類型。

事務處理是一種機制,用來管理必須成批執行的MySQL操做,以保證數據庫不包含不完整的操做結果。利用事務處理,能夠保證一組操做不會中途中止,它們或者做爲總體執行,或者徹底不執行(除非明確指示)。若是沒有錯誤發生,整組語句提交給(寫到)數據庫表。若是發生錯誤,則進行回退(撤銷)以恢復數據庫到某個已知且安全的狀態。

事務開始

START TRANSACTION

使用ROLLBACK

START TRANSACTION
​```
ROLLBACK;

哪些語句能夠回退? 事務處理用來管理 INSERT 、 UPDATE 和 DELETE 語句。你不能回退 SELECT 語句。(這樣作也沒有什麼意義。)你不能回退 CREATE 或 DROP 操做。事務處理塊中可使用 這兩條語句,但若是你執行回退,它們不會被撤銷。

使用COMMIT

START TRANSACTION;
DELETE FROM orderitems WHERE order_num = 20010;
DELETE FROM orders WHERE order_num = 20010;
COMMIT;
-- 在這個例子中,從系統中徹底刪除訂單 20010 。由於涉及更新兩個數據庫表 orders 和 orderItems ,因此使用事務處理塊來保證訂單不被部分刪除。最後的 COMMIT 語句僅在不出錯時寫出更改。若是第一條 DELETE 起做用,但第二條失敗,則 DELETE 不會提交(實際上,它是被自動撤銷的)。

隱含事務關閉 當 COMMIT 或 ROLLBACK 語句執行後,事務會自動關閉(未來的更改會隱含提交)。

每一個保留點都取標識它的惟一名字,以便在回退時,MySQL知道要回退到何處。爲了回退到本例給出的保留點,可以下進行:

savepoint delete1;

​```

ROLLBACK TO delete1;

autocommit 標誌決定是否自動提交更改,無論有沒有 COMMIT語句。設置 autocommit 爲 0 (假)指示MySQL不自動提交更改(直到 autocommit 被設置爲真爲止)。

SET autocommit = 0;
相關文章
相關標籤/搜索