#登陸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