MySQL总结
前言
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。
MySQL是一种关系数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库。
由于其社区版的性能卓越,搭配 PHP 和 Apache 可组成良好的开发环境。
一、检索数据
1. 检索所有列
select * from products;
2. 检索单个列
select prod_id from products;
3. 检索多个列
select prod_id, prod_name from products;
4. 检索不同行
select vend_id from products;
5. 限制结果
Eg:检索的结果不超过5行。
select prod_name from products limit 5;
Eg:从第6行开始检索prod_name,检索5行,也就是检索6~11行的数据。(注意:limit 0是第一行)
select prod_name from products limit 5,5;
6. 使用完全限定的表名
select products.prod_name from crashcourse.products;
等同于:
select prod_name from products;
二、排序检索数据
排序数据
select prod_name from products;
上面这条mysql语句是没有特定的顺序排列的。
Eg:使用order by(默认从小到大)按照prod_name顺序排列。
select prod_name from products order by prod_name;
按多个列排序
Eg:使用oder by按照prod_price, prod_name多个列排序。
select prod_id, prod_price, prod_name from products order by prod_price, prod_name;
按指定排序方向
Eg:使用oder by按照prod_price, prod_name多个列降序排序。
select prod_id, prod_price, prod_name from products order by prod_price desc, prod_name desc;
三、过滤数据
使用where子句
Eg:查找prod_price = 2.50的匹配结果。
select prod_name, prod_price from products where prod_price = 2.50;
where子句操作符
运算符 | 描述 |
---|---|
= | 等于 |
<> | 不等于。注释:在 SQL 的一些版本中,该操作符可被写成 != |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
BETWEEN | 在某个范围内 |
LIKE | 搜索某种模式 |
IN | 指定针对某个列的多个可能值 |
1.检查单个值
select prod_name, prod_price from products where prod_name = 'fuses';
select prod_name, prod_price from products where prod_price > 5;
select prod_name, prod_price from products where prod_price >= 5;
2. 不匹配检查
Eg:查找不是由供应商1003制造的所有产品。
法一(<>):
select vend_id, vend_name from products where vend_id <> 1003;
法二(!=):
select vend_id, vend_name from products where vend_id != 1003;
3. 范围值检查
Eg:检索价格在5~10之间的所有产品。
select prod_name, prod_price from products where prod_price between 5 and 10;
4. 空值检查
Eg:检索顾客的邮件(cust_email)为空的匹配项。
select cust_id from customers where cust_email is null;
三、数据过滤
组合where子句
1. and操作符
Eg:找出vend_id=1003 and prod_price <= 10所有产品的prod_id,prod_price,prod_name。
select prod_id, prod_price, prod_name from products where vend_id = 1003 and prod_price <= 10;
2. or操作符
Eg:找出vend_id=1002 or vend_id=1003所有产品的prod_name,prod_price。
select prod_name, prod_price from products where vend_id = 1002 or vend_id = 1003;
3. 计算次序
or和and一起的时候,优先处理and操作符
select prod_name, prod_price from products where vend_id = 1002 or vend = 1003 and prod_price >= 10;
上面这条mysql语句,优先执行and操作符。
正确的做法(mysql语句):
select prod_id,prod_price from products where (vend_id = 1002 or vend_id = 1003) and prod_price >= 10;
in操作符
Eg:找出vend_id在1001~1003范围内的所有prod_name,prod_price匹配的结果。
select prod_name, prod_price from products where vend_id in (1001,1003) order by prod_name;
not操作符
Eg:找出vend_id不在1001~1003范围内的所有prod_name,prod_price匹配的结果。
select prod_name, prod_price from products where vend_id not in (1001,1003) order by prod_name;
四、用通配符进行数据过滤
like操作符
1. 百分号(%)通配符
Eg:找出所有jet开头的产品。
select prod_id, prod _name from products where prod_name like 'jet%';
Eg:找出包含jet的产品。
select prod_id, prod _name from products where prod_name like '%jet%';
2. 下划线(_)通配符
Eg:找出后面跟有两个通配符ton anvil。
select prod_id, prod_name from products where prod_name like '_ton anvil';
结果:
prod_id prod_name
ANV02 1 ton anvil
ANV03 2 ton anvil
对比,来看看使用%ton anvil匹配的结果:
select prod_id, prod_name from products where prod_name like '%ton_anvil';
结果:
prod_id prod_name
ANV01 .5 ton anvil
ANV02 1 ton anvil
ANV03 2 ton anvil
思考
为什么使用_ton anvil和%ton_anvil返回的结果不一样?少了ANV01的结果?
解答:因为下划线(_)只可以匹配一个字符,不能多,也不能少!而百分号(%)就不一样了,它没有限制!
五、使用MySQL正则表达式
正则表达式查询REGEXP
选项 | 说明 | 例子 | 示例 |
---|---|---|---|
^ | 匹配文本的开始字符 | ‘^b’匹配以字母b开头的字符串 | book,big,banana,bike |
$ | 匹配文本的结束字符 | ‘st$’匹配以st结尾的字符串 | test, resist,persist |
. | 匹配任意单个字符 | b.t匹配任何b和t之间有一个字符 | bit,bat,but,bite |
* | 匹配零个或多个在它前面的字符 | f*n匹配字符n前面有任意个字符f | fn,fan,faan,abcn |
+ | 匹配前面的字符1次或多次 | ‘ba+’匹配b后面至少有一个a | ba, bay, bare, battle |
<字符串> | 匹配包含指定的字符串的文本 | ‘fa’ | fan, afa, faad |
[字符集合] | 匹配字符集合中的任何一个字符 | [xz]匹配x或者z | dizzy,zebra,x-ray,extra |
[^] | 匹配不在括号中的任何字符 | [^abc]匹配任凭不包含a,b或c的字符串 | desk, fox, f8ke |
字符串{n,} | 匹配前面的字符串至少n次 | b{2}匹配2个或者更多的b | bbb,bbbb,bbbbb |
字符串{n, m} | 匹配前面的字符串至少n次,至多m次 | b{2, 4}匹配最少2个,最多4个b | bb,bbb,bbbb |
1. 基本字符匹配
Eg:检索匹配.000的字符。
select prod_name from products where prod_name regexp '.000' order by prod_name;
结果:
prod_name
JetPack 1000
JetPack 2000
2. 进行or匹配
Eg:检索prod_name为1000或2000的匹配结果,并按prod_name默认升序。
select prod_name from products regexp '1000|2000' order by prod_name;
结果:
prod_name
JetPack 1000
JetPack 2000
3. 匹配几个字符之一
Eg:检索prod_name的匹配字符为1、2的符合结果。
select prod_name from products where prod_name regexp '[12] Ton' order by prod_name;
结果:
prod_name
1 ton anvil
2 ton anvil
4. 匹配范围
Eg:检索prod_name的匹配字符为1-5的结果。
select prod_name from products where regexp '[1-5] Ton' order by prod_name;
结果:
prod_name
.5 ton anvil
1 ton anvil
2 ton anvil
注意:因为.5也是符合1-5的,所以会被检索。
5. 匹配特殊字符
Eg:返回vend_name含有.的匹配结果。
select vend_name from vendors where vend_name regexp '\\.' order by vend_name;
结果:
vend_name
Furball Inc
6. 匹配字符类
7. 匹配多个实例
Eg1:
\\([0-9]匹配prod_name的0-9的任意数字;
sticks?\\使s可选,没有?,匹配stick和sticks非常困难。
mysql语句:
select prod_name from products where prod_name regexp '\\([0-9] sticks?\\)' order by prod_name;
结果:
prod_name
TNT (1 stick)
TNT (5 stick)
Eg2:匹配林仔一起的四位数字。
select prod_name from products where prod_name regexp '[[:digit:]]{4}' order by prod_name;
结果:
prod_name
JetPack 1000
JetPack 2000
说明:
[:digit:]匹配任意数字,因而它为数字的一个集合。
{4}确切地要求它前面的字符(任意数字)出现四次。
所以,[[:digit:]]{4}匹配连在一起的任意四位数字。
Eg2的等同写法:
select prod_name from products where prod_name regexp '[0-9][0-9][0-9][0-9]' order by prod_name;
8. 定位符
定位元字符
Eg:找出以一个数(包括小数点开始的数)开始的所有产品。
select prod_name from products where prod_name regexp '^[0-9\\.]' order by prod_name;
结果:
prod_name
.5 ton anvil
1 ton anvil
2 ton anvil
六、创建计算字段
拼接字段
普通拼接
Eg1:
select concat(vend_name, '(', vend_country, ')') from vendors order by vend_name;
结果:
concat(vend_name, '(', vend_country, ')')
ACME (USA)
Anvils R Us (USA)
Furball Inc. (USA)
Jet Set (England)
Jouets Et Ours (France)
LT Supplies (USA)
rtrim()函数
Eg2:rtrim()函数去掉右边的所有空格。
select concat(rtrim(vend_name, '(', vend_country, ')') from vendors order by vend_name;
使用别名
别名(alias),使用as关键字赋予。
Eg3:
select concat(rtrim(vend_name), '(', rtrim(vend_country), ')') as vend_title from vendors order by vend_name;
结果:
vend_title
ACME (USA)
Anvils R Us (USA)
Furball Inc. (USA)
Jet Set (England)
Jouets Et Ours (France)
LT Supplies (USA)
执行算术计算
select prod_id, quantity, item_price from orderitems where order_num = 2005;
结果:
prod_id quantity item_price
ANV01 10 5.99
ANV02 3 9.99
TNT2 10 10.00
FB 1 10.00
Eg:汇总物品价格(单价乘以订购数量)。
select prod_id,
quantity,
item_price,
quantity*item_price as expanded_price
from orderitems
where order_num = 2005;
结果:
prod_id quantity item_price extended_price
ANV01 10 5.99 59.90
ANV02 3 9.99 29.97
TNT2 10 10.00 50.00
FB 1 10.00 10.00
七、使用数据处理函数
1. 文本处理函数
名称 | 调用示例 | 示例结果 | 描述 |
---|---|---|---|
LEFT | LEFT('abc123', 3) | abc | 返回从左边取指定长度的子串 |
RIGHT | RIGHT('abc123', 3) | 123 | 返回从右边取指定长度的子串 |
LENGTH | LENGTH('abc') | 3 | 返回字符串的长度 |
LOWER | LOWER('ABC') | abc | 返回小写格式字符串 |
UPPER | UPPER('abc') | ABC | 返回大写格式字符串 |
LTRIM | LTRIM(' abc') | abc | 将字符串左边空格去除后返回 |
RTRIM | RTRIM('abc ') | abc | 将字符串右边空格去除后返回 |
SUBSTRING | SUBSTRING('abc123', 2, 3) | bc1 | 从字符串第2位开始截取3位字符 |
CONCAT | CONCAT('abc', '123', 'xyz') | abc123xyz | 将各个字符串参数拼接成一个新的字符串 |
Eg:
select vend_name, upper(vend_name) as vend_upcase from vendors order by vend_name;
结果:
vend_name vend_name_upcase
ACME ACME
Anvils R Us ANVILS R US
Furball Inc. FURBALL INC
Jet Set JET SET
Jouets Et Ours JOUETS ET OURS
LT Supplies LT SUPPLIES
2. 日期和时间处理函数
Eg:
select cust_id, order_num from orders where order_date = '2005-09-01';
结果:
cust_id order_num
1001 2005
3. 数值处理函数
八、创建和操纵表
创建表
Eg:
create table customers
(
cust_id int not null auto_increment
cust_name char(50) not null ,
cust_city char(50) null ,
cust_state char(5) null ,
cust_zip char(10) null ,
cust_country char(50) null ,
cust_contact char(50) null ,
cust_email char(255) null ,
primary key (cust_id)
)ENGINE=InnoDB;
- ENGINE=InnoDB:表的引擎。
- auto_increment:自动增长。
更新表
给表增加一列:
alter table vendors add vend_phone char(20);
删除表
drop table customers;
重命名表
重命名单个表:
rename table customers to cust;
重命名多个表:
rename table backup_customers to cust, backup_vendors to vendors, backup_products to products;
九、插入数据
1. 插入完整的行
Eg:直观的插入数据。
insert into customers
(
cust_name,
cust_city,
cust_zip,
cust_country,
cust_contact,
cust_email
)values(
'Pep E. LaPew',
'100 Main Street',
'Los Angeles',
'CA',
'90046',
'USA'
null,
null;
);
2. 插入多个行
Eg:
insert into customers
(
cust_name,
cust_city,
cust_zip,
cust_country,
cust_contact,
cust_email
)values(
'Pep E. LaPew',
'100 Main Street',
'Los Angeles',
'CA',
'90046',
'USA'
),
(
'M. Martian',
'42 Galaxy Way',
'New York',
'NY',
'11213',
'USA'
);
十、汇总数据
聚集函数
1. avg()函数:
Eg:使用avg()函数返回products表中所有产品的平均值。
select avg(prod_price) as avg_price from products;
结果:
avg_price
16.133571
2. count()函数:
Eg1:返回customers表中客户的总数。
select count(*) as num_cust from customers;
结果:
num_cust
5
Eg2:返回具有电子邮件的客户计数。
select coun(cust_email) as num_cust from customers;
结果:
num_cust
3
Eg3:
select cust_id, count(*) as orders from orders group by cust_id having count(*) >= 2;
结果:
cust_id orders
1000 2
3. max()函数:
Eg:
select max(prod_price) as max_price from products;
结果:
max_price
55.00
4. min()函数:
g:
select min(prod_price) as min_price from products;
结果:
min_price
2.50
5. sum()函数:
Eg:计算总的订单金额。
select sum(item_price*quantity) as total_price from orderitems where order_num = 2005;
结果:
total_price
149.87
十一、分组数据
1. 创建分组
Eg:使用group by来进行分组。
select vend_id, count(*) as num_prods from products group by vend_id;
结果:
vend_id num_prod
1001 3
1002 2
1003 7
1005 2
2. 过滤分组
使用having来过滤分组,实际上,可以用having来替代where。
唯一的区别就是,where过滤行,having过滤分组。
Eg:
select cust_id, count(*) as orders from orders group by cust_id having count(*) >= 2;
结果:
cust_id orders
1000 2
3. 分组和排序
Eg1:检索订单价格大于等于50的订单和总计订单价格。
select order_num, sum(quantity*item_price) as ordertotal from orderitems group by order_num having sum(quantity*item_price) >= 50;
结果:
order_num ordertotal
2005 149.87
2006 55.00
2007 1000.00
2008 125.00
Eg2:
select order_num, sum(quantity*item_price) as ordertotal from orderitems group by order_num having sum(quantity*item_price) >= 50 order by ordertotal;
结果:
order_num ordertotal
2006 55.00
2008 125.00
2005 149.87
2007 1000.00
十二、使用子查询
1. 使用子查询进行过滤
select order_num from orderitems where prod_id = 'TNT2';
结果:
order_num
2005
2007
select cust_id from orders where order_num in (2005,2007)
结果:
cust_id
1001
1004
使用子查询:
Eg:
select cust_id from orders where order_num in (select order_num from orderitems where prod_id = 'TNT2');
结果:
cust_id
1001
1004
2. 作为计算字段使用子查询
Eg:
select cust_name,
cust_state,
(select count(*)
from orders
where orders.cust_id = customers.cust_id) as orders from customers order by cust_name;
结果:
cust_name cust_state orders
Coyote Inc MI 2
E Fudd IL 1
Mouse House OH 0
Wascals IN 1
Yosemite Place AZ 1
十三、联结表
如果数据储存在多个表中,如何用单个select检索出来?
创建联结
Eg:
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;
联结多个表
Eg:
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 = 2005;
结果:
prod_name vend_name prod_price quantity
.5 ton anvil Anvils R Us 5.99 10
1 ton anvil Anvils R Us 9.99 3
TNT (5 staicks) ACME 10.00 5 Bird seed ACME 10.00 1
十四、创建高级联结
十五、组合查询
1. 使用union
单个查询:
select vend_id, prod_id, prod_price from products where prod_price <= 5;
vend_id prod_id prod_price
1003 FC 2.50
1002 FU1 3.42
1003 SLING 4.49
1003 TNT1 2.50
select vend_id, prod_id, prod_price from products where vend_id in (1001,1002);
vend_id prod_id prod_price
1001 ANV01 5.99
1001 ANV02 9.99
1001 ANV03 14.99
1002 FU1 3.42
1002 OL1 8.99
思考:我是否可以使用一条mysql语句来组合她们?
Eg:
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);
结果:
vend_id prod_id prod_price
1003 FC 2.50
1002 FU1 3.42
1003 SLING 4.49
1003 TNT1 2.50
1001 ANV01 5.99
1001 ANV02 9.99
1001 ANV03 14.99
1002 OL1 8.99
2. 包含或取消重复的行
Eg:
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);
结果:
vend_id prod_id prod_price
1003 FC 2.50
1002 FU1 3.42
1003 SLING 4.49
1003 TNT1 2.50
1001 ANV01 5.99
1001 ANV02 9.99
1001 ANV03 14.99
1002 FU1 3.42
1002 OL1 8.99
这里注意看下面这行↓
1002 FU1 3.42
是不是多了一行,这就是union all
3. 对组合查询结果排序
Eg:
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;
结果:
vend_id prod_id prod_price
1001 ANV01 5.99
1001 ANV02 9.99
1001 ANV03 14.99
1002 FU1 3.42
1002 OL1 8.99
1003 FC 2.50
1003 TNT1 2.50
1003 SLING 4.49
十六、全文本搜索
注意:
MyISAM引擎支持全文本搜索;
InnoDB引擎不支持全文本搜索。
1. 启用全文本搜索
Eg:首先要创建一个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),
fulltest(note_text)
)engine=MyISAM;
MySQL根据子句fulltest(note_text)的指示对它进行全文索引。
注意:这里的fulltext索引单个列!
2. 使用全文本搜索
Eg:
select note_text
from productnotes
where math(note_text) against('rabbit');
返回的结果只是包含rabbit的这一行。
注意:这里的math()里面的值必须与fulltext()里面的值相同;搜索不区分大小写。
使用like语句也是可以达到相同的效果的
select note_text
from productnotes
where math(note_text) like '%rabbit%';
2. 使用查询扩展
Eg:
select note_text from productnotes where math(note_text) against('anvils' with query expansion);
返回的结果是很多行,还包含了rabbit。
3. 布尔文本搜索
Eg:
select note_text from productnotes where math(note_text) against('heavy' in boolean mode);
十七、安全管理
管理用户
mysql>use mysql;
mysql>select user from user;
结果:
user
root
1. 创建用户账号
create user ben identified 'password';
2. 重命名用户账号
rename user ben to bforta;
3. 删除用户账号
drop user bforta;
4. 设置访问权限
权限 | 权限级别 | 权限说明 |
---|---|---|
CREATE | 数据库、表或索引 | 创建数据库、表或索引权限 |
DROP | 数据库或表 | 删除数据库或表权限 |
GRANT OPTION | 数据库、表或保存的程序 | 赋予权限选项 |
REFERENCES | 数据库或表 | |
ALTER | 表 | 更改表,比如添加字段、索引等 |
DELETE | 表 | 删除数据权限 |
INDEX | 表 | 索引权限 |
INSERT | 表 | 插入权限 |
SELECT | 表 | 查询权限 |
UPDATE | 表 | 更新权限 |
CREATE VIEW | 视图 | 创建视图权限 |
SHOW VIEW | 视图 | 查看视图权限 |
ALTER ROUTINE | 存储过程 | 更改存储过程权限 |
CREATE ROUTINE | 存储过程 | 创建存储过程权限 |
EXECUTE | 存储过程 | 执行存储过程权限 |
FILE | 服务器主机上的文件访问 | 文件访问权限 |
CREATE TEMPORARY TABLES | 服务器管理 | 创建临时表权限 |
LOCK TABLES | 服务器管理 | 锁表权限 |
CREATE USER | 服务器管理 | 创建用户权限 |
PROCESS | 服务器管理 | 查看进程权限 |
RELOAD | 服务器管理 | 执行flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables, flush-threads, refresh, reload等命令的权限 |
REPLICATION CLIENT | 服务器管理 | 复制权限 |
REPLICATION SLAVE | 服务器管理 | 复制权限 |
SHOW DATABASES | 服务器管理 | 查看数据库权限 |
SHUTDOWN | 服务器管理 | 关闭数据库权限 |
SUPER | 服务器管理 | 执行kill线程权限 |
查看赋予用户账号的权限
show grants for;
Eg:允许用户在crashcourse这个数据库中的所有表中使用select。
grant select on crashcourse.* to bforta;
- 整个服务器:grant all、revoke all
- 整个数据库,on database.*
- 特定的表,on database.table
- 特定的列
- 特定的储存过程
十八、数据库维护
1. 备份数据库
2. 进行数据库维护
Eg1:检查表键是否正确。
analyze table orders;
Eg2: 针对性地检查表。
check table orders, ordertems;
3. 诊断启动问题
mysql
--help
--safe-mode //装载减去某些最佳配置的服务器
--verbose //显示全文本消息
--version
4. 查看日志文件
- 错误日志:data目录→hostname.err
- 查询日志:data目录→hostname.log
- 二进制文件:data目录→hostname-bin
- 缓慢查询日志:data目录→hostname-slow.log
十九、改善性能
- 建议将MySQL运行在自己专用服务器上。
- MySQL的预设值可以调整: 比如内存分配, 缓冲区大小。
- MySQL是一个多线程的DBMS, 经常同时执行多个任务, 可能会被其中一个执行缓慢的任务影响, 使用 SHOW PROCESSLIST 显示活动进程来分析, 使用KILL杀死进程。
- SELECT语句的多种尝试: 联结, 并, 子查询等, 找出最佳方法。
- 使用EXPLAIN让MySQL解释如何执行一个查询。
- 存储过程执行比一条一条的执行个SQL语句快。
- 应该总是使用正确的数据类型。
- 少用SELECT * : 也就是不要检索超出需求的数据。
- 必须索引数据库表以改善数据检索的性能。
- 使用多条SELECT 和连接他们的UNION语句代替OR条件。
- 索引改善检索数据的性能, 但是影响增删改, 如果一个表不经常被检索, 则不要索引他们。
- Like很慢, 最好使用FULLTEXT。
- 数据库是不断变化的, 一组优化良好的表可能一会就面目全非了, 所以理想优化也会改变。
- 本文标签: MySQL
- 本文链接: http://www.lzhpo.com/article/47
- 版权声明: 本文由lzhpo原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权