數據庫 : Mysql - 平常應用

#登陸MYSQL數據庫
MYSQL -u root -p

#顯示全部數據庫
SHOW databases;

#顯示當前數據庫與應用程序間進行了多少條鏈接
SHOW processlist;

#使用某一數據庫
USE database;

#顯示全部表
SHOW tables;

#表結構描述 describe
DESC table;

#篩選表數據
#選擇哪些列
SELECT prod_name, prod_price
#從哪一個表選
FROM products
#選擇的列作出什麼篩選匹配
WHERE vend_id = 1003 OR vend_id = 1004
#根據什麼順序做出排序 DESC 降序 ASC 升序
ORDER BY prod_price;

WHERE--------------------------
vend_id IN (......)
vend_id IS NOT NULL
-------------------------------------

SELECT prod_id, prod_price
FROM products
WHERE prod_name LIKE 'jet%'
ORDER BY prod_price;

-------------------------------------
WHERE prod_name LIKE '_ ton anvil'
-------------------------------------
/*
    你最好避免使用匹配符_ %,由於會有性能損失的問題,
    尤爲別在搜索的字符串前面使用。
 */

#正則表達式

SELECT prod_name 
FROM products
WHERE prod_name REGEXP '1000'
ORDER BY prod_name;

---------------------------------------

#模糊查詢經常使用

SELECT prod_name
FROM products
WHERE prod_name LIKE '1000'
ORDER BY prod_name;

SELECT prod_name 
FROM products
WHERE prod_name REGEXP '.000'
ORDER BY prod_name;

/*
LIKE 匹配整個列。若是被匹配的文本在列值
中出現, LIKE 將不會找到它,相應的行也不被返回(除非使用
通配符)。而 REGEXP 在列值內進行匹配,若是被匹配的文本在
列值中出現, REGEXP 將會找到它,相應的行將被返回。這是一
個很是重要的差異。
*/

#匹配兩個串之一
SELECT prod_name 
FROM products
WHERE prod_name REGEXP '1000|2000'
ORDER BY prod_name;

#匹配幾個字符之一
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[123] Ton'
ORDER BY prod_name;

#否認匹配,匹配這些字符除外的任何串
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[^123] ton'
ORDER BY prod_name;

#匹配範圍能夠被指定
SELECT prod_name 
FROM products
WHERE prod_name REGEXP '[1-9] ton'
ORDER BY prod_name;

#匹配特殊字符須要在其前面添加\\做爲前 '.'匹配0個或1個字符
SELECT prod_name 
FROM products
WHERE prod_name REGEXP '\\.'
ORDER BY prod_name;

--------------------------------------------------------------
#字符類
/*
[:alnum:]           [a-zA-Z0-9]
[:alpha:]            [a-zA-Z]   
[:blank:]            [\\t]
[:cntrl:]             [ASCII 0-31和127]
[:digit:]             [0-9]
[:graph:]            和[:print:]相同,但不包括空格
[:lower:]            [a-z]
[:print:]             任意可打印字符
[:punct:]            既不在[:alnum]又不在[:cntrl:]的字符
[:space:]            包括空格在內的任意空白字符(\\f\\n\\r\\t\\v)
[:upper:]            [A-Z]
[:xdigit:]            十六進制[a-fA-F0-9]
 */

--------------------------------------------------------------
#重複元字符
/*
*                       0個或多個匹配
+                       1個或多個匹配(等於{1,})
?                       0個或1個匹配(等於{0,1})
{n}                     指定數目的匹配
{n,}                    很多於指定數目的匹配
{n,m}                  匹配數目的範圍(m不超過255)
*/

SELECT prod_name 
FROM products
WHERE prod_name REGEXP '\\([0-9] sticks?\\)'
ORDER BY prod_name;

SELECT prod_name 
FROM products
WHERE prod_name REGEXP '[[:digit:]]{4}'
ORDER BY prod_name;

------------------------------------------------------------------
/*
^                   文本的開始
$                   文本的結尾
[[:<:]]             詞的開始
[[:>:]]             詞的結尾
 */

SELECT prod_name
FROM products
WHERE prod_name REGEXP '^[0-9\\.]'
ORDER BY prod_name;

-----------------------------------------------------------------
/*
    計算字段
    通常數據庫中存取的數據與應用程序所要求的數據格式並不一致,
    因此須要進行格式轉換,而計算字段就是應用於這一用途的字段。
    計算字段是運行時在SELECT中建立出來的。
 */

#拼接 --例:供應商 + 地址
SELECT Concat(vend_name, '(', vend_country, ')')
FROM vendors
ORDER BY vend_name;

#剪切空格 RTrim
SELECT Concat(RTrim(vend_name), '(', vend_country, ')')
FROM vendors
ORDER BY vend_name;

#使用別名 AS
SELECT Concat(RTrim(vend_name), '(', vend_country, ')') AS vend_title
FROM vendors
ORDER BY vend_name;

#執行算術運算
SELECT prod_id,
         quantity,
         item_price,
         quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num = 20005;

---------------------------------------------------
#函數
#函數能方便程序員編寫代碼,可是這樣會影響代碼的可移植性。

/*
1.文本處理函數
Left()                  返回串左邊的字符
Length()               返回串的長度
Locate()                找出串的一個子串
Lower()                將串轉換爲小寫
LTrim()                 去掉串左邊的空格
Right()                 返回串右邊的字符
RTrim()                 去掉串右邊的空格
Soundex()              返回串的SOUNDEX值
SubString()             返回子串的字符
Upper()                 將串轉換爲大寫

SOUNDEX 是一個將任何文本串轉換爲描述其語音表示的字母數字模式的算法。 
SOUNDEX 考慮了相似的發音字符和音節,使得能對串進行發音比較而不是字母比較。
 如下進行該函數的使用對比
 */
SELECT cust_name,cust_contact
FROM customers
WHERE cust_contact = 'Y. Lie';

SELECT cust_name,cust_contact
FROM customers
WHERE Soundex(cust_contact) = Soundex('Y. Lie');

/*
日期和時間處理函數
AddDate()               增長一個日期(天、周等)
AddTime()               增長一個時間(時、分等)
CurDate()                返回當前日期
CurTime()                返回當前時間
Date()                    返回日期時間的日期部分
DateDiff()                計算兩個日期之差
Date_Add()               高度靈活的日期運算函數
Date_Format()            返回一個格式化的日期或時間串
Day()                     返回一個日期的天數部分
DayOfWeek()             對於一個日期,返回對應的星期幾
Hour()                    返回一個時間的小時部分
Minute()                  返回一個時間的分鐘部分
Month()                   返回一個日期的月份部分
Now()                     返回當前日期和時間
Second()                  返回一個時間的秒部分
Time()                     返回一個日期時間的時間部分
Year()                      返回一個日期的年份部分

 */

SELECT cust_id, order_num
FROM orders
WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30';

/*
    數值處理

Abs()               返回一個數的絕對值
Cos()               返回一個角度的餘弦
Exp()               返回一個數的指數值
Mod()               返回除操做的餘數
Pi()                 返回圓周率
Rand()              返回一個隨機數
Sin()               返回一個角度的正弦
Sqrt()              返回一個數的平方根
Tan()              返回一個角度的正切
 */

-------------------------------------------------------------

#彙集函數
#咱們常常須要彙總數據而不用把它們實際檢索出來。
/*
AVG()               返回某列的平均值
COUNT()             返回某列的行數
MAX()               返回某列的最大值
MIN()                返回某列的最小值
SUM()               返回某列值之和


DISTINCT 聚焦不一樣值, ALL 所有值進行計算
 */

SELECT AVG(prod_price) AS avg_price
FROM products
WHERE vend_id = 1003;

SELECT COUNT(*) AS num_cust
FROM customers;

SELECT AVG(DISTINCT prod_price) AS avg_price
FROM products
WHERE vend_id = 1003;


SELECT COUNT(*) AS num_items,
        MIN(prod_price) AS price_min,
        MAX(prod_price) AS price_max,
        AVG(prod_price) AS price_avg
FROM products;

-------------------------------------------------------------

#數據分組
/*
數據分組由GROUP BY 語句引出,注意一點就是選擇的字段若是不是
彙集函數則須要歸在分組字段中

WITH ROLLUP關鍵字能夠獲得每一個分組以及每一個分組彙總級別
(針對每一個分組)的值
 */

SELECT vend_id, COUNT(*) AS num_prods
FROM products
GROUP BY vend_id;


SELECT vend_id, AVG(prod_price) AS price_avg, COUNT(*)
FROM products
GROUP BY vend_id;

SELECT vend_id, AVG(prod_price) AS price_avg, COUNT(*)
FROM products
GROUP BY vend_id WITH ROLLUP;


#過濾分組
SELECT cust_id, COUNT(*) AS orders
FROM orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;

#HAVING過濾的是分組後數據組,而WHERE過濾的是數據項
SELECT vend_id, COUNT(*) AS num_prods
FROM products
WHERE prod_price >= 10
GROUP BY vend_id
HAVING COUNT(*) >= 2;

SELECT order_num, SUM(quantity*item_price) AS ordertotal
FROM orderitems
GROUP BY order_num
HAVING ordertotal >= 50
ORDER BY ordertotal;

#SELECT子句順序
#SELECT --  FROM -- WHERE -- GROUP BY --
#-- HAVING -- ORDER BY -- LIMIT  


---------------------------------------------------------------
#子查詢
SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
                        FROM orderitems
                        WHERE prod_id = 'TNT2');

SELECT cust_name,
            cust_state,
            (SELECT COUNT(*)
                FROM orders
                WHERE orders.cust_id = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;

-------------------------------------------------------------------
/*
聯結
分解數據爲多個表能更有效地存儲,更方便地處理,而且具備更大的
可伸縮性。使用特殊的語法,能夠聯結多個表返回一組輸出,
聯結在運行時關聯表中正確的行。

在聯結兩個表時,你實際上作的是將第一個表中的每一行
與第二個表中的每一行配對,而後由WHERE語句進行篩選。
兩個表的行之間映射的結果又稱笛卡爾積。
 */

SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name, prod_name;


SELECT vend_name, prod_name, prod_price
FROM vendors, products
ORDER BY vend_name, prod_name;

/*
目前爲止所用的聯結稱爲等值聯結(equijoin),它基於兩個表之間的
相等測試。這種聯結也稱爲內部聯結。其實,對於這種聯結可使用稍
微不一樣的語法來明確指定聯結的類型。
 */
#內部聯結
SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;

#聯結多張表成一張大表
SELECT prod_name, vend_name, prod_price, quantity
FROM orderitems, products, vendors
WHERE products.vend_id = vendors.vend_id
AND orderitems.prod_id = products.prod_id
AND order_num = 20005;

#注意,聯結表是性能低下的緣由之一。
-------------------------------------------------------------
#使用表別名

SELECT Concat(RTrim(vend_name),'(',RTrim(vend_country),')')
AS vend_title
FROM vendors
ORDER BY vend_name;

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

#自聯結
/*
當須要在一張表進行兩次查詢才能查找到正確的字段時,能夠採用自聯結。
如在一張商品表中尋找某樣產品的產商下的全部產品。
 */

SELECT prod_id, prod_name
FROM products
WHERE vend_id = (SELECT vend_id
                    FROM products
                    WHERE prod_id = 'DTNTR');

SELECT p1.prod_id, p1.prod_name
FROM products AS p1, products AS p2
WHERE p1.vend_id = p2.vend_id
AND p2.prod_id = 'DTNTR';

#外部聯結
/*
聯結沒有匹配到的行
 */
SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;

SELECT customers.cust_id, orders.order_num
FROM customers RIGHT OUTER JOIN orders
ON orders.cust_id = customers.cust_id;

#使用帶彙集函數的聯結
SELECT customers.cust_name,
        customers.cust_id,
        COUNT(orders.order_num) AS num_ord
FROM customers INNER JOIN orders
ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id;


SELECT customers.cust_name,
        customers.cust_id,
        COUNT(orders.order_num) AS num_ord
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id;

#組合查詢
/*
多數SQL查詢都只包含從一個或多個表中返回數據的單條 SELECT 語
句。MySQL也容許執行多個查詢(多條 SELECT 語句)
,並將結果做爲單個查詢結果集返回。
這 些 組 合 查 詢 通 常 稱 爲 並 ( union ) 或 復 合 查 詢
(compound query).
 */
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5;

SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001, 1002);

>>>>>>>>>>>>>>>>>>>>>

SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION 
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001, 1002);

#UNION 默認會去除重複的行,若是想所有顯示出來則使用
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION ALL
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001, 1002);

--------------------------------------------------------------
/*
並不是全部的引擎都支持全文本搜索,選擇引擎時需注意。
LIKE通配符搜索和正則表達式查找存在幾個問題:

性能——通配符和正則表達式匹配一般要求MySQL嘗試匹配表
中全部行(並且這些搜索極少使用表索引)。
所以,因爲被搜索行數不斷增長,這些搜索可能很是耗時。

明確控制——使用通配符和正則表達式匹配,很難(並且並不總
是能)明確地控制匹配什麼和不匹配什麼。例如,指定一個詞必
須匹配,一個詞必須不匹配,而一個詞僅在第一個詞確實匹配的
狀況下才能夠匹配或者才能夠不匹配。

智能化的結果——雖然基於通配符和正則表達式的搜索提供了非
常靈活的搜索,但它們都不能提供一種智能化的選擇結果的方法。
例如,一個特殊詞的搜索將會返回包含該詞的全部行,而不區分
包含單個匹配的行和包含多個匹配的行(按照多是更好的匹配
來排列它們)。相似,一個特殊詞的搜索將不會找出不包含該詞但
包含其餘相關詞的行。
 */

#在使用全文本搜索時,MySQL不須要分別查看每一個行,不須要分別分析和處理
#每一個詞。MySQL建立指定列中各詞的一個索引,搜索能夠針對這些詞進
#行。

#爲了進行全文本搜索,必須索引被搜索的列,並且要隨着數據的改
#變不斷地從新索引。在對錶列進行適當設計後,MySQL會自動進行全部
#的索引和從新索引。

#啓動全文本搜索支持
CREATE TABLE productnotes
(
    note_id     INT          NOT NULL AUTO_INCREMENT,
    prod_id     CHAR(10)    NOT NULL,
    note_data DATE     NOT NULL,
    note_text   TEXT         NULL,
    PRIMARY KEY(note_id),
    FULLTEXT(note_text),
) ENGINE = MyISM;
#這裏FULLTEXT索引單個列。

#不要在導入數據的時候使用FULLTEXT索引,由於更新索引須要時間。
#應該首先導入全部數據,而後再修改表,定義FULLTEXT。

#在索引以後,使用兩個函數 Match() 和 Against() 執行全文本搜索,
#其中 Match() 指定被搜索的列, Against() 指定要使用的搜索表達式。

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('rabbit');

#全文本搜索會對查詢結果進行排序。
SELECT note_text,
        Match(note_text) Against('rabbit') AS rank
FROM productnotes;

#布爾文本搜索是全文本搜索的一種選擇模式。

------------------------------------------------------------------

#數據插入有如下幾個方式

#插入完整的行
INSERT INTO customers
VALUES(NULL,
    'Pep E. LaPew',
    '100 Main Street',
    'Los Angeles',
    'CA',
    '90046',
    'USA',
    NULL,
    NULL
    );

#插入多行
INSERT INTO customers(cust_name,
                cust_address,
                cust_city,
                cust_state,
                cust_zip,
                cust_country)
            VALUES(
                    'Pep E. LaPew',
                    '100 Main Street',
                    'Los Angeles',
                    'CA',
                    '90046',
                    'USA'
                ),
                    (
                    'M. Martian',
                    '42 Galaxy Way',
                    'New York',
                    'NY',
                    '11213',
                    'USA'
                );
#插入某些查詢的結果
INSERT INTO customers(cust_id,
                cust_contact,
                cust_email,
                cust_name,
                cust_address,
                cust_city,
                cust_state,
                cust_zip,
                cust_country)
            SELECT cust_id,
                     cust_contact,
                    cust_email,
                    cust_name,
                    cust_address,
                    cust_city,
                    cust_state,
                    cust_zip,
                    cust_country
            FROM custnew;

/*
提升總體性能:
數據庫常常被多個客戶訪問,對處理什麼請求以及用什麼次序處理
進行管理是MySQL的任務。
INSERT操做可能很耗時(特別是有不少索引須要更新時),並且它可能
下降等待處理的 SELECT 語句的性能。
若是數據檢索是最重要的(一般是這樣),則你能夠經過在
INSERT 和 INTO 之間添加關鍵字 LOW_PRIORITY ,指示MySQL
下降 INSERT 語句的優先級。
 */
INSERT LOW_PRIORITY INTO
UPDATE LOW_PRIORITY
DELETE LOW_PRIORITY


#更新操做
UPDATE customers
SET  cust_name = 'The Fudds',
        cust_email = 'elmer@fudd.com'
WHERE cust_id = 10004;

#刪除操做
DELETE FROM customers
WHERE cust_id = 10006;

#刪除一表後重建表
TRUNCATE TABLE  

-------------------------------------------------------------------

#建立表
#指定默認值,多個主鍵
CREATE TABLE orderitems
(
    order_num   INT         NOT NULL,
    order_item   CHAR(10)   NOT NULL,
    quantity     INT          NOT NULL  DEFAULT 1,
    item_price   DECIMAL(8,2) NOT NULL,
    PRIMARY KEY(order_num, order_item)
) ENGINE=InnoDB;

/*
與其餘DBMS同樣, MySQL有一個具體管理和處理數據的內部引擎。
在你使用 CREATE TABLE 語句時,該引擎具體建立表,而在你使用 SELECT
語句或進行其餘數據庫處理時,該引擎在內部處理你的請求。多數時候,
此引擎都隱藏在DBMS內,不須要過多關注它。不一樣的是mysql打包了多種
引擎。

 InnoDB 是一個可靠的事務處理引擎(參見第26章)
,它不支持全文
本搜索;
 MEMORY 在功能等同於 MyISAM ,但因爲數據存儲在內存(不是磁盤)
中,速度很快(特別適合於臨時表)
;
 MyISAM 是一個性能極高的引擎,它支持全文本搜索(參見第18章)
,但不支持事務處理。
 */

#注意:
#混用引擎類型有一個大缺陷。外鍵不能跨引擎,即便用一
#個引擎的表不能引用具備使用不一樣引擎的表的外鍵。

------------------------------------------------------------------

#更新表結構,一般修改表結構是錯誤的,由於可能影響多處接口。 

ALTER TABLE vendors
ADD vend_phone CHAR(20);

ALTER TABLE vendors
DROP CIOLUMN vend_phone;

#ALTER TABLE 一種常見的用途就是定義外鍵。
ALTER TABLE orderitems
ADD CONSTRAINT fk_orderitems_orders
FOREIGN KEY (order_num) REFERENCES orders (order_num);

#刪除表

DROP TABLE customers;

#重命名

RENAME TABLE backup_customers TO customers,
                backup_vendors TO vendors,
                backup_products TO products;
---------------------------------------------------------------------
/*
視圖
視圖是虛擬的表,自己並不包含任何列或數據,它包含的是SQL查詢。

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

簡單地認爲視圖就是包裝SQL查詢語句的包,每次執行都會調用相應的
查詢語句塊。
*/
CREATE VIEW productcustomers AS
SELECT cust_name, cust_contact, prod_id
FROM customers, orders, orderitems
WHERE customers.cust_id = orders.cust_id
AND orderitems.order_num = orders.order_num;

SELECT cust_name, cust_contact
FROM productcustomers
WHERE prod_id = 'TNT2';

#格式化檢索出的數據
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country),')')
AS vend_title
FROM vendors
ORDER BY vend_name;

CREATE VIEW vendorlocations AS
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country),')')
AS vend_title
FROM vendors
ORDER BY vend_name;

#用視圖過濾不想要的視圖
CREATE VIEW customeremaillist AS
SELECT cust_id, cust_name, cust_email
FROM customers
WHERE cust_email IS NOT NULL;

#使用視圖與計算字段
SELECT prod_id,
        quantity,
        item_price,
        quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num = 20005;

----------------------------------------------------------------

/*
存儲過程用於將SQL操做綁定成一個執行的最小子集,要麼一塊兒成功,
要麼一塊兒失敗。

 */
#建立存儲過程
CREATE PROCEDURE productpricing()
BEGIN
    SELECT Avg(prod_price) AS priceaverage
    FROM products;
END;

#若是命令行實用程序要解釋存儲過程自身內的 ; 字符,
#則它們最終不會成爲存儲過程的成分,這會使存儲過程當中的SQL出現句法
#錯誤。
#使用DELIMITER 來臨時標記命令行實行程序的語句分隔符
DELIMITER //

CREATE PROCEDURE productpricing()
BEGIN
    SELECT Avg(prod_price) AS priceaverage
    FROM products;
END //

DELIMITER ;

#調用存儲過程

CALL productpricing();

#刪除儲存過程
DROP PROCEDURE productpricing;

#帶變量的存儲過程
#通常存儲過程是不返回結果的,而是把結果存儲至變量之中。
#OUT參數用於存儲結果 
#IN參數用於傳遞參數

CREATE PROCEDURE productpricing(
        OUT pl DECIMAL(8,2),
        OUT ph DECIMAL(8,2),
        OUT pa DECIMAL(8,2)
)
BEGIN
    SELECT Min(prod_price)
    INTO pl
    FROM products;
    SELECT Max(prod_price)
    INTO ph
    FROM products;
    SELECT Avg(prod_price)
    INTO pa
    FROM products;
END;

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

SELECT @pricelow,@pricehigh,@priceaverage;

----------------------------------------------------------------

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;

CALL ordertotal(20005, @total);

----------------------------------------------------------------
#存儲過程通常會添加業務規則

#下面一個存儲過程展現了下面幾個事物
#獲取訂單合計
#把營業稅有條件加入合計中
#返回合計

DELIMITER //
#Name : ordertotal
#Parameters: onumber = order number
#              taxable  = 0 if not taxable, 1 if taxable
#              ototal    = order total variable
CREATE PROCEDURE ordertotal(
    IN onumber INT,
    IN taxable BOOLEAN,
    OUT ototal DECIMAL(8,2)
)COMMENT 'Obtain order total,optionally adding tax.'
BEGIN

#Declare variable for total
DECLARE total DECIMAL(8,2);
#Declare tax percentage
DECLARE taxrate INT DEFAULT 6;

#Get the order total
SELECT Sum(item_price*quantity)
FROM orderitems
WHERE order_num = onumber
INTO total;

#Is this taxable?
IF taxable THEN
#Yes,so add taxrate to the total
    SELECT total+(total/100*taxrate) INTO total;
END IF;
#And finally,save to out variable
SELECT total INTO ototal;
END //
DELIMITER ;

CALL ordertotal(20005, 0, @total);
SELECT @total;
CALL ordertotal(20006, 0, @total);
SELECT @total;

#顯示用來建立一個存儲過程的CREATE語句
SHOW CREATE PROCEDURE ordertotal;
#獲取什麼時候由誰建立等詳細信息
SHOW PROCEDURE STATUS LIKE 'ordertotal';

-----------------------------------------------------------------
/*
遊標(cursor)是一個存儲在Mysql服務器上的數據庫查詢,它不是一條
SELECT語句,而是被該語句檢索出來的結果集。在存儲了遊標以後,
應用程序能夠根據須要滾動或瀏覽其中的數據。
注意,mysql的遊標只能做用於存儲過程(和函數)。
 */
CREATE PROCEDURE processorders()
BEGIN
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FROM orders;

    OPEN ordernumbers;
    CLOSE ordernumbers;
END;

#這個過程建立遊標,打開和關閉遊標

CREATE PROCEDURE processorders()
BEGIN
    DECLARE o INT;
    #定義遊標
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FROM orders;
    #打開遊標
    OPEN ordernumbers;
    #抓取數據
    FETCH ordernumbers INTO o;
    #關閉遊標
    CLOSE ordernumbers;
END;


#如下是遊標的實際應用:
CREATE PROCEDURE processorders()
BEGIN
    
    DECLARE done BOOLEAN DEFAULT 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;
    /*
    這條語句定義了一個 CONTINUE HANDLER ,它是在條件出現時被執行
    的代碼。這裏,它指出當 SQLSTATE '02000' 出現時, SET done=1。 
    SQLSTATE'02000' 是一個未找到條件,當 REPEAT 因爲沒有更多的行
    供循環不能繼續時,出現這個條件。
     */
    CREATE TABLE IF NOT EXISTS ordertotals
        (order_num INT, total DECIMAL(8,2));

    OPEN ordernumbers;

    REPEAT

        FETCH ordernumbers INTO o;

        CALL ordertotal(o, 1, t);

        INSERT INTO ordertotals(order_num, total)
        VALUES(o,t);

    UNTIL done END REPEAT;

    CLOSE ordernumbers;

END;

SELECT * FROM ordertotals;
/*輸出結果
+-----------+---------+
| order_num | total   |
+-----------+---------+
|     20005 |  158.86 |
|     20009 |   40.78 |
|     20006 |   58.30 |
|     20007 | 1060.00 |
|     20008 |  132.50 |
|     20008 |  132.50 |
+-----------+---------+
*/

/*
觸發器是Mysql響應如下任意語句而自動執行的一條Mysql語句或者是
位於BEGIN和END之間的一組語句。
DELETE
INSERT
UPDATE
 */
#建立觸發器
CREATE TRIGGER newproduct AFTER INSERT ON products
FOR EACH ROW SELECT 'Product added' INTO @temp;
#當對products表進行插入時觸發,對每一行插入後輸出Product added.

#每一個表最多支持6個觸發器(每條INSERT,UPDATE和DELETE的以前和以後)。
#單一觸發器不能與多個事件或多張表關聯。

#刪除觸發器
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 INTO @temp;
#插入數據至orders表後輸出插入數據的order_num列屬性。

INSERT INTO orders(order_date, cust_id)
VALUES(NOW(), 10001);


/*
DELETE觸發器

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

#刪除
#在舊訂單數據刪除前插入新表,保存數據。
CREATE TRIGGER deleteorder 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;

/*
UPDATE觸發器

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

#更改NEW的值
CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors
FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);

-------------------------------------------------------------------------
/*
事務管理——要麼一塊兒完成,要麼一塊兒失敗;
理清幾個概念
 事務( transaction )指一組SQL語句;
 回退( rollback )指撤銷指定SQL語句的過程;
 提交( commit )指將未存儲的SQL語句結果寫入數據庫表;
 保留點( savepoint )指事務處理中設置的臨時佔位符(place-
holder),你能夠對它發佈回退(與回退整個事務處理不一樣)。
*/
SELECT * FROM ordertotals;
START TRANSACTION;
DELETE FROM ordertotals;
SELECT * FROM ordertotals;
ROLLBACK;
SELECT * FROM ordertotals;

#ROLLBACK 只能在一個事務處理內使用,也就是在一條
#START TRANSACTION以後

#通常的MySQL語句都是直接針對數據庫表執行和編寫的。這就是
#所謂的隱含提交(implicit commit),即提交(寫或保存)操做是自動
#進行的。但在事務處理塊中,提交須要進行明確的提交。
START TRANSACTION;
DELETE FROM orderitems WHERE order_num = 20010;
DELETE FROM orders WHERE order_num = 20010;
COMMIT;

#複雜的事務處理可能須要部分提交或回退,能夠用保留點來進行操做。

SAVEPOINT delete1;

ROLLBACK TO delete1;

RELEASE SAVEPOINT;

#讓事務不自動提交
SET autocommit = 0;

---------------------------------------------------------------------
/*
全球化和本地化
 字符集爲字母和符號的集合;
 編碼爲某個字符集成員的內部表示;
 校對爲規定字符如何比較的指令
*/
#使用何種字符集和校對的決定在服務器、數據庫和表級進行。
SHOW CHARACTER SET;

#查看所支持校對的完整列表,_ci不區分大小寫,_cs區分大小寫
SHOW COLLATION;

#表級
#爲了給表指定字符集和校對,可以使用帶子句的 CREATE TABLE
#不多會有服務器和數據庫級別的字符集和校對的設置。
CREATE TABLE mytable(
    columnn1 INT,
    columnn2 VARCHAR(10)
)DEFAULT CHARACTER SET hebrew
COLLATE hebrew_general_ci;

#查看table的字符集和校對
SHOW TABLE STATUS FROM GoodtoKnowMysql LIKE '%order%';

----------------------------------------------------------------------
/*
安全管理
訪問控制——給用戶提供他們所需的訪問權,且僅提供他們所需的訪問權。

Mysql Administrator 提供一個圖形用戶界面,可用來管理用戶及
帳號權限。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
在現實世界
的平常工做中,決不能使用 root 。應該建立一系列的帳號,有的用於管
理,有的供用戶使用,有的供開發人員使用,等等。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 */

#查看用戶
USE mysql;
SELECT user FROM user;

#建立用戶
CREATE USER Rudolph_Browne IDENTIFIED BY '**********';

#重命名用戶
RENAME USER Rudolph_Browne TO Harry;

#刪除用戶
DROP USER Harry;

#設置訪問權限

#查看用戶權限
SHOW GRANTS FOR Rudolph_Browne;

#授予權限——GRANT
GRANT SELECT ON GoodtoKnowMysql.* TO Rudolph_Browne;
#容許用戶在GoodtoKnowMysql數據庫中的全部表進行SELECT操做;
GRANT ALL ON GoodtoKnowMysql.* TO Rudolph_Browne;
#授予全部權限

#撤銷權限
REVOKE SELECT ON GoodtoKnowMysql.* FROM Rudolph_Browne;

/*
GRANT 和 REVOKE 可在幾個層次上控制訪問權限:
 整個服務器,使用 GRANT ALL 和 REVOKE ALL;
 整個數據庫,使用 ON database.*;
 特定的表,使用 ON database.table;
 特定的列;
 特定的存儲過程。
 */
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#權限表詳情請參見手冊或者Mysql必知必會 p213
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

#簡化屢次受權
GRANT SELECT, INSERT, UPDATE, DELETE ON GoodtoKnowMysql.* TO Rudolph_Browne;

#更改用戶口令
SET PASSWORD FOR Rudolph_Browne = Password('*********');

#更改本身口令
SET PASSWORD =  Password('**********');

---------------------------------------------------------------------
#數據庫維護

/*
備份數據
像全部數據同樣,MySQL的數據也必須常常備份。因爲MySQL數據
庫是基於磁盤的文件,普通的備份系統和例程就能備份MySQL的數據。
可是,因爲這些文件老是處於打開和使用狀態,普通的文件副本備份不
必定老是有效。

下面列出這個問題的可能解決方案。
 使用命令行實用程序 mysqldump 轉儲全部數據庫內容到某個外部
文件。在進行常規備份前這個實用程序應該正常運行,以便能正
確地備份轉儲文件。
 可用命令行實用程序 mysqlhotcopy 從一個數據庫複製全部數據
(並不是全部數據庫引擎都支持這個實用程序)
。
 可使用MySQL的 BACKUP TABLE 或 SELECT INTO OUTFILE 轉儲所
有數據到某個外部文件。這兩條語句都接受將要建立的系統文件
名,此係統文件必須不存在,不然會出錯。數據能夠用 RESTORE
TABLE 來複原。
*/

#首先刷新未寫數據 爲了保證全部數據被寫到磁盤(包括索引
#數據),可能須要在進行備份前使用 FLUSH TABLES 語句。#導出整個數據庫mysqldump -u 用戶名 -p 數據庫名 > 導出的文件名 #導出數據庫中指定表mysqldump -u 用戶名 -p 數據庫名 --tables table_name1 table_name2 table_name3 > db_script.sql
相關文章
相關標籤/搜索