安裝
mac:去官網下載安裝包,安裝
安裝 -> 系統偏好設置 –> 點擊最下方mysql start mysql server /usr/local/MySQL/bin/mysql -u root -p *******
mysql引擎
- InnoDB是一個可靠的事務處理引擎(參見第26章),它不支持全文本搜索;
- MEMORY在功能等同於MyISAM,但由於數據存儲在內存(不是磁盤)中,速度很快(特別適合於臨時表);
- MyISAM是一個性能極高的引擎,它支持全文本搜索(參見第18章),但不支持事務處理。
- 混用引擎類型。
where
數據庫中常用的是where關鍵字,用於在初始表中篩選查詢,獲取指定記錄。它是一個約束聲明,用於約束數據,在返回結果集之前起作用。
分組數據 group by
創建分組
分組,對select查詢出來的結果集按照一個或多個列對結果集進行分組。,獲得一組組的集合,然後從每組中取出一個指定字段或者表達式的值。在分組的列上我們可以使用 COUNT, SUM, AVG,等函數。
SELECT column_name, function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
WITH ROLLUP 可以實現在分組統計數據基礎上再進行相同的統計(SUM,AVG,COUNT…)。
比如,查詢每個人登陸總次數,
SELECT coalesce(name, '總數'), SUM(signin) as signin_count FROM employee_tbl GROUP BY name WITH ROLLUP;
- GROUP BY子句可以包含任意數目的列。這使得能對分組進行嵌套, 爲數據分組提供更細緻的控制。
- 如果在GROUP BY子句中嵌套了分組,數據將在最後規定的分組上 進行彙總。換句話說,在建立分組時,指定的所有列都一起計算(所以不能從個別的列取回數據)。
- GROUP BY子句中列出的每個列都必須是檢索列或有效的表達式(但不能是聚集函數)。如果在SELECT中使用表達式,則必須在 GROUP BY子句中指定相同的表達式。不能使用別名。
- 除聚集計算語句外,SELECT語句中的每個列都必須在GROUP BY子 句中給出。
- 如果分組列中具有NULL值,則NULL將作爲一個分組返回。如果列 中有多行NULL值,它們將分爲一組。
- GROUP BY子句必須出現在WHERE子句之後,ORDER BY子句之前。
過濾分組 having
SELECT cust_id, count(*) as orders from orders groupby cust_id having count(*) > 2;
用於對where和group by查詢出來的分組經行過濾,查出滿足條件的分組結果。它是一個過濾聲明,是在查詢返回結果集以後對查詢結果進行的過濾操作。
MySQL爲此目的提供了另外的子 句,那就是HAVING子句。HAVING非常類似於WHERE。事實上,目前爲止所 學過的所有類型的WHERE子句都可以用HAVING來替代。唯一的差別是 WHERE過濾行,而HAVING過濾分組。WHERE在數據 分組前進行過濾,HAVING在數據分組後進行過濾。
執行順序
select -> from –> where –> group by –> having –> order by -> limit
大小寫
mysql默認不區分大小寫,可以通過 binaer關鍵字指定;
select prod_name from products WHERE prod_name REGEXP BINARY 'JetPack .000';
and / or
更新數據 update
語句可用來修改表中的數據, 簡單來說基本的使用形式爲
update 表名稱 set 列名稱=新值 where 更新條件;
以下是在表 students 中的實例:將 id 爲 5 的手機號改爲默認的 - :
update students set tel=default where id=5;
將所有人的年齡增加 1:
update students set age=age+1;
將手機號爲 13288097888 的姓名改爲 "小明", 年齡改爲 19:
update students set name="小明", age=19 where tel="13288097888";
當我們需要將字段中的特定字符串批量修改爲其他字符串時,可已使用以下操作:
UPDATE table_name SET field=REPLACE(field, 'old-string', 'new-string') [WHERE Clause];
以下實例將更新 runoob_id 爲 3 的runoob_title 字段值的 "C++" 替換爲 "Python":
UPDATE runoob_tbl SET runoob_title = REPLACE(runoob_title, 'C++', 'Python') where runoob_id = 3;
delete
刪除 MySQL 數據表中的記錄,
delete,drop,truncate
都有刪除表的作用,區別在於:
- 1、delete 和 truncate 僅僅刪除表數據,drop 連表數據和表結構一起刪除,打個比方,delete 是單殺,truncate 是團滅,drop 是把電腦摔了。
- 2、delete 是 DML 語句,操作完以後如果沒有不想提交事務還可以回滾,truncate 和 drop 是 DDL 語句,操作完馬上生效,不能回滾,打個比方,delete 是發微信說分手,後悔還可以撤回,truncate 和 drop 是直接扇耳光說滾,不能反悔。
- 3、執行的速度上,drop>truncate>delete,打個比方,drop 是神舟火箭,truncate 是和諧號動車,delete 是自行車。
delete from customers where cust_id = 10086;
like
匹配/模糊匹配,會與 % 和 _ 結合使用。SQL LIKE 子句中使用百分號 %字符來表示任意字符,類似於UNIX或正則表達式中的星號 *。如果沒有使用百分號 %, LIKE 子句與等號 = 的效果是一樣的。將 runoob_tbl 表中獲取 runoob_author 字段中以 COM 爲結尾的的所有記錄:
SELECT * from runoob_tbl WHERE runoob_author LIKE '%COM';
- '%a' //以a結尾的數據
- 'a%' //以a開頭的數據
- '%a%' //含有a的數據
- 'a' //三位且中間字母是a的
- '_a' //兩位且結尾字母是a的
- 'a_' //兩位且開頭字母是a的
在 where like 的條件查詢中,SQL 提供了四種匹配方式。
- %:表示任意 0 個或多個字符。可匹配任意類型和長度的字符,有些情況下若是中文,請使用兩個百分號(%%)表示。
- _:表示任意單個字符。匹配單個任意字符,它常用來限制表達式的字符長度語句。
- []:表示括號內所列字符中的一個(類似正則表達式)。指定一個字符、字符串或範圍,要求所匹配對象爲它們中的任一個。
- [^] :表示不在括號所列之內的單個字符。其取值和 [] 相同,但它要求所匹配對象爲指定字符以外的任一個字符。
查詢內容包含通配符時,由於通配符的緣故,導致我們查詢特殊字符 “%”、“_”、“[” 的語句無法正常實現,而把特殊字符用 “[ ]” 括起便可正常查詢。
regexp 匹配正則表達式
查找name字段中以'st'爲開頭的所有數據:
SELECT name FROM person_tbl WHERE name REGEXP '^st';
查找name字段中以'.t'爲開頭的所有數據:
SELECT name FROM person_tbl WHERE name REGEXP '^\\.t'; --匹配特殊字符 .t
like 和 regexp 區別
// todo
假設目前products如下:
prod_name |
---|
JetPack 1000 |
JetPack 2000 |
select prod_name from products where prod_name like '1000' order by prod_name; -- 無結果
select prod_name from products where prod_name regexp '1000' order by prod_name; -- 返回 JetPack 1000
組合查詢 UNION
有兩種基本情況,其中需要使用組合查詢:
- 在單個查詢中從不同的表返回類似結構的數據;
- 對單個表執行多個查詢,按單個查詢返回數據。
用於將不同表中相同列中查詢的數據展示出來;(不包括重複數據);
MySQL UNION 操作符用於連接兩個以上的 SELECT 語句的結果組合到一個結果集合中。多個 SELECT 語句會刪除重複的數據。使用形式如下:
-- SELECT 列名稱 FROM 表名稱 UNION SELECT 列名稱 FROM 表名稱 ORDER BY 列名稱;
-- 查詢價格小於等於5的所有物品的一個列表
select vend_id, prod_name, prod_price from products where prod_price <= 5 union select vend_id, prod_name, prod_price from products where vend_id in (1001, 1002) order by prod_price;
select vend_id, prod_name, prod_price from products where prod_price <= 5 or vend_id in (1001, 1002) order by prod_price;
UNION DISTINCT: 可選,刪除結果集中重複的數據。默認情況下 UNION 操作符已經刪除了重複數據,所以 DISTINCT 修飾符對結果沒啥影響。
UNION ALL: 可選,返回所有結果集,包含重複數據;
- UNION必須由兩條或兩條以上的SELECT語句組成,語句之間用關鍵字UNION分隔(因此,如果組合4條SELECT語句,將要使用3個 UNION關鍵字)。
- UNION中的每個查詢必須包含相同的列、表達式或聚集函數(不過各個列不需要以相同的次序列出)。
- 列數據類型必須兼容:類型不必完全相同,但必須是DBMS可以隱含地轉換的類型(例如,不同的數值類型或不同的日期類型)。
order by
對查詢結果進行排序,DESC 降序,ASC 升序; 默認情況下,它是按升序排列。
聯結表 join
通過外鍵聯結
創建聯結
---在引用的列可能出現二義性時,必須使用完 全限定列名(用一個點分隔的表名和列名)。應該保證所有聯結都有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 inner join products on vendors.vend_id = products.vend_id order by vend_name, prod_name;
---笛卡兒積(cartesian product) 由沒有聯結條件的表關係返回的結果爲笛卡兒積。檢索出的行的數目將是第一個表中的行數乘 以第二個表中的行數。
select vend_name, prod_name, prod_price from vendors, products order by vend_name, prod_name;
-- 顯示編號爲20005的訂單中的物品
select vend_name, prod_name, prod_price, quantity from vendors, orderitems, products where vendors.vend_id = products.vend_id and orderitems.prod_id = products.prod_id and order_num = 20005;
inner join(內連接,或等值連接)
獲取兩個表中字段匹配關係的記錄。連接以上兩張表來讀取runoob_tbl表中所有runoob_author字段在tcount_tbl表對應的runoob_count字段值,
SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
兩個表的交集。
自連接
--找出商品ID爲DTNTR的供應商的所有商品,使用別名
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 c.*, o.order_num, o.order_date, oi.prod_id, oi.quantity, oi.item_price 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 = 'fb';
外部聯結
聯結包含了那些在相關表中沒有關聯行的行。這種類型的聯結稱爲外部聯結。
-- 檢索所有客戶及其訂單 --> 內部聯結
select customers.cust_id, orders.order_num from customers inner join orders on customers.cust_id = orders.cust_id;
-- 檢索所有客戶,包括那些沒有訂單的客戶,不存在的會顯示null --> 內部聯結
select customers.cust_id, orders.order_num from customers left outer join orders on customers.cust_id = orders.cust_id;
外部聯結 -- left join (左連接)
獲取左表所有記錄,即使右表沒有對應匹配的記錄。返回座標所有數據和左右表的交集數據;
外部聯結 -- right join (右連接)
與 LEFT JOIN 相反,用於獲取右表所有記錄,即使左表沒有對應匹配的記錄。
帶聚集函數的聯結
-- 檢索所有客戶及每個客戶所下的訂單數
select customers.cust_id, customers.cust_name, 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_id, customers.cust_name, 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;
null 處理
在 MySQL 中,NULL 值與任何其它值的比較(即使是 NULL)永遠返回 NULL,即 NULL = NULL 返回 NULL 。MySQL 中處理 NULL 使用 IS NULL 和 IS NOT NULL 運算符。
SELECT * from runoob_test_tbl WHERE runoob_count IS NOT NULL;
事務 transaction
主要用於處理操作量大,複雜度高的數據;在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。事務處理可以用來維護數據庫的完整性,保證成批的 SQL 語句要麼全部執行,要麼全部不執行。事務用來管理 insert,update,delete 語句一般來說,事務是必須滿足4個條件(ACID)::原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、持久性(Durability)。
- 事務(transaction)指一組SQL語句;
- 回退(rollback)指撤銷指定SQL語句的過程;
- 提交(commit)指將未存儲的SQL語句結果寫入數據庫表;
- 保留點(savepoint)指事務處理中設置的臨時佔位符(place-holder),你可以對它發佈回退(與回退整個事務處理不同)。
start transaction;
set autocommit = 0; --不自動提交更改
operation ZZZ;
rollback; -- 直接回滾
operations XXX;
savepoint A;
operations YYY;
commit;
rollback to A;
savepoint B;
release savepoint B; --刪除指定savepoint
alter
(add 新增列、drop 刪除列、modify 修改列類型、change 修改列名稱、alter 修改字段默認值、rename 修改表名)
修改數據表名或者修改數據表字段;刪除表的 i 字段:
ALTER TABLE testalter_tbl DROP i;
ADD 子句來向數據表中添加列:
ALTER TABLE testalter_tbl ADD i INT;
可以再語句後面添加 FIRST 或者 AFTER columnName 來指定新增列的位置。
ALTER TABLE testalter_tbl ADD i INT AFTER c;
如果需要修改字段類型及名稱, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。
ALTER TABLE testalter_tbl MODIFY c CHAR(10);
ALTER TABLE testalter_tbl CHANGE i j BIGINT;
如果需要修改字段默認值,
ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000;
修改數據表類型:
ALTER TABLE testalter_tbl ENGINE = MYISAM;
修改表名:
ALTER TABLE testalter_tbl RENAME TO alter_tbl;
定義外鍵:
ALTER TABLE orderitems add constraint fk_orderitems_orders foreign key(order_num) references orders (order_num);
index 索引
索引可以大大提高MySQL的檢索速度;索引分單列索引和組合索引。單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。組合索引,即一個索引包含多個列。實際上,索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄。上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件。建立索引會佔用磁盤空間的索引文件。
create index indexName on table_name (columnName); // 創建
ALTER table tableName ADD INDEX indexName(columnName) // 修改表結構
CREATE TABLE mytable(ID INT NOT NULL, username VARCHAR(16) NOT NULL,INDEX [indexName] (username(length))); // 創建時指定
DROP INDEX [indexName] ON mytable; // 刪除索引
複製表
SHOW CREATE TABLE tableName; 顯示 create table 的語句詳情,複製粘貼即可。
CREATE TABLE targetTable LIKE sourceTable;
INSERT INTO targetTable SELECT * FROM sourceTable;
元數據 查詢結果信息、數據庫和數據表信息、mysql服務器信息;
導出數據
select * from tableName into outfile 'a.txt';
導入數據
load data infile;
計算字段
存儲在表中的數據都不是應用程序所需要的。 我們需要直接從數據庫中檢索出轉換、計算或格式化過的數據;而不是檢索出數據,然後再在客戶機應用程序或報告程序中重新格式化。
拼接 concat
將值連結到一起構成單個值。
select concat(prod_name,' (',prod_id, ')') from products order by prod_name; --商品(id)
RTrim
刪除值右側的所有空格。
select concat(RTrim(prod_name),' (', RTrim(prod_id), ')') from products order by prod_name; --商品(id)
LTrim
刪除值左側的所有空格。
select concat(LTrim(prod_name),' (', LTrim(prod_id), ')') from products order by prod_name; --商品(id)
Trim
刪除值左右兩側的所有空格。
select concat(Trim(prod_name),' (', Trim(prod_id), ')') from products order by prod_name; --商品(id)
爲計算字段新起別名
比如將列名從 concat(Trim(prod_name),' (', Trim(prod_id), ')') 改爲 prod_title。
select concat(Trim(prod_name),' (', Trim(prod_id), ')') as prod_title from products order by prod_name; --商品(id)
執行算數計算
主要包括 +、-、*、/、abs()、Now()……
select prod_name, quantity, item_price, quantity * item_price as expanded_price from products order by prod_name = 'test'; --該商品的
數據處理函數(MYSQL必知必會-第11章)
https://forta.com/books/0672327120/
select prod_name, Upper(prod_name) from products; --轉換成大寫
文本函數 | 說明 |
---|---|
Left() | 返回串左邊的字符 |
Right() | 返回串右邊的字符 |
Length() | 返回串的長度 |
Locate() | 找出串的一個子串 |
Lower() | 將串轉換爲小寫 |
Upper() | 將串轉換爲大寫 |
Soundex() | 返回串的SOUNDEX值 |
SubString() | 返回子串的字符 |
日期函數 | 說明 |
DateDiff() | 計算兩個日期之差 |
Day() | 返回一個日期的天數部分 |
Year() | 返回一個日期的年份部分 |
CurTime() | 返回當前時間 |
數值處理函數 | 說明 |
Abs() | 返回一個數的絕對值 |
Cos() | 返回一個角度的餘弦 |
Exp() | 返回一個數的指數值 |
Sqrt() | 返回一個數的平方根 |
註釋:SOUNDEX是一個將任何文本串轉換爲描述其語音表示的字母數字模式的算法。SOUNDEX考慮了類似的發音字符和音節,使得能對串進行發音比較而不是字母比較。雖然 SOUNDEX不是SQL概念,但MySQL(就像多數DBMS一樣)都提供對SOUNDEX的支持。
MySQL使用的日期格式。無論你什麼時候指定一個日期,不管是插入或更新表值還是用WHERE子句進行過濾,日期必須爲 格式yyyy-mm-dd。
彙總數據 - 聚集函數
函數 | 說明 |
---|---|
avg() | 返回某列平均數 |
count() | 返某列行數 |
max() | 返回某列最大值 |
min() | 返回某列最小值 |
sum() | 返回某列和 |
select avg(distinct prod_price) from products where vend_id = 1003;
訂單數據庫
本節示例的數據庫描述:該數據庫表是關係表。
vendors表:存儲銷售產品的供應商
列 | 說明 |
---|---|
vend_id | 唯一的供應商ID,自動增量的主鍵 |
vend_name | 供應商名 |
vend_address | 供應商的地址 |
vend_city | 供應商的城市 |
vend_state | 供應商的州 |
vend_zip | 供應商的郵政編碼 |
vend_country | 供應商的國家 |
products 表:包含產品目錄,每行一個產品
列 | 說明 |
---|---|
prod_id | 唯一的產品ID |
vend_id | 產品供應商ID(關聯到vendors表中的vend_id) |
prod_name | 產品名 |
prod_price | 產品價格 |
prod_desc | 產品描述 |
customers 表:存儲所有顧客的信息
列 | 說明 |
---|---|
cust_id | 唯一的顧客ID,自動增量的主鍵 |
cust_name | 顧客名 |
cust_address | 顧客的地址 |
cust_city | 顧客的城市 |
cust_state | 顧客的州 |
cust_zip | 顧客的郵政編碼 |
cust_country | 顧客的國家 |
cust_contact | 顧客的聯繫名 |
cust_email | 顧客的聯繫email地址 |
orders 表:儲顧客訂單(但不是訂單細節)。每個訂單唯一地編號 (order_num列)。訂單用cust_id列(它關聯到customer表的顧客唯一ID)與相應的顧客關聯。
列 | 說明 |
---|---|
order_num | 唯一訂單號,自動增量的主鍵 |
order_date | 訂單日期 |
cust_id | 訂單的顧客ID,(關係到customers表的 cust_id) |
orderitems 表:存儲每個訂單中的實際物品,每個訂單的每個物品佔一行。order_num和order_item作爲其主鍵,prod_id上定義外鍵,關聯它到products 的prod_id。
列 | 說明 |
---|---|
order_num | 訂單號(關聯到orders表的order_num) |
order_item | 訂單物品號(在某個訂單中的順序) |
prod_id | 產品ID(關聯到products表的prod_id) |
quantity | 物品數量 |
item_price | 物品價格 |
productnotes表:存儲與特定產品有關的註釋。並非所有產品都有相 關的註釋,而有的產品可能有許多相關的註釋。列note_text必須爲FULLTEXT搜索進行索引,由於這個表使用全文本搜索,因此必須指定ENGINE=MyISAM。
列 | 說明 |
---|---|
note_id | 唯一註釋ID,主鍵 |
prod_id | 產品ID(對應於products表中的prod_id) |
note_date | 增加註釋的日期 |
note_text | 註釋文本 |
子查詢
示例1:列出訂購物品 TNT2 的所有客戶
select * from customers where cust_id in
(select cust_id from orders where order_num in
(select order_num from orderitems where prod_id = 'TNT2'));
select * from customers, orders, orderitems where customers.cust_id = orders.cust_id and orderitems.order_num = orders.order_num and prod_id = 'TNT2';
在SELECT語句中,子查詢總是從內向外處理。子查詢一般用 IN 操作符結合使用,但是也可以用於測試 = <> 等。
示例2:需要顯示 customers 表中每個客戶的訂單總數。
-- 相關子查詢:涉及外部查詢的子查詢。任何時候只要列名可能有多義性,就必須使用這種語法。
-- 需要比較這兩個列以正確地把訂單與它們相應的顧客匹配,新生成了計算字段 orders
select cust_name, (select count(*) from orders where orders.cust_id = customers.cust_id) as orders from customers order by cust_name;
select cust_name, (select count(*) as order_num from orders where orders.cust_id = customers.cust_id group by cust_name) as orderss from customers order by cust_name;
- 第一句 第二句
+----------------+--------+ | +----------------+---------+
| cust_name | orders | | | cust_name | orderss |
+----------------+--------+ | +----------------+---------+
| Coyote Inc. | 2 | | | Coyote Inc. | 2 |
| E Fudd | 1 | | | E Fudd | 1 |
| Mouse House | 0 | | | Mouse House | NULL |
| Wascals | 1 | | | Wascals | 1 |
| Yosemite Place | 1 | | | Yosemite Place | 1 |
+----------------+--------+ +----------------+---------+
全文本搜索
MySQL 支持幾種基本的數據庫引擎。並非所有的引擎都支持本書所描述的全文本搜索。兩個最常使用的引擎爲MyISAM和InnoDB, 前者支持全文本搜索,而後者不支持。這就是爲什麼雖然本書 中創建的多數樣例表使用InnoDB,而有一個樣例表(productnotes表)卻使用MyISAM的原因。
LIKE關鍵字,它利用通配操作符匹配文本(和部分文 本)。使用LIKE,能夠查找包含特殊值或部分值的行。
正則表達式基於文本的搜索,作爲匹配列值的更進一步的介紹。使用正則表達式,可以編寫查找所需行的非常複雜的匹配模 式。
雖然這些搜索機制非常有用,但存在幾個重要的限制:
- 性能——通配符和正則表達式匹配通常要求MySQL嘗試匹配表中所有行(而且這些搜索極少使用表索引)。因此,由於被搜索行數不斷增加,這些搜索可能非常耗時。
- 明確控制——使用通配符和正則表達式匹配,很難(而且並不總是能)明確地控制匹配什麼和不匹配什麼。例如,指定一個詞必 須匹配,一個詞必須不匹配,而一個詞僅在第一個詞確實匹配的 情況下才可以匹配或者纔可以不匹配。
- 智能化的結果——雖然基於通配符和正則表達式的搜索提供了非 常靈活的搜索,但它們都不能提供一種智能化的選擇結果的方法。 例如,一個特殊詞的搜索將會返回包含該詞的所有行,而不區分 包含單個匹配的行和包含多個匹配的行(按照可能是更好的匹配 來排列它們)。類似,一個特殊詞的搜索將不會找出不包含該詞但 包含其他相關詞的行。
在使用 全文本搜索時,MySQL不需要分別查看每個行,不需要分別分析和處理每個詞。MySQL創建指定列中各詞的一個索引,搜索可以針對這些詞進行。這樣,MySQL可以快速有效地決定哪些詞匹配(哪些行包含它們),哪些詞不匹配,它們匹配的頻率,等等。
爲了進行全文本搜索,必須索引被搜索的列,而且要隨着數據的改 變不斷地重新索引。在對錶列進行適當設計後,MySQL會自動更新所有的索引和重新索引。
在索引之後,SELECT可與Match()和Against()一起使用以實際執行 搜索。
啓用全文本搜索支持
創建table的時候,對需要搜索的列添加 FULLTEXT。爲了進行全文本搜索, MySQL根據子句FULLTEXT(note_text)的指示對它進行索引。這裏的FULLTEXT索引單個列,如果需要也可以指定多個列。在定義之後,MySQL自動維護該索引。在增加、更新或刪除行時,索引隨之自動更新。
CREATE TABLE productnotes
(
note_id int NOT NULL AUTO_INCREMENT,
prod_id char(10) NOT NULL,
note_date datetime NOT NULL,
note_text text NULL ,
PRIMARY KEY(note_id),
FULLTEXT(note_text)
) ENGINE=MyISAM;
注意:不要在導入數據時使用FULLTEXT 更新索引要花時間,雖然不是很多,但畢竟要花時間。如果正在導入數據到一個新表, 此時不應該啓用FULLTEXT索引。應該首先導入所有數據,然後再修改表,定義FULLTEXT。這樣有助於更快地導入數據(而且使索引數據的總時間小於在導入每行時分別進行索引所需的總時間)。
進行全文本搜索
在索引之後,使用兩個函數Match()和Against()執行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表達式。
傳遞給Match()的值必須與FULLTEXT()定義中的相同。如果指定多個列,則必須列出它們(而且次序正確)。
select note_text from productnotes where note_te like '%rabit%';
select note_text from productnotes where note_te REGEXP BINARY 'rabit';
select note_text from productnotes where match(note_text) against('rabit'); -- 全文本搜索的一個重要部分就是對結果排序。具有較高等級的行先返回
-- todo
select note_text, match(note_text) against('rabit') as rank from productnotes; -- 所有行都被返回(因爲沒有WHERE子句),Match()和Against() 用來建立一個計算列(別名爲rank),此列包含全文本搜索計算出的等級值。等級由MySQL根據行中詞的數目、唯一詞的數目、整個索引中詞的總數以及包含該詞的行的數目計算出來。正如所見,不包含詞rabbit的行等級爲0(因此不被前一例子中的WHERE子句選擇)。確實包含詞rabbit 的兩個行每行都有一個等級值,文本中詞靠前的行的等級值比詞靠後的行的等級值高。
全文本搜索提供了簡單LIKE搜索不能提供的功能。而且,由於數據是索引的,全文本搜索還相當快。
使用查詢擴展
查詢擴展用來設法放寬所返回的全文本搜索結果的範圍。在使用查詢擴展時,MySQL對數據和索引進行兩遍掃描來完成搜索:
- 首先,進行一個基本的全文本搜索,找出與搜索條件匹配的所有 行;
- 其次,MySQL檢查這些匹配行並選擇所有有用的詞(我們將會簡要地解釋MySQL如何斷定什麼有用,什麼無用)。
- 再其次,MySQL再次進行全文本搜索,這次不僅使用原來的條件, 而且還使用所有有用的詞。
select note_text from productnotes where match(note_text) against('anvils');
select note_text from productnotes where match(note_text) against('anvils' with query expansion) ; --這次返回了7行。第一行包含詞anvils,因此等級最高。第二行與anvils無關,但因爲它包含第一行中的兩個詞(customer和recommend),所以也被檢索出來。第3行也包含這兩個相同的詞,但它們在文本中的位置更靠後且分開得更遠,因此也包含這一行,但等級爲第三。第三行確實也沒有涉及anvils(按它們的產品名)。
布爾文本搜索
select note_text from productnotes where match(note_text) against('anvils -rope*' in boolean mode); -- 匹配包含anvils但不包含任意以rope開始的詞的行
全文本布爾操作符
全文本布爾操作符 | 說 明 |
---|---|
+ | 包含,詞必須存在 |
- | 排除,詞必須不出現 |
> | 包含,而且增加等級值 |
< | 包含,且減少等級值 |
() | 把詞組成子表達式(允許這些子表達式作爲一個組被包含、排除、排列等) |
~ | 取消一個詞的排序值 |
* | 詞尾的通配符 |
"" | 定義一個短語(與單個詞的列表不一樣,它匹配整個短語以便包含或排除這個短語) |
視圖 view
視圖是虛擬的表。與包含數據的表不一樣,視圖只包含使用時動態檢索數據的查詢。
select * from customers, orders, orderitems where customers.cust_id = orders.cust_id and orderitems.order_num = orders.order_num and prod_id = 'TNT2';
此查詢用來檢索訂購了某個特定產品的客戶。任何需要這個數據的人都必須理解相關表的結構,並且知道如何創建查詢和對錶進行聯結。 爲了檢索其他產品(或多個產品)的相同數據,必須修改最後的WHERE子句。
現在,假如可以把整個查詢包裝成一個名爲productcustomers的虛擬表,則可以如下輕鬆地檢索出相同的數據:
select * from productcustomers where prod_id = 'TNT2';
productcustomers是一個視圖,作爲視圖,它不包含表中應該有的任何列或數據,它包含的是一個SQL查詢(與上面用以正確聯結表的相同的查詢)。
視圖應用場景:
- 重用SQL語句。
- 簡化複雜的SQL操作。在編寫查詢後,可以方便地重用它而不必知道它的基本查詢細節。
- 使用表的組成部分而不是整個表。
- 保護數據。可以給用戶授予表的特定部分的訪問權限而不是整個表的訪問權限。
- 更改數據格式和表示。視圖可返回與底層表的表示和格式不同的數據。
在視圖創建之後,可以用與表基本相同的方式利用它們。可以對視圖執行SELECT操作,過濾和排序數據,將視圖聯結到其他視圖或表,甚至能添加和更新數據。
視圖僅僅是用來查看存儲在別處的數據的一種設施。視圖本身不包含數據,因此它們返回的數據是從其他表中檢索出來的。在添加或更改這些表中的數據時,視圖將返回改變過的數據。
視圖的規則和限制:
- 與表一樣,視圖必須唯一命名(不能給視圖取與別的視圖或表相同的名字)。
- 對於可以創建的視圖數目沒有限制。
- 爲了創建視圖,必須具有足夠的訪問權限。這些限制通常由數據庫管理人員授予。
- 視圖可以嵌套,即可以利用從其他視圖中檢索數據的查詢來構造一個視圖。
- ORDER BY可以用在視圖中,但如果從該視圖檢索數據SELECT中也含有ORDER BY,那麼該視圖中的ORDER BY將被覆蓋。
- 視圖不能索引,也不能有關聯的觸發器或默認值。
- 視圖可以和表一起使用。例如,編寫一條聯結表和視圖的SELECT語句。
-- 創建視圖 create view viewname as sql語句;
create view productcustomers as select * from customers, orders, orderitems where customers.cust_id = orders.cust_id and orderitems.order_num = orders.order_num ;
-- 顯示視圖語句
show create view viewname;
-- 刪除視圖
drop view;
-- 更新視圖,並非所有視圖都是可更新的,視圖中有分組查詢、子查詢、聯結、並、聚集函數、distinct、導出操作的,不能那個更新
create or replace view viewname as XXX;
存儲過程
存儲過程簡單來說,就是爲以後的使用而保存的一條或多條MySQL語句的集合。可將其視爲批文件,雖然它們的作用不僅限於批處理。
使用存儲過程有3個主要的好處,即簡單、安全、高性能。
創建存儲過程
-- 返回產品平均價格的存儲過程
create procedure productpricing()
begin
select avg(prod_price) as proceaverage from products;
end;
-- 傳參版本,出參
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;
-- 入參版本
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);
select @total;
此存儲過程名爲 productpricing,用CREATE PROCEDURE productpricing()語句定義。如果存儲過程接受參數,它們將在()中列舉出來。此存儲過程沒有參數,但後跟的()仍然需要。BEGIN和END語句用來限定存儲過程體,過程體本身僅是一個簡單的SELECT語句。
執行存儲過程
CALL接受存儲過程的名字以及需要傳遞給它的任意參數。
call productpricing(@pricelow, @pricehigh, @priceaverage); --所有MySQL變量都必須以@開始
select @priceaverage;
執行名爲productpricing的存儲過程,它計算並返回產品的最低、最高和平均價格。
刪除存儲過程
存儲過程在創建之後,被保存在服務器上以供使用,直至被刪除。
drop procedure productpricing if exists;
使用遊標 cursor
不像多數DBMS,MySQL遊標只能用於 存儲過程(和函數)。
遊標用DECLARE語句創建(參見第23章)。DECLARE命名遊標,並定義相應的SELECT語句,根據需要帶WHERE和其他子句。例如,下面的語句定義了名爲ordernumbers的遊標,使用了可以檢索所有訂單的SELECT語句:
-- 穿件遊標
create procedure processorders()
begin
declare ordernumbers cursor
for
select order_num from orders;
end;
-- 打開遊標
open ordernumbers;
-- 關閉遊標
close ordernumbers;
存儲過程處理完成後,遊標就消失(因爲它侷限於存儲過程)。
CLOSE釋放遊標使用的所有內部內存和資源,因此在每個遊標 不再需要時都應該關閉。
觸發器
觸發器是MySQL響應以下任意語句而自動執行的一條MySQL語句(或位於BEGIN和END語句之間的一組語句):
- DELETE;
- INSERT;
- UPDATE。
其他MySQL語句不支持觸發器。
每個表每個事件每次只允許一個觸發器。因此,每個表最多支持6個觸發器(每條INSERT、UPDATE 和DELETE的之前和之後)。
在創建觸發器時,需要給出4條信息: - 唯一的觸發器名,觸發器名必須在每個表中唯一,但不是在每個數據庫中唯一;
- 觸發器關聯的表,只有表才支持觸發器,視圖不支持(臨時表也不支持);
- 觸發器應該響應的活動(DELETE、INSERT或UPDATE);
- 觸發器何時執行(處理之前或之後)。
create trigger newproduct after insert/update/delete on products for each row select 'product added';
create trigger newproduct before insert/update/delete on products for each row select 'product added';
drop trigger newproduct; --觸發器不能更新或覆蓋
create trigger用來創建名爲newproduct的新觸發器。觸發器可在一個操作發生之前或之後執行,這裏給出了AFTER INSERT, 所以此觸發器將在INSERT語句成功執行後執行。這個觸發器還指定FOR EACH ROW,因此代碼對每個插入行執行。在這個例子中,文本Product added將對每個插入的行顯示一次。
全球化和本地化
介紹MySQL處理不同字符集和語言的基礎知識。
數據庫表被用來存儲和檢索數據。不同的語言和字符集需要以不同的方式存儲和檢索。因此,MySQL需要適應不同的字符集(不同的字母和字符),適應不同的排序和檢索數據的方法。
MySQL支持衆多的字符集。爲查看所支持的字符集完整列表,使用以下語句: show character set; 這條語句顯示所有可用的字符集以及每個字符集的描述和默認校對。
查看所支持校對的完整列表 show collation;
安全管理
給用戶提供他們所需的訪問權,且僅提供他們所需的訪問權。這就是所謂的訪問控制,管理訪問控制需要創建和管理用戶賬號。
select * from user;
create user A identified by 'p@qqqqq'