教程
官方第三章文档 点我。
由于第3章都是一些操作性的实例,这里就提取一下重点内容。
3.1 从服务器连接和断开
(1)连接: 指定 主机(-h),连接用户(-u),密码(-p)
shell> mysql -h host -u user -p
Enter password: ********
(2)断开:
成功连接后,您可以通过在提示符mysql>
后键入QUIT
(或\q
)来随时断开连接:
mysql> QUIT
Bye
在Unix上,您也可以通过按Control + D
断开连接。
3.2 输入查询
这是一个简单的查询,要求服务器告诉您它的版本号和当前日期。
mysql> SELECT VERSION(), CURRENT_DATE;
+-----------+--------------+
| VERSION() | CURRENT_DATE |
+-----------+--------------+
| 5.8.0-m17 | 2015-12-21 |
+-----------+--------------+
1 row in set (0.02 sec)
mysql>
1.查询语句以分号结尾,有些不用比如QUIT
2.输出结果是表格形式,头行显示列名(你可以使用 as+别名 指定列名或用默认的)
3.输出结果还显示一个粗略的时间,表示查询执行了多久,这个时间是系统时间(wall clock time
)而不是CPU时间
4.关键字不区分大小写,如 sElect
等同于sELECt
mysql> SeLeCt vErSiOn(), current_DATE;
5.select 后面接算数表达式可以做个计算器 select 1+2
;
6.一行可以写多个语句,用分号分隔开就行
mysql> SELECT VERSION(); SELECT NOW();
7.一条语句太长可以多行,用分号分结尾就行
mysql> SELECT
-> USER()
-> ,
-> CURRENT_DATE;
8.临时取消语句:输入\c
9. -> 等你输入 '> "> `> /*> 这4个等你输入相应的闭合字符
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30;
'>
10.字符串可以使用单引号或双引号来包裹
3.3 创建和使用数据库
后面的查询例子都用了一个官方提供的宠物数据库,先下载。
1.显示所有数据库: SHOW DATABASES;
mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql |
| test |
| tmp |
+----------+
2.使用某个数据库 USE dbname
;
mysql> USE test
Database changed
3.管理员用户或root赋予用户('your_mysql_name'@'your_client_host'
)某一数据库(dbname
)的所有权限
GRANT ALL ON dbname.* TO 'your_mysql_name'@'your_client_host';
3.3.1 创建和选择数据库
1.创建数据库,create database dbname
:
linux机器上库名区分大小写,所以建议创建 小写的 库名,表名,列名。
mysql> CREATE DATABASE menagerie;
2.连接数据库提供密码的两种方式
a. 使用-p
, p后留空白,代表在下一行输入密码。
shell> mysql -h host -p -u user
Enter password: ********
b. 使用-ppassword
,p后直接跟密码。
shell> mysql -h host -u user -ppassword
3.3.2 创建表
1.显示当前数据库内的表 show tables;
2.建立一个宠物pet表和event表
CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
CREATE TABLE event (name VARCHAR(20), date DATE,type VARCHAR(15), remark VARCHAR(255));
3.VARCHAR
类型可以指定列的长度,可选1~65535
4.检查创建pet表的语法 describe pet;
或者desc pet;
mysql> DESCRIBE pet;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| owner | varchar(20) | YES | | NULL | |
| species | varchar(20) | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
| birth | date | YES | | NULL | |
| death | date | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
3.3.3 将数据加载到表中
1.可以使用LOAD DATA
或Insert into
两种方法加载数据
2.如果你的数据在txt中,可以用tab来区分每一个列,使用\N
表示当前数据为空,使用'YYYY-MM-DD'
表示一个日期。
下面是pet.txt
中的数据:
3.1 使用LOAD DATA
导入数据
LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;
windows提供文件路径使用双反斜线C:\\windows\\pet.txt
注意:如果出现错误The used command is not allowed with this MySQL version
,那是因为系统变量local_infile
没有打开。
解决方案:
(1)停止mysql服务,修改配置文件,在[mysqld]
部分增加
[mysqld]
local_infile = ON
(2)开启mysql服务,使用mysql客户端连接的时候提供参数--local-infile=1
。
shell> mysql -uxxx -P 34567 -p menagerie --local-infile=1
(3)执行LOAD DATA
,插入成功。
(4)如果你的导入还有问题,请参阅 Section 6.1.6, “Security Issues with LOAD DATA LOCAL“
3.2 使用INSERT INTO
一次插入一条
INSERT INTO pet VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
3.3.4 从表中检索信息
0.检索pet表数据
select * from pet;
SELECT * FROM pet WHERE birth >= '1998-1-1';
1.修改某条数据
UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';
字符串比较时通常对大小些不敏感,例如 BOWser
2.AND
和OR
可以混用,但AND比OR具有更高的优先级.如果你使用两个操作符,使用圆括号指明如何对条件进行分组
SELECT * FROM pet WHERE (species = 'cat' AND sex = 'm') OR (species = 'dog' AND sex = 'f');
3.对选择的列去重
SELECT DISTINCT owner FROM pet;
增加关键字DISTINCT检索出每个唯一的输出记录,DISTINCT后面可以接多列进行最少输出
4.对结果进行排序
SELECT name,birth FROM pet order by [binary] birth [ASC|DESC];
默认排序是升序(ASC) ,且大小写不敏感,如果想敏感可以在列名前增加binary
,如果降序可以用DESC;可以对每个列都进行排序 (有种先分组再在组内排序的意思)
mysql> SELECT name, species, birth FROM pet
-> ORDER BY species, birth DESC;
+----------+---------+------------+
| name | species | birth |
+----------+---------+------------+
| Chirpy | bird | 1998-09-11 |
| Whistler | bird | 1997-12-09 |
| Claws | cat | 1994-03-17 |
| Fluffy | cat | 1993-02-04 |
| Fang | dog | 1990-08-27 |
| Bowser | dog | 1989-08-31 |
| Buffy | dog | 1989-05-13 |
| Puffball | hamster | 1999-03-30 |
| Slim | snake | 1996-04-29 |
+----------+---------+------------+
5.日期计算
(1)年龄的两种计算方式
- 使用内置的
TIMESTAMPDIFF
方法(简单)
SELECT name, birth, CURDATE(),TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age FROM pet;
- 先算年,然后日期比较看是否要-1
SELECT name,birth,(YEAR(CURDATE())-YEAR(birth))- (RIGHT(CURDATE(),5)<RIGHT(birth,5)) AS age FROM pet;
(2)下个月过生日计算的两种方法:
- 使用内置
DATE_ADD
函数
SELECT name, birth FROM pet WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
- 使用内置
MOD
函数
SELECT name, birth FROM pet WHERE MONTH(birth) = MOD(MONTH(CURDATE()),12)+1
6.空值NULL
使用colnum IS NOT NULL
而非colnum != NULL来进行比较,因为NULL是特殊的值,不能使用普通比较符来比较;
mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
-> 0,1
NULL的算数比较结果都是NULL ,
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
In MySQL,0 or NULL means false and anything else means true
在GROUP BY
中,两个NULL值视为相同
使用ORDER BY排序时,如果有NULL值,则它出现在最前面;DESC的时候,出现在最后面。
mysql> select sex from pet order by sex asc;
7.模式匹配
模式匹配允许你使用 _
匹配任何单个字符(包含0个字符)
而%
匹配任意数目字符(包括0个字符)
模式匹配默认是忽略大小写的(BINARY 来强制敏感)
使用LIKE
或 NOT LIKE
(或者使用 REGEXP
和NOT REGEXP
)
mysql> SELECT * FROM pet WHERE name LIKE '%w%';
mysql> SELECT * FROM pet WHERE REGEXP_LIKE(name, '^b');
更多请见 Section 12.5.2, “Regular Expressions”.
8.计数
(1)了解每位业主拥有多少宠物
SELECT owner, COUNT(*) FROM pet GROUP BY owner;
(2)group by 用在 where 之后
(3)用在groupb by 语句中,如果你使用了某一列(name),和一个聚合函数列,你需要指定group by name
,否则在ONLY_FULL_GROUP_BY
这种sql模式下会报错,例如:
mysql> SET sql_mode = 'ONLY_FULL_GROUP_BY';
mysql> SELECT owner, COUNT(*) FROM pet;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression
#1 of SELECT list contains nonaggregated column 'menager
修改为下面的语句,才会正常:
SELECT owner, COUNT(*) FROM pet group by owner;
9.连接多表
- Inner join 连接两张表 (比如,查询宠物生宝宝时候的年龄和具体细节
)
SELECT pet.name, TIMESTAMPDIFF(YEAR,birth,date) AS age,remark
FROM pet INNER JOIN event ON pet.name = event.name
WHERE event.type = 'litter';
- 连接自身
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species FROM pet AS p1, pet AS p2
WHERE p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm';
+--------+------+--------+------+---------+
| name | sex | name | sex | species |
+--------+------+--------+------+---------+
| Fluffy | f | Claws | m | cat |
| Buffy | f | Fang | m | dog |
| Buffy | f | Bowser | m | dog |
+--------+------+--------+------+---------+
10.如果表有索引,SHOW INDEX FROM tbl_name
生成有关索引的信息。
3.5 在批处理模式下使用mysql
(1)windows下:
mysql -e "source C:\\Users\\eve\\Desktop\\batch.txt" [>file| more] [-t -vvv]
(2)linux 下:
msyql < batch.txt
cron模式下不许使用交互,最好使用批处理文件
3.6. 常用查询的例子
1.实例表:
CREATE TABLE shop (article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,dealer CHAR(20) DEFAULT '' NOT NULL,price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3,'C',1.69),(3,'D',1.25),(4,'D',19.95);
(1)求某列中的最大值
SELECT MAX(article) AS article FROM shop;
(2)求拥有某列最大值的行
例如:找出最贵物品(article)的价格(price),经销商(dealer),有三种解决方案
- a 子查询
SELECT article, dealer, price
FROM shop
WHERE price=(SELECT MAX(price) FROM shop);
- b 左连接 或右连接
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
RIGHTJOIN shop s2 ON s1.price > s2.price
WHERE s1.article IS NULL;
- c
order by
+limit
SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1;
如果有几个最昂贵的文章,每个价格为19.95,LIMIT解决方案只显示其中一个。
(3)求每组拥有的最大列值
例如:找到每种物品的最高价格
select article,max(price) from shop group by article;
(4)求每组内拥有某列最大值的行
例如:对每项物品,找出最贵价格的物品的经销商。
- 通过子查询(这是一个相关子查询,效率可能低下)
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article)
ORDER BY article;
- 在FROM内使用非相关子查询
SELECT s1.article, dealer, s1.price
FROM shop s1
JOIN (
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article) AS s2
ON s1.article = s2.article AND s1.price = s2.price
ORDER BY article;
- 左外连接
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.price
WHERE s2.article IS NULL
ORDER BY s1.article;
更多关于连接的使用,请参考 第13.2.10.2节“JOIN语法”
- 带窗口函数的公用表表达式
WITH s1 AS (
SELECT article, dealer, price,
RANK() OVER (PARTITION BY article
ORDER BY price DESC
) AS `Rank`
FROM shop
)
SELECT article, dealer, price
FROM s1
WHERE `Rank` = 1
ORDER BY article;
2.使用用户变量
SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
3.确定每个月的访问天数
3.1 实例表
CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL,
day INT(2) UNSIGNED ZEROFILL);
INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),
(2000,2,23),(2000,2,23);
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 GROUP BY year,month
4.对于MyISAM表,在一张表的第二列定义列含有 AUTO_INCREMENT属性,并将一二列做成多列索引,可以达成一种数据分组的情况,例如:
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
完