安裝MySQL
添加mysql源
# rpm -Uvh http://repo.mysql.com//mysql57-community-release-el7-7.noarch.rpm
安裝mysql
# yum -y install mysql-community-server
啟動mysql並設置為開機自啟動服務
# chkconfig mysqld on # service mysqld start
檢查mysql服務狀態
# service mysqld status
第一次啟動mysql,會在日志文件中生成root用戶的一個隨機密碼,使用下面命令查看該密碼
# grep 'temporary password' /var/log/mysqld.log
修改root用戶密碼
# mysql -u root -p -h localhost Enter password: mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'Mysql-2016';
創建數據庫(數據庫名為:crashcourse)
mysql> create database crashcourse;
使用crashcourse數據庫
mysql> use crashcourse;
執行sql腳本(使用source命令)
mysql> source /root/MySQLCrashCourse/create.sql; mysql> source /root/MySQLCrashCourse/populate.sql;
查看可用數據庫的列表
mysql> show databases;
查看當前數據庫內可用表的列表
mysql> show tables;
顯示表列(表名:customers)
mysql> show columns from customers;
顯示服務器錯誤或警告消息
mysql> show errors; mysql> show warnings;
檢索數據
檢索單個列
mysql> select prod_name from products;
檢索多個列
mysql> select prod_id, prod_name, prod_price from products;
檢索所有列(除非你確實需要表中的每個列,否則最好別使用*通配符,因為會降低應用程序的性能)
mysql> select * from products;
檢索不同的行(使用distinct關鍵字)
mysql> select distinct vend_id from products;
限制結果
返回不多於5行 mysql> select prod_name from products limit 5; 檢索的開始行和行數 mysql> select prod_name from products limit 5,5;
使用完全限定的表名
mysql> select products.prod_name from crashcourse.products;
排序檢索數據
排序數據
mysql> select prod_name from products order by prod_name;
按多個列排序
mysql> select prod_id, prod_price, prod_name from products order by prod_price, prod_name;
指定排序方向(使用desc關鍵字,desc為倒序,默認是asc,正序)
mysql> select prod_id, prod_price, prod_name from products order by prod_price desc;
使用order by和limit的組合
mysql> select prod_price from products order by prod_price desc limit 1;
過濾數據
檢索單個值
mysql> select prod_name, prod_price from products where prod_name = 'fuses';
不匹配檢查
mysql> select vend_id, prod_name from products where vend_id != 1003;
范圍值檢查
mysql> select prod_name, prod_price from products where prod_price between 5 and 10;
空值檢查
mysql> select prod_name from products where prod_price is null;
數據過濾
and操作符
mysql> select prod_id, prod_price, prod_name from products where vend_id = 1003 and prod_price <= 10;
or操作符
mysql> select prod_name, prod_price from products where vend_id = 1003 or prod_id = 1003;
計算次序
mysql> select prod_name, prod_price from products where (vend_id = 1002 or vend_id = 1003) and prod_price >= 10;
in操作符
mysql> select prod_name, prod_price from products where vend_id in (1002,1003) order by prod_name;
not操作符
mysql> select prod_name, prod_price from products where vend_id not in (1002,1003) order by prod_name;
用通配符進行過濾
百分號(%)通配符(匹配0,1或多個字符)
mysql> select prod_id, prod_name from products where prod_name like 'jet%';
下划線(_)通配符(匹配1個字符)
mysql> select prod_id, prod_name from products where prod_name like '_ ton anvil';
用正則表達式進行搜索
基本字符匹配
mysql> select prod_name from products where prod_name regexp '.000' order by prod_name;
進行or匹配
mysql> select prod_name from products where prod_name regexp '1000|2000' order by prod_name;
匹配范圍
mysql> select prod_name from products where prod_name regexp '[1-5] Ton' order by prod_name;
匹配特殊字符(使用\\進行轉義)
mysql> select vend_name from vendors where vend_name regexp '\\.' order by vend_name;
匹配字符類
mysql> select prod_name from products where prod_name regexp '[[:digit:]]{4}' order by prod_name;
匹配多個實例
mysql> select prod_name from products where prod_name regexp '\\([0-9] sticks?\\)' order by prod_name;
定位符(^, $, [[:<:]], [[:>:]])
mysql> select prod_name from products where prod_name regexp '^[0-9\\.]' order by prod_name;
創建計算字段
拼接字段
mysql> select concat(vend_name, ' (', vend_country, ')') from vendors order by vend_name;
使用別名
mysql> select concat(rtrim(vend_name), ' (', rtrim(vend_country), ')') as vend_title from vendors order by vend_name;
執行算術計算
mysql> select prod_id, quantity, item_price, quantity*item_price as expanded_price from orderitems where order_num = 20005;
使用數據處理函數
文本處理函數
mysql> select vend_name, upper(vend_name) as vend_name_upcase from vendors order by vend_name;
mysql> select cust_name, cust_contact from customers where soundex(cust_contact) = soundex('Y Lie');
日期和時間處理函數
mysql> select cust_id, order_num from orders where date(order_date) between '2005-09-01' and '2005-09-30'; mysql> select cust_id, order_num from orders where year(order_date) = 2005 and month(order_date) = 9;
匯總數據
avg()函數
mysql> select avg(prod_price) as avg_price from products;
count()函數
mysql> select count(*) as num_cust from customers;
max()函數
mysql> select max(prod_price) as max_price from products;
min()函數
mysql> select min(prod_price) as min_price from products;
sum()函數
mysql> select sum(quantity) as items_ordered from orderitems where order_num = 20005; mysql> select sum(item_price*quantity) as total_price from orderitems where order_num = 20005;
聚合不同的值
mysql> select avg(distinct prod_price) as avg_price from products where vend_id = 1003;
組合聚集函數
mysql> 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;
分組數據
創建分組
mysql> select vend_id, count(*) as num_prods from products group by vend_id;
過濾分組(使用having關鍵字)
mysql> select cust_id, count(*) as orders from orders group by cust_id having count(*) >= 2; mysql> select vend_id, count(*) as num_prods from products where prod_price >= 10 group by vend_id having count(*) >= 2;
分組和排序
mysql> select order_num, sum(quantity*item_price) as ordertotal
from orderitems
group by order_num
having sum(quantity*item_price) >= 50
order by ordertotal;
使用子查詢
利用子查詢進行過濾
mysql> select cust_name, cust_contact
from customers
where cust_id in (select cust_id
from orders
where order_num in (select order_num
from orderitems
where prod_id = 'TNT2'));
作為計算字段使用子查詢
mysql> select cust_name, cust_state,
(select count(*)
from orders
where orders.cust_id = customers.cust_id) as orders
from customers
order by cust_name;
聯結表
創建聯結
mysql> select vend_name, prod_name, prod_price
from vendors, products
where vendors.vend_id = products.vend_id
order by vend_name, prod_name;
內部聯結
mysql> select vend_name, prod_name, prod_price
from vendors inner join products
on vendors.vend_id = products.vend_id;
聯結多個表
mysql> 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';
創建高級聯結
使用別名
mysql> 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';
自然聯結
mysql> select c.*, o.order_num, o.order_date, oi.prod_id, oi.quantity, oi.item_price
from customer 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';
外部聯結
mysql> select customers.cust_id, orders.order_num
from customers left join orders
on customers.cust_id = orders.cust_id;
使用帶聚集函數的聯結
mysql> 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;
組合查詢
使用union
mysql> 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 all命令)
mysql> select vend_id, prod_id, prod_price
from products
where prod_peice <= 5
union all
select vend_id, prod_id, prod_price
from products
where vend_id in (1001,1002);
對組合查詢結果排序
mysql> 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)
order by vend_id, prod_price;
全文搜索
僅在MyISAM數據庫引擎中支持全文搜索,一般在創建表時啟用全文搜索
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;
進行全文本搜索
mysql> select note_text
from productnotes
where match(note_text) against('rabbit');
使用查詢擴展
mysql> select note_text
from productnotes
where match(note_text) against('anvils' with query expansion);
布爾文本搜索
mysql> select note_text
from productnotes
where match(note_text) against('heavy' in boolean mode);
為匹配包含heavy但不包含任意以rope開始的詞的行
mysql> select note_text
from productnotes
where match(note_text) against('heavy -rope*' in boolean mode);
插入數據
插入完整的行
mysql> insert into customers(cust_name,
cust_contact,
cust_email,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
values('Pep E. LaPew',
Null,
Null,
'100 Main Street',
'Los Angeles',
'CA',
'90046',
'USA');
插入多個行
mysql> insert into customers(cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
values(
'Pep E. LaPew',
'100 Main Street',
'Logs Angeles',
'CA',
'90046',
'USA'
),
(
'M. Martian',
'42 Galaxy Way',
'New York',
'NY',
'11213',
'USA'
);
插入檢索出的數據
mysql> 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> update customers
set cust_name = 'The Fudds',
cust_email = 'elmer@fudd.com'
where cust_id = 10005;
刪除數據
mysql> delete from customers
where cust_id = 10006;
創建和操縱表
創建表
mysql> create table customers(
cust_id int NOT NULL AUTO_INCREMENT,
cust_name char(50) NOT NULL,
cust_address char(50) NULL,
cust_city char(50) NULL,
cust_state char(5) NULL,
char_zip char(10) NULL,
char_country char(50) NULL,
char_contact char(50) NULL,
char_email char(255) NULL,
PRIMARY KEY (cust_id)
) ENGINE=InnoDB;
指定默認值
mysql> create table orderitems(
order_num int NOT NULL,
order_item int NOT NULL,
prod_id 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;
引擎類型
InnoDB是一個可靠的事務處理引擎。 MEMORY在功能上等同於MyISAM,但是數據存儲在內存中,速度很快。 MyISAM是性能極高的引擎,支持全文搜索,但不支持事務處理。
更新表
給表添加一列:
mysql> alter table vendors
add vend_phone char(20);
刪除剛剛添加的列:
mysql> alter table vendors
drop column vend_phone;
ALTER TABLE的一種常見用途是定義外鍵:
mysql> alter table orderitems
add constraint fk_orderitems_orders
foreign key (order_num) references orders (order_num);
mysql> alter table orderitems
add constraint fk_orderitems_products
foreign key (prod_id) references products (prod_id);
mysql> alter table orders
add constraint fk_orders_customers
foreign key (cust_id) references customers (cust_id);
mysql> alter table products
add constraint fk_products_vendors
foreign key (vend_id) references vendors (vend_id);
刪除表
mysql> drop table customers2;
重命名表
mysql> rename table customers2 to customers;
對多個表重命名
mysql> rename table backup_customers to customers,
backup_vendors to vendors,
backup_products to products;
使用視圖
利用視圖簡化復雜的聯結
mysql> 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;
用視圖重新格式化檢索出的數據
mysql> create view vendorlocations as
select concat(rtrim(vend_name), ' (', rtrim(vend_country), ')')
as vend_title
from vendors
order by vend_name;
用視圖過濾不想要的數據
mysql> create view customeremaillist as
select cust_id, cust_name, cust_email
from customers
where cust_email is not null;
使用視圖與計算字段
mysql> create view orderitemsexpanded as
select order_num,
prod_id,
quantity,
item_price,
quantity*item_price as expanded_price
from orderitems;
使用存儲過程
執行存儲過程(所有mysql變量都必須以@開始)
mysql> call productpricing(@pricelow,
@pricehigh,
@priceaverage);
創建存儲過程
mysql> create procedure productpricing()
begin
select avg(prod_price) as priceaverage
from products;
end;
刪除存儲過程
mysql> drop procedure productpricing;
使用參數
mysql> 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;
建立智能存儲過程
-- 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;
taxable=0測試結果
call ordertotal(20005, 0, @total); select @total;
taxable=1測試結果
call ordertotal(20005, 1, @total); select @total;
檢查存儲過程
mysql> show create procedure ordertotal;
限制過程狀態結果
mysql> show procedure status like 'ordertotal';
使用游標
創建游標
create procedure processorders()
begin
declare ordernumbers cursor
for
select order_num from orders;
end;
打開和關閉游標
-- 打開游標 open ordernumbers; -- 關閉游標 close ordernumbers;
使用游標
create procedure processorders()
begin
-- declare local variables
declare done boolean default 0;
declare o int;
declare t decimal(8,2);
-- declare the cursor
declare ordernumbers cursor
for
select order_num from orders;
-- declare continue handler
declare continue handler for sqlstate '02000' set done=1;
-- create a table to store the results
create table if not exists ordertotals
(order_num int, total decimal(8,2));
-- open the cursor
open ordernumbers;
-- loop through all rows
repeat
-- get order number
fetch ordernumbers into o;
-- get the total for this order
call ordertotal(o, 1, t);
-- insert order and total into ordertotals
insert into ordertotals(order_num, total)
values(o, t);
-- end of loop
until done end repeat;
-- close the cursor
close ordernumbers;
end;
使用觸發器
創建觸發器
create trigger newproduct after insert on products for each row select 'Product added';
刪除觸發器
drop trigger newproduct;
使用觸發器
-- insert觸發器 create trigger neworder after insert on orders for each row select new.order_num; -- delete觸發器 create tigger deleteorder before delete on orders for each row begin insert into archive_orders(order_num, order_date, cust_id) value(old.order_num, old.order_date, old.cust_id); end; -- update觸發器 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)指事務處理中設置的臨時占位符,你可以對它發布回退。
使用rollback
select * from ordertotals; start transaction; delete from ordertotals; select * from ordertotals; rollback; select * from ordertotals;
使用commit
start transaction; delete from orderitems where order_num = 20010; delete from orders where order_item = 20010; commit;
使用保留點
savepoint delete1; rollback to delete1;
更改默認的提交行為(設置autocommit為0,mysql不自動提交更改,直到autocommit為設置為1為止)
set autocommit=0;
全球化和本地化
字符集為字母和符號的集合;
編碼為某個字符集成員的內部表示;
校對為規定字符如何比較的指令。
查看所支持的字符集完整列表
show character set;
查看所支持校對的完整列表
show collation;
顯示數據庫所用的字符集和校對
show variables like 'character%'; show variables like 'collation%';
給表指定字符集和校對
create table mytable ( column1 int, column2 varchar(10) ) default character set hebrew collate hebrew_general_ci;
對每個列設置字符集和校對
create table mytable ( column1 int, column2 varchar(10), columm3 varchar(10) character set latin1 collate latin1_general_ci ) default character set hebrew collate hebrew_general_ci;
校對順序排序
select * from customers order by lastname, firstname collate latin1_general_cs;
安全管理
不應該在日常的MySQL操作中使用root
獲得所有賬號列表
mysql> use mysql; mysql> select user from user;
創建用戶賬號
mysql> create user ben identified by 'p@$$w0rd';
重命名用戶賬號
mysql> rename user ben to bforta;
刪除用戶賬號
mysql> drop user bforta;
查看用戶賬號權限
mysql> show grants for bforta;
給用戶賬號授予權限
mysql> grant select on crashcourse.* to bforta;
撤銷用戶權限
mysql> revoke select on crashcourse.* from bforta;
更改用戶口令
set password for bforta = password('n3w p@$$w0rd');
設置自己的口令
set password = password('n3w p@$$w0rd');
數據庫維護
備份數據
- 使用命令行實用程序mysqldump轉儲所有數據庫內容到某個外部文件
- 使用命令行實用程序mysqlhotcoy從一個數據庫復制所有數據
- 使用backup table或select into outfile轉儲所有數據到某個外部文件
數據庫維護
- analyze table用來檢查表鍵是否正確
mysql> analyze table orders;
- check table用來針對許多問題對表進行檢查
mysql> check table orders, orderitems;
- 如果從一個表中刪除大量數據,應該使用optimize table來回收所用的空間,從而優化表的性能
查看日志文件
- 錯誤日志。它包含啟動和關閉問題以及任意關鍵錯誤的細節。通常名為hostname.err
- 查詢日志。它記錄所有mysql活動,在診斷問題時非常有用。通常名為hostname.log
- 二進制日志。它記錄更新過數據的所有語句。通常名為hostname.bin
- 緩慢查詢日志。它記錄執行緩慢的任何查詢。通常名為hostname-slow.log
改善性能
查看當前設置
mysql> show variables; mysql> show status;
顯示所有活動進程
mysql> show processlist;
- 如果某個任務執行緩慢,則所有的請求都會執行緩慢,可以用kill命令終結該進程。
- 總是有不止一種方法編寫同一條select語句,應該試驗聯結、並、子查詢等,找出最佳的方法。
- 使用explain語句讓mysql解釋它如何執行一條select語句。
- 一般來說,存儲過程執行比一條條地執行其中的各條mysql語句快。
- 應該總是使用正確的數據類型。
- 決不要檢索比需求還要多的數據。換言之,不要用select *(除非你真的需要每個列)。
- 有的操作(包括insert)支持一個可選的delayed關鍵字,如果使用它,將把控制立即返回給調用程序,並且一旦有可能就實際執行該操作。
- 在導入數據時,應該關閉自動提交。你可能還想刪除索引(包括fulltext索引),然后在導入完成后再重建它們。
- 必須索引數據庫以改善數據檢索的性能。確定索引什么不是一件微不足道的任務,需要分析使用的select語句以找出重復的where和order by子句。如果一個簡單的where子句返回結果所花的時間太長,則可以斷定其中使用的列(或幾個列)就是需要索引的對象。
- 你的select語句中有一系列復雜的or條件嗎?通過使用多條select語句和連接它們的union語句,你能看到極大的性能改進。
- 索引改善數據檢索的性能,但損害數據插入、刪除和更新的性能。如果你有一些表,它們收集數據且不經常被搜索,則在有必要之前不要索引它們。(索引可根據需要添加和刪除。)
- like很慢。一般來說,最好是使用fulltext而不是like。
- 數據庫是不斷變化的實體。一組優化良好的表一會兒后可能就面目全非了。由於表的使用和內容的更改,理想的優化和配置也會改變。
- 最重要的規則就是,每條規則在某些條件下都會被打破。
