MySQL基础复习

这段时间发现自己把MySQL忘记得差不多了,也刚好没有什么事情,就希望能复习一下,就找了《MySQL必知必会》稍微看了一下。

首先从http://www.forta.com/books/0672327120/下载创建数据库和导入数据的sql文件。

首先在命令行登录我的mysql,创建新的数据库:

1
2
create database mysql_learning;
use mysql_learning;

然后导入表格和数据:

1
2
source /path_to_data/create.sql
source /path_to_data/populate.sql

这样就完成了数据的导入。

查询表的结构

例如我要查询custom的结构,用如下命令:

1
show columns from customers;

输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> show columns from customers;
+--------------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(50) | NO | | NULL | |
| cust_address | char(50) | YES | | NULL | |
| cust_city | char(50) | YES | | NULL | |
| cust_state | char(5) | YES | | NULL | |
| cust_zip | char(10) | YES | | NULL | |
| cust_country | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
| cust_email | char(255) | YES | | NULL | |
+--------------+-----------+------+-----+---------+----------------+

检索数据

use mysql_learning;后,就可以开始执行查询操作了。

单列检索

1
select cust_name from customers;

输出如下:

1
2
3
4
5
6
7
8
9
10
11
mysql> select cust_name from customers;
+----------------+
| cust_name |
+----------------+
| Coyote Inc. |
| Mouse House |
| Wascals |
| Yosemite Place |
| E Fudd |
+----------------+
5 rows in set (0.00 sec)

多列检索

1
select cust_name, cust_city from customers;

输出如下:

1
2
3
4
5
6
7
8
9
10
11
mysql> select cust_name, cust_city from customers;
+----------------+-----------+
| cust_name | cust_city |
+----------------+-----------+
| Coyote Inc. | Detroit |
| Mouse House | Columbus |
| Wascals | Muncie |
| Yosemite Place | Phoenix |
| E Fudd | Chicago |
+----------------+-----------+
5 rows in set (0.00 sec)

所有列检索

1
select * from cust_name;

会输出整个表格。

distinct关键字

在这里面可能会遇到这样的情况,输出可能会有重复。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> select vend_id from products;
+---------+
| vend_id |
+---------+
| 1001 |
| 1001 |
| 1001 |
| 1002 |
| 1002 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1003 |
| 1005 |
| 1005 |
+---------+
14 rows in set (0.00 sec)

加上distinct关键字:

1
2
3
4
5
6
7
8
9
10
mysql> select distinct vend_id from products;
+---------+
| vend_id |
+---------+
| 1001 |
| 1002 |
| 1003 |
| 1005 |
+---------+
4 rows in set (0.00 sec)

可以看出去重了。

limit限制输出行数

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select cust_name from customers;
+----------------+
| cust_name |
+----------------+
| Coyote Inc. |
| Mouse House |
| Wascals |
| Yosemite Place |
| E Fudd |
+----------------+
5 rows in set (0.00 sec)

可以用limit限定输出前几行:

1
2
3
4
5
6
7
8
9
mysql> select cust_name from customers limit 3;
+-------------+
| cust_name |
+-------------+
| Coyote Inc. |
| Mouse House |
| Wascals |
+-------------+
3 rows in set (0.00 sec)

还可以再加上offset限制从第几行开始取:

1
2
3
4
5
6
7
mysql> select cust_name from customers limit 1 offset 2;
+-----------+
| cust_name |
+-----------+
| Wascals |
+-----------+
1 row in set (0.00 sec)

以上例子值得是从第二行开始取一行。

排序检索

可以用order by关键字来做排序:

1
select prod_id from products order by prod_id;

输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> select prod_id from products order by prod_id;
+---------+
| prod_id |
+---------+
| ANV01 |
| ANV02 |
| ANV03 |
| DTNTR |
| FB |
| FC |
| FU1 |
| JP1000 |
| JP2000 |
| OL1 |
| SAFE |
| SLING |
| TNT1 |
| TNT2 |
+---------+
14 rows in set (0.00 sec)

而order by可以有多个参数,可以按多个优先级排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> select prod_id, prod_price, prod_name from products order by prod_price, prod_name;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| FC | 2.50 | Carrots |
| TNT1 | 2.50 | TNT (1 stick) |
| FU1 | 3.42 | Fuses |
| SLING | 4.49 | Sling |
| ANV01 | 5.99 | .5 ton anvil |
| OL1 | 8.99 | Oil can |
| ANV02 | 9.99 | 1 ton anvil |
| FB | 10.00 | Bird seed |
| TNT2 | 10.00 | TNT (5 sticks) |
| DTNTR | 13.00 | Detonator |
| ANV03 | 14.99 | 2 ton anvil |
| JP1000 | 35.00 | JetPack 1000 |
| SAFE | 50.00 | Safe |
| JP2000 | 55.00 | JetPack 2000 |
+---------+------------+----------------+
14 rows in set (0.01 sec)

还可以用desc反向排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> select prod_id, prod_price, prod_name from products order by prod_price desc, prod_name;
+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| JP2000 | 55.00 | JetPack 2000 |
| SAFE | 50.00 | Safe |
| JP1000 | 35.00 | JetPack 1000 |
| ANV03 | 14.99 | 2 ton anvil |
| DTNTR | 13.00 | Detonator |
| FB | 10.00 | Bird seed |
| TNT2 | 10.00 | TNT (5 sticks) |
| ANV02 | 9.99 | 1 ton anvil |
| OL1 | 8.99 | Oil can |
| ANV01 | 5.99 | .5 ton anvil |
| SLING | 4.49 | Sling |
| FU1 | 3.42 | Fuses |
| FC | 2.50 | Carrots |
| TNT1 | 2.50 | TNT (1 stick) |
+---------+------------+----------------+
14 rows in set (0.00 sec)

在目标列后加入desc即可。

过滤数据

用where语句可以筛选数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select prod_id from products where prod_price < 10;
+---------+
| prod_id |
+---------+
| ANV01 |
| ANV02 |
| FC |
| FU1 |
| OL1 |
| SLING |
| TNT1 |
+---------+
7 rows in set (0.00 sec)

操作符包括 =, <, >, <> (不等于) , !=, <= , >= , between。

空值检查

IS NULL可以用来判定限定空值:

1
2
3
4
5
6
7
8
mysql> select cust_name, cust_email from customers where cust_email is null;
+-------------+------------+
| cust_name | cust_email |
+-------------+------------+
| Mouse House | NULL |
| E Fudd | NULL |
+-------------+------------+
2 rows in set (0.00 sec)

AND OR

这个也没啥好说的

in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> select prod_name, prod_price, vend_id from products where vend_id in (1002,1003);
+----------------+------------+---------+
| prod_name | prod_price | vend_id |
+----------------+------------+---------+
| Fuses | 3.42 | 1002 |
| Oil can | 8.99 | 1002 |
| Detonator | 13.00 | 1003 |
| Bird seed | 10.00 | 1003 |
| Carrots | 2.50 | 1003 |
| Safe | 50.00 | 1003 |
| Sling | 4.49 | 1003 |
| TNT (1 stick) | 2.50 | 1003 |
| TNT (5 sticks) | 10.00 | 1003 |
+----------------+------------+---------+
9 rows in set (0.00 sec)

这个感觉像是集合操作,在里面就选中。

not

这个操作就是取反。

1
2
3
4
5
6
7
8
9
10
11
mysql> select prod_name, prod_price, vend_id from products where vend_id not in (1002,1003);
+--------------+------------+---------+
| prod_name | prod_price | vend_id |
+--------------+------------+---------+
| .5 ton anvil | 5.99 | 1001 |
| 1 ton anvil | 9.99 | 1001 |
| 2 ton anvil | 14.99 | 1001 |
| JetPack 1000 | 35.00 | 1005 |
| JetPack 2000 | 55.00 | 1005 |
+--------------+------------+---------+
5 rows in set (0.00 sec)

通配符

百分号通配符

1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name like "Jet%";
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)

百分号代表任意字符出现任意次数。

下划线通配符

1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name like "JetPack _000";
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)

下划线通配符与百分号通配符意思相近,但是只能表示一个字符。

正则表达式匹配

MySQL的正则表达式用于匹配包含目标字段的内容:

如:

1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name REGEXP "Jet";
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)

LIKE匹配整个列。如果被匹配的文本在列值中出现, LIKE将不会找到它,相应的行也不被返回(除非使用通配符)。而REGEXP在列值内进行匹配,如果被匹配的文本在列值中出现, REGEXP将会找到它,相应的行将被返回。这是一个非常重要的差别。

使用.匹配

.表示任意一个字符,如下:

1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name REGEXP ".00";
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)

使用OR匹配

|表示或:

1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name REGEXP "1000|2000";
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)

匹配几个字符之一

1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name REGEXP "[123] Ton";
+-------------+
| prod_name |
+-------------+
| 1 ton anvil |
| 2 ton anvil |
+-------------+
2 rows in set (0.00 sec)

在这里面用[123]来单独表示某个字符的取值范围。如果没有[],则可能会出现匹配了1,2和3 Ton.

可以用:

1
2
3
4
5
6
7
8
9
mysql> select prod_name from products where prod_name REGEXP "[1-9] Ton";
+--------------+
| prod_name |
+--------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
+--------------+
3 rows in set (0.00 sec)

-表示范围.

特殊字符

\\作为前导.

匹配字符类

1
2
3
4
5
6
7
8
9
10
11
12
[:alnum:] 任意字母和数字(同[a-zA-Z0-9])
[:alpha:] 任意字符(同[a-zA-Z])
[:blank:] 空格和制表(同[\\t])
[:cntrl:] ASCII控制字符( 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]

匹配多个实例

1
2
3
4
5
6
* 0个或多个匹配
+ 1个或多个匹配(等于{1,})
? 0个或1个匹配(等于{0,1})
{n} 指定数目的匹配
{n,} 不少于指定数目的匹配
{n,m} 匹配数目的范围( m不超过255)

例如:

1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name REGEXP '\\(*\\)';
+----------------+
| prod_name |
+----------------+
| TNT (1 stick) |
| TNT (5 sticks) |
+----------------+
2 rows in set (0.00 sec)
1
2
3
4
5
6
7
8
mysql> select prod_name from products where prod_name REGEXP 'JetPack [:alnum:]{4}';
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.00 sec)

{4}代表[:alnum:]出现4次.

定位符

1
2
3
4
^ 文本的开始
$ 文本的结尾
[[:<:]] 词的开始
[[:>:]] 词的结尾

例子如下:

1
2
3
4
5
6
7
8
9
mysql> select prod_name from products where prod_name REGEXP '^[0-9\\.]';
+--------------+
| prod_name |
+--------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
+--------------+
3 rows in set (0.00 sec)

^表示开始,