戴树谦的博客


  • Home

  • Tags

  • Archives

  • Search

常见查询示例

Posted on 2019-02-15
Words count in article: 2.2k | Reading time ≈ 11

常见查询示例

  假设有一个表格,是商店为某些交易员(经销商)保存每种商品(项目号)的价格。假设每个交易者的每件商品都有一个固定的价格,那么(商品,交易者)就是记录的主键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
mysql> create database shop;
Query OK, 1 row affected (0.00 sec)

mysql> use shop;
Database changed

mysql> create table shop_tab(
-> 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));
Query OK, 0 rows affected (0.12 sec)

mysql> insert into shop_tab 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);
Query OK, 7 rows affected (0.05 sec)
Records: 7 Duplicates: 0 Warnings: 0

mysql> select * from shop_tab order by article;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | A | 3.45 |
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | B | 1.45 |
| 0003 | C | 1.69 |
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+--------+-------+
7 rows in set (0.00 sec)

1.列的最大值

1
2
3
4
5
6
7
mysql> select max(price) from shop_tab;
+------------+
| max(price) |
+------------+
| 19.95 |
+------------+
1 row in set (0.00 sec)

2.包含某一列的最大值的行

  使用子查询完成此操作

1
2
3
4
5
6
7
8
mysql> select * from shop_tab 
-> where price=(select max(price) from shop_tab);
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0004 | D | 19.95 |
+---------+--------+-------+
1 row in set (0.01 sec)

  按价格降序排序所有行,并使用特定于MySQL的LIMIT子句获取第一行

1
2
3
4
5
6
7
8
9
mysql> select * from shop_tab
-> order by price desc
-> limit 1;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0004 | D | 19.95 |
+---------+--------+-------+
1 row in set (0.00 sec)

3.每种商品的最高价格

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select article,max(price) as price                                             
-> from shop_tab
-> group by article
-> order by article;
+---------+-------+
| article | price |
+---------+-------+
| 0001 | 3.99 |
| 0002 | 10.99 |
| 0003 | 1.69 |
| 0004 | 19.95 |
+---------+-------+
4 rows in set (0.00 sec)

4.对于每种商品,找到价格最贵的经销商

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1解:以price为条件,使用where s1.article = s2.article或者any操作符使主查询一条记录
对应子查询的一条记录。
ANY 关键字必须接在一个比较操作符的后面,表示与子查询返回的任何值比较为 TRUE 则返回 TRUE
主查询的一条记录对应子查询多条记录会产生错误
(ERROR 1242 (21000): Subquery returns more than 1 row)。
mysql> select article,dealer,price
-> from shop_tab as s1
-> where price=(select max(s2.price)
-> from shop_tab as s2
-> where s1.article = s2.article
-> order by article
-> );
或者
mysql> select article,dealer,price
-> from shop_tab as s1
-> where price= any(select max(s2.price)
-> from shop_tab as s2
-> order by article
-> );
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+--------+-------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2解:筛选出每件商品最贵的价格作为s2,与原表S1内连接,显示两边表同时有对应的数据,
任何一边缺失数据就不显示
mysql> select s1.article,s1.dealer,s1.price
-> from shop_tab as s1 join(
-> select article,max(price) as price
-> from shop_tab group by article) as s2
-> where s1.article = s2.article and s1.price = s2.price
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+--------+-------+
4 rows in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
3解:s2左连接s1,通过s1.article = s2.article 两张表进行价格比较
mysql> select * from shop_tab as s1
-> left join shop_tab as s2
-> on s1.article = s2.article and s1.price < s2.price;
+---------+--------+-------+---------+--------+-------+
| article | dealer | price | article | dealer | price |
+---------+--------+-------+---------+--------+-------+
| 0001 | A | 3.45 | 0001 | B | 3.99 |
| 0001 | B | 3.99 | NULL | NULL | NULL |
| 0002 | A | 10.99 | NULL | NULL | NULL |
| 0003 | B | 1.45 | 0003 | C | 1.69 |
| 0003 | C | 1.69 | NULL | NULL | NULL |
| 0003 | D | 1.25 | 0003 | B | 1.45 |
| 0003 | D | 1.25 | 0003 | C | 1.69 |
| 0004 | D | 19.95 | NULL | NULL | NULL |
+---------+--------+-------+---------+--------+-------+
8 rows in set (0.00 sec)
然后再选取s2中为NULL值的行
mysql> select s1.article,s1.dealer,s1.price
-> from shop_tab as s1
-> left join shop_tab as s2
-> on s1.article = s2.article AND s1.price < s2.price
-> where s2.article is null;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+--------+-------+
4 rows in set (0.00 sec)

5.用户自定义变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> select @min_price:=min(price),@max_price:=max(price)
-> from shop_tab;
+------------------------+------------------------+
| @min_price:=min(price) | @max_price:=max(price) |
+------------------------+------------------------+
| 1.25 | 19.95 |
+------------------------+------------------------+
1 row in set (0.00 sec)

mysql> select * from shop_tab
-> where price = @min_price:=min(price)
-> \c
mysql> select * from shop_tab
-> where price = @min_price or price = @max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+--------+-------+
2 rows in set (0.00 sec)

6.使用外键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
CREATE TABLE person (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);

CREATE TABLE shirt (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),
PRIMARY KEY (id)
);

INSERT INTO person VALUES (NULL, 'Antonio Paz');

SELECT @last := LAST_INSERT_ID();

INSERT INTO shirt VALUES
(NULL, 'polo', 'blue', @last),
(NULL, 'dress', 'white', @last),
(NULL, 't-shirt', 'blue', @last);

INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');

SELECT @last := LAST_INSERT_ID();

INSERT INTO shirt VALUES
(NULL, 'dress', 'orange', @last),
(NULL, 'polo', 'red', @last),
(NULL, 'dress', 'blue', @last),
(NULL, 't-shirt', 'white', @last);

SELECT * FROM person;
+----+---------------------+
| id | name |
+----+---------------------+
| 1 | Antonio Paz |
| 2 | Lilliana Angelovska |
+----+---------------------+

SELECT * FROM shirt;
+----+---------+--------+-------+
| id | style | color | owner |
+----+---------+--------+-------+
| 1 | polo | blue | 1 |
| 2 | dress | white | 1 |
| 3 | t-shirt | blue | 1 |
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
| 7 | t-shirt | white | 2 |
+----+---------+--------+-------+


SELECT s.* FROM person p INNER JOIN shirt s
ON s.owner = p.id
WHERE p.name LIKE 'Lilliana%'
AND s.color <> 'white';

+----+-------+--------+-------+
| id | style | color | owner |
+----+-------+--------+-------+
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
+----+-------+--------+-------+


SHOW CREATE TABLE shirt\G
*************************** 1. row ***************************
Table: shirt
Create Table: CREATE TABLE `shirt` (
`id` smallint(5) unsigned NOT NULL auto_increment,
`style` enum('t-shirt','polo','dress') NOT NULL,
`color` enum('red','blue','orange','white','black') NOT NULL,
`owner` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

7.使用两个键搜索

  逻辑运算符or 使用一个主键能够被很好的优化,就像处理and一样
但是使用or去搜索两个不同的主键比较棘手

1
2
SELECT field1_index, field2_index FROM test_table
WHERE field1_index = '1' OR field2_index = '1'

  可以使用union结合两个单独的select语句进行查询,会更加有效。每个select只搜索一个键则会很好的优化

1
2
3
4
5
SELECT field1_index, field2_index
FROM test_table WHERE field1_index = '1'
UNION
SELECT field1_index, field2_index
FROM test_table WHERE field2_index = '1';

8.计算每日访问量

以下示例显示如何使用位组功能计算用户访问网页的每月天数。

1
2
3
4
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);

  示例表包含表示用户对页面的访问的年 - 月 - 日值。要确定这些访问每月发生的天数,请使用以下查询:

1
2
3
4
5
6
7
8
9
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1
GROUP BY year,month;

+------+-------+------+
| year | month | days |
+------+-------+------+
| 2000 | 01 | 3 |
| 2000 | 02 | 2 |
+------+-------+------+

  该查询计算每个年/月组合在表中显示的天数,并自动删除重复的条目

9.使用AUTO_INCREMENT

该AUTO_INCREMENT属性可用于为新行生成唯一标识:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> CREATE TABLE animals (
-> id MEDIUMINT NOT NULL AUTO_INCREMENT,
-> name CHAR(30) NOT NULL,
-> PRIMARY KEY (id)
-> );
Query OK, 0 rows affected (0.25 sec)

mysql> insert into animals(name) values ('dog'),('cat'),('penguin'),('lax'),('bird');
Query OK, 5 rows affected (0.04 sec)
Records: 5 Duplicates: 0 Warnings: 0

mysql> select * from animals;
+----+---------+
| id | name |
+----+---------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | bird |
+----+---------+
5 rows in set (0.00 sec)

  AUTO_INCREMENT列没有指定值,因此MySQL自动分配序列号。也可以显式地为列分配0来生成序列号,除非启用了NO_AUTO_VALUE_ON_ZERO SQL模式(NO_AUTO_VALUE_ON_ZERO影响AUTO_INCREMENT列的处理。一般情况下可以向该列插入NULL或0生成下一个序列号)。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> INSERT INTO animals (id,name) VALUES(0,'groundhog');
Query OK, 1 row affected (0.02 sec)

mysql> select * from animals;
+----+-----------+
| id | name |
+----+-----------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | bird |
| 6 | groundhog |
+----+-----------+
6 rows in set (0.01 sec)

  如果声明了列NOT NULL,则还可以分配NULL给列以生成序列号。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> INSERT INTO animals (id,name) VALUES(NULL,'squirrel');
Query OK, 1 row affected (0.04 sec)

mysql> select * from animals;
+----+-----------+
| id | name |
+----+-----------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | bird |
| 6 | groundhog |
| 7 | squirrel |
+----+-----------+
7 rows in set (0.00 sec)

  将任何其他值插入AUTO_INCREMENT列时,列被设置为该值,序列被重置,以便下一个自动生成的值按照最大列值的顺序生成。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql>INSERT INTO animals (id,name) VALUES(100,'rabbit');
Query OK, 1 row affected (0.04 sec)
mysql>INSERT INTO animals (id,name) VALUES(NULL,'mouse');
Query OK, 1 row affected (0.04 sec)
SELECT * FROM animals;
+-----+-----------+
| id | name |
+-----+-----------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
| 7 | groundhog |
| 8 | squirrel |
| 100 | rabbit |
| 101 | mouse |
+-----+-----------+

  AUTO_INCREMENT使用LAST_INSERT_ID() SQL函数或mysql_insert_id() C API函数检索最新自动生成的值 。这些函数是特定于连接的,因此它们的返回值不受另一个执行插入的连接的影响。

1
2
3
4
5
6
7
mysql> select LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 7 |
+------------------+
1 row in set (0.00 sec)

注意

  • 对于多行插入,LAST_INSERT_ID()和mysql_insert_id()实际上从插入的第一行返回AUTO_INCREMENT键。

  要从除1之外的AUTO_INCREMENT值开始,使用CREATE TABLE或ALTER TABLE设置该值,如下所示:

1
2
3
mysql>  ALTER TABLE animals AUTO_INCREMENT = 100;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0

MySQL检索信息

Posted on 2019-02-07
Words count in article: 3.4k | Reading time ≈ 15

从表中检索信息

  该SELECT语句用于从表中提取信息。声明的一般形式是:

1
2
3
SELECT what_to_select
FROM which_table
WHERE conditions_to_satisfy;

  what_to_select表示你想看到什么,这可以是列表中的一列, * 可以表示“ 所有列”。which_table表示要从中检索数据的表。该WHERE 条款是可选的。如果存在,则 conditions_to_satisfy指定行必须满足的一个或多个条件才有资格进行检索。

1
2
3
4
5
6
7
8
9
10
11
mysql> select name
-> from pet
-> where sex='m';
+--------+
| name |
+--------+
| Claws |
| Fang |
| Bowser |
+--------+
3 rows in set (0.00 sec)

1.选择所有数据

  SELECT最简单的形式从表中检索所有内容

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select * from pet;
+--------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+------------+
| Fluffy | Harold | cat | f | 1999-02-04 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| Chirpy | Genw | bird | f | 1998-09-11 | NULL |
+--------+--------+---------+------+------------+------------+
6 rows in set (0.00 sec)

  UPDATE语句修复错误记录 :

1
2
3
4
5
6
7
mysql> update pet
-> set birth='1990-01-01'
-> where name='Bowser';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql>

2.选择特定行

  例如,如果想验证刚才对Bowser出生日期所做的更改,请选择Bowser的记录,如下所示:

1
2
3
4
5
6
7
8
9
10
11
mysql> select *     
-> from pet
-> where name='Bowser';
+--------+-------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+-------+---------+------+------------+------------+
| Bowser | Diane | dog | m | 1990-01-01 | 1995-07-29 |
+--------+-------+---------+------+------------+------------+
1 row in set (0.00 sec)

mysql>

  字符串比较通常不区分大小写,因此可以将名称指定为’bowser’, ‘BOWSER’等等。查询结果是一样的。

  也可以在任何列上指定条件,例如想知道1997年或之后出生的动物:

1
2
3
4
5
6
7
8
9
10
mysql> select *                                       
-> from pet
-> where birth >= '1997-02-22';
+--------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat | f | 1999-02-04 | NULL |
| Chirpy | Genw | bird | f | 1998-09-11 | NULL |
+--------+--------+---------+------+------------+-------+
2 rows in set (0.00 sec)

  还可以使用 AND 进行组合条件进行查询

1
2
3
4
5
6
7
8
9
10
mysql> select *      
-> from pet
-> where species = 'dog' and sex = 'm';
+--------+-------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+-------+---------+------+------------+------------+
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1990-01-01 | 1995-07-29 |
+--------+-------+---------+------+------------+------------+
2 rows in set (0.00 sec)

  除了AND逻辑运算符还有OR。

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select *                                                        
-> from pet
-> where species = 'dog' or species = 'bird';
+--------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+------------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1990-01-01 | 1995-07-29 |
| Chirpy | Genw | bird | f | 1998-09-11 | NULL |
+--------+--------+---------+------+------------+------------+
4 rows in set (0.00 sec)

  AND和OR可以混合,但 AND优先级高于 OR。如果同时使用这两个运算符,最好使用括号明确指出条件应如何分组。

1
2
3
4
5
6
7
8
9
10
mysql> select *     
-> from pet
-> where (species='dog' and sex='f') or (species='bird' and sex='f');
+--------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+-------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Chirpy | Genw | bird | f | 1998-09-11 | NULL |
+--------+--------+---------+------+------------+-------+
2 rows in set (0.00 sec)

3.选择特定列

  如果不查看表中的整行,只需将感兴趣的列名进行逗号分隔。例如如果查询谁的动物什么时候出生,请选择name和 birth列:

1
2
3
4
5
6
7
8
9
10
11
12
mysql> SELECT name, birth FROM pet;
+--------+------------+
| name | birth |
+--------+------------+
| Fluffy | 1999-02-04 |
| Claws | 1994-03-17 |
| Buffy | 1989-05-13 |
| Fang | 1990-08-27 |
| Bowser | 1990-01-01 |
| Chirpy | 1998-09-11 |
+--------+------------+
6 rows in set (0.00 sec)

  要找出宠物属于谁,如下查询

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select owner from pet;
+--------+
| owner |
+--------+
| Harold |
| Gwen |
| Harold |
| Benny |
| Diane |
| Genw |
+--------+
6 rows in set (0.00 sec)

  要最小化输出,请通过添加关键字 DISTINCT 去除重复输出:

1
2
3
4
5
6
7
8
9
10
11
mysql> select distinct owner from pet;
+--------+
| owner |
+--------+
| Harold |
| Gwen |
| Benny |
| Diane |
| Genw |
+--------+
5 rows in set (0.00 sec)

  使用WHERE子句将行选择与列选择组合在一起。例如,仅获取狗和猫的出生日期,如下查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select name,species,birth
-> from pet
-> where species = 'dog' or species = 'cat';
+--------+---------+------------+
| name | species | birth |
+--------+---------+------------+
| Fluffy | cat | 1999-02-04 |
| Claws | cat | 1994-03-17 |
| Buffy | dog | 1989-05-13 |
| Fang | dog | 1990-08-27 |
| Bowser | dog | 1990-01-01 |
+--------+---------+------------+
5 rows in set (0.00 sec)

4.对行排序

  当行以某种有意义的方式排序时,通常更容易查询输出。要对结果进行排序,请使用ORDER BY子句。
  默认排序顺序是升序。要按反向(降序)排序,请将DESC关键字添加到要排序 的列名称后面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mysql> select name, birth from pet order by birth;
+--------+------------+
| name | birth |
+--------+------------+
| Buffy | 1989-05-13 |
| Bowser | 1990-01-01 |
| Fang | 1990-08-27 |
| Claws | 1994-03-17 |
| Chirpy | 1998-09-11 |
| Fluffy | 1999-02-04 |
+--------+------------+
6 rows in set (0.00 sec)

mysql> select name, species, birth from pet
-> order by species,birth desc;
+--------+---------+------------+
| name | species | birth |
+--------+---------+------------+
| Chirpy | bird | 1998-09-11 |
| Fluffy | cat | 1999-02-04 |
| Claws | cat | 1994-03-17 |
| Fang | dog | 1990-08-27 |
| Bowser | dog | 1990-01-01 |
| Buffy | dog | 1989-05-13 |
+--------+---------+------------+
6 rows in set (0.00 sec)

  该DESC关键字仅适用于紧邻的列名(birth); 它不会影响species列排序顺序。

  LIMIT 子句用于限制由 SELECT 语句返回的数据数量。下面是 LIMIT 子句与 OFFSET 子句一起使用时的语法:

1
2
3
SELECT column1, column2, columnN 
FROM table_name
LIMIT [no of rows] OFFSET [row num]

  引擎将返回从下一行开始直到给定的 OFFSET 为止的所有行。

5.日期计算

  要确定每只宠物的年龄,使用 TIMESTAMPDIFF()功能。它的参数是你所希望结果表达的 单位,以及取得差异的两个日期。以下查询显示了每只宠物的出生日期,当前日期和年龄。一个 别名(age)使得输出列更有意义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> SELECT name, birth, CURDATE(),
-> TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age
-> FROM pet;
+--------+------------+------------+------+
| name | birth | CURDATE() | age |
+--------+------------+------------+------+
| Fluffy | 1999-02-04 | 2019-02-19 | 20 |
| Claws | 1994-03-17 | 2019-02-19 | 25 |
| Buffy | 1989-05-13 | 2019-02-19 | 29 |
| Fang | 1990-08-27 | 2019-02-19 | 28 |
| Bowser | 1990-01-01 | 2019-02-19 | 29 |
| Chirpy | 1998-09-11 | 2019-02-19 | 20 |
+--------+------------+------------+------+
6 rows in set (0.00 sec)

  也可以使用order by 对age进行排序,不再演示


  下面说明TIMESTAMPDIFF函数的语法。

1
TIMESTAMPDIFF(unit,begin,end);

  TIMESTAMPDIFF函数返回begin-end的结果,其中begin和end是DATE或DATETIME表达式。

  TIMESTAMPDIFF函数允许其参数具有混合类型,例如,begin是DATE值,end可以是DATETIME值。 如果使用DATE值,则TIMESTAMPDIFF函数将其视为时间部分为“00:00:00”的DATETIME值。

  unit参数是确定(end-begin)的结果的单位,表示为整数。 以下是有效单位:
MICROSECOND(微秒)、SECOND(秒)、MINUTE(分钟)、HOUR(小时)、DAY(天)、WEEK(星期)、MONTH(月)、QUARTER(季度)、YEAR(年)


  类似的查询可用于确定死亡动物的死亡年龄。可以通过检查death值是否为null 。然后,对于那些非NULL值的,计算death和 birth值之差:

1
2
3
4
5
6
7
8
9
10
11
mysql> select name,birth,death,
-> timestampdiff(year,birth,death) as age
-> from pet
-> where death is not null
-> order by age;
+--------+------------+------------+------+
| name | birth | death | age |
+--------+------------+------------+------+
| Bowser | 1990-01-01 | 1995-07-29 | 5 |
+--------+------------+------------+------+
1 row in set (0.00 sec)

  MySQL提供了用于提取日期的部分,如一些功能 YEAR(), MONTH()和 DAYOFMONTH()。如下一个简单的查询birth和 MONTH(birth):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> select name,birth,month(birth) from pet; 
+--------+------------+--------------+
| name | birth | month(birth) |
+--------+------------+--------------+
| Fluffy | 1999-02-04 | 2 |
| Claws | 1994-03-17 | 3 |
| Buffy | 1989-05-13 | 5 |
| Fang | 1997-02-22 | 2 |
| Bowser | 1990-01-01 | 1 |
| Chirpy | 1998-09-11 | 9 |
+--------+------------+--------------+
6 rows in set (0.00 sec)

mysql> select name,birth
-> from pet
-> where month(birth)=5;
+-------+------------+
| name | birth |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
1 row in set (0.00 sec)

  DATE_ADD()可以将时间间隔添加到给定日期。如果将值添加到CURDATE(),然后提取月份部分MONTH(),结果将生成查找生日的月份:

1
2
3
4
5
6
7
8
mysql> select name,birth from pet
-> where month(birth)=month(date_add(curdate(),interval 2 month));
+-------+------------+
| name | birth |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
1 row in set (0.00 sec)

6.null 值

  要测试NULL,请使用IS NULL 和 IS NOT NULL运算符,如下所示

1
2
3
4
5
6
7
8
mysql> SELECT 1 IS NULL, 1 IS NOT NULL
-> ;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
| 0 | 1 |
+-----------+---------------+
1 row in set (0.00 sec)

  任何算术比较NULL的结果 也是NULL,所以你不能从这种比较中获得任何有意义的结果。
  在MySQL中,0或NULL 为假,其他则为真。布尔运算的默认真值是1。

7.模式匹配

  MySQL提供标准的SQL模式匹配以及基于扩展正则表达式的模式匹配,类似于Unix实用程序(如vi,grep和 sed)使用的扩展正则表达式 。

  SQL模式匹配可以使用 “_” 匹配任何单个字符并且%匹配任意数量的字符(包括零个字符)。在MySQL中,SQL模式默认情况下不区分大小写。使 用SQL模式时不要使用 =或<>,改用LIKE或 NOT LIKE比较运算符。

  查找以b(b%)开头。%fy(以fy结尾),%w%(包含w字符)

1
2
3
4
5
6
7
8
9
10
mysql> select  *
-> from pet
-> where name like 'b%';
+--------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+------------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Bowser | Diane | dog | m | 1990-01-01 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+
2 rows in set (0.00 sec)

  要查找包含五个字符的名称:

1
2
3
4
5
6
7
8
mysql> select * from pet where name like '_____';
+-------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+-------+--------+---------+------+------------+-------+
2 rows in set (0.00 sec)

  MySQL提供的另一种模式匹配使用扩展的正则表达式。当为这种类型的模式测试匹配时,使用 REGEXP和NOT REGEXP运算符(或 RLIKE和 NOT RLIKE,它们是同义词)。

  以下列表描述了扩展正则表达式的一些特征:

  . 匹配任何单个字符。
字符类[…]匹配括号内的任何字符。例如, [abc]匹配a, b或c。[a-z] 匹配任何字母,而[0-9] 匹配任何数字。

  *匹配前面事物的零个或多个实例。例如,x 匹配任意数量的x字符, [0-9]匹配任意数量的数字,.*匹配任意数量的任何字符。

  如果模式与测试值中的任何位置匹配,则正则表达式模式匹配成功 。(这与LIKE模式匹配不同,仅在模式与整个值匹配时才会成功。)
使用锚定模式以使其与要测试的值的开头或结尾匹配,请使用模式^开头或$结尾。

1
2
3
4
5
6
7
8
mysql> select * from pet where name regexp '^b';
+--------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+------------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Bowser | Diane | dog | m | 1990-01-01 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+
2 rows in set (0.00 sec)

8.计数行

  COUNT(*)计算行数,因此计算动物数量的查询如下所示:

1
2
3
4
5
6
7
mysql> select count(*) from pet;
+----------+
| count(*) |
+----------+
| 6 |
+----------+
1 row in set (0.00 sec)

  计算每个人拥有几个宠物

1
2
3
4
5
6
7
8
9
10
11
mysql> select owner,count(*) from pet group by owner;
+--------+----------+
| owner | count(*) |
+--------+----------+
| Benny | 1 |
| Diane | 1 |
| Genw | 1 |
| Gwen | 1 |
| Harold | 2 |
+--------+----------+
5 rows in set (0.00 sec)

  上述查询使用GROUP BY对每个owner进行分组。使用COUNT()结合 GROUP BY在各种分组表征数据时非常有用。

  想要得到每种性别的动物数量仅适用于已知性别的动物:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> select species,sex,count(*)                                            
-> from pet
-> where sex is not null
-> group by species,sex;
+---------+------+----------+
| species | sex | count(*) |
+---------+------+----------+
| bird | f | 1 |
| cat | f | 1 |
| cat | m | 1 |
| dog | f | 1 |
| dog | m | 2 |
+---------+------+----------+
5 rows in set (0.00 sec)

9.使用多个表

  pet 表记录了宠物的基本信息,还需要一张表记录他们生活中的事件,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> create table event (name varchar(20),date date,type varchar(20),remark varchar(250));
Query OK, 0 rows affected (0.30 sec)
mysql> select * from event;
+--------+------------+--------+-----------------+
| name | date | type | remark |
+--------+------------+--------+-----------------+
| Fluffy | 1995-05-15 | litter | 4,3female,1male |
| Buffy | 1993-06-23 | litter | 4,3female,1male |
| Buffy | 1994-06-19 | litter | 4,3female,1male |
| Chirpy | 1999-03-19 | daily | go away |
| Fang | 1991-10-12 | kennel | NULL |
| Bowser | 1991-10-12 | kennel | NULL |
+--------+------------+--------+-----------------+
6 rows in set (0.00 sec)

  假设你想要得到宠物下崽的年龄。宠物的下崽日期在 event表格中,但要计算她在该日期的年龄,需要她的出生日期,该日期存储在 pet表格中。这意味着查询需要两个表:

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select pet.name,timestampdiff(year,birth,date) as age,remark 
-> from pet inner join event
-> on pet.name = event.name
-> where event.type='litter';
+--------+------+-----------------+
| name | age | remark |
+--------+------+-----------------+
| Fluffy | 3 | 4,3female,1male |
| Buffy | 4 | 4,3female,1male |
| Buffy | 5 | 4,3female,1male |
+--------+------+-----------------+
3 rows in set (0.00 sec)

  该FROM子句连接两个表,因为查询需要从两个表中提取信息

  组合(连接)来自多个表的信息时,需要指定一个表中的记录如何与另一个表中的记录匹配。

  该查询使用 INNER JOIN来组合表。只有当两个表都满足ON子句中指定的条件时,内部联接才允许其中一个表中的行出现在结果中。在这个例子中, ON子句指定 pet表中的name列必须的匹配 event表的name列 。如果名称出现在一个表中但不出现在另一个表中,则该行不会出现在结果中,因为该ON 子句中的条件失败。

  由于该name列出现在两个表中,因此必须具体说明引用该列时的表。这是通过将表名添加到列名称来完成的。

  如果要将表中的记录与同一表中的其他记录进行比较,有时将表连接到自身会很有用。例如,要在宠物中找到繁殖对,可以pet自身加入表格,以生成候选对:

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select p1.name,p1.sex,p2.name,p2.sex,p1.species 
->from pet as p1 inner join pet as p2
->on p1.species = p2.species
->and p1.sex = 'f' and p1.death is null
->and p2.sex = 'm' and p2.death is null;
+--------+------+-------+------+---------+
| name | sex | name | sex | species |
+--------+------+-------+------+---------+
| Fluffy | f | Claws | m | cat |
| Buffy | f | Fang | m | dog |
+--------+------+-------+------+---------+
2 rows in set (0.00 sec)

  在此查询中,我们为表名指定别名以引用列,并保持每个列引用与表关联的表的实例。

MySQL语句(菜鸟教程)

Posted on 2019-02-02
Words count in article: 4k | Reading time ≈ 20

创建数据库

语法为:
CREATE DATABASE 数据库名;

1
2
mysql> create database dsq_mysql;
Query OK, 1 row affected (0.01 sec)

删除数据库

语法为:
drop database <数据库名>;

1
2
mysql> drop database test;
Query OK, 0 rows affected (0.00 sec)

选择数据库

  在你连接到 MySQL 数据库后,可能有多个可以操作的数据库,所以你需要选择你要操作的数据库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| 16netlab |
| dsq_mysql |
| mysql |
| performance_schema |
| shop |
+--------------------+
6 rows in set (0.00 sec)

mysql> use dsq_mysql;
Database changed

创建数据表

创建MySQL数据表需要 表名、表字段名、表字段定义:
CREATE TABLE table_name (column_name column_type);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> create table dsq_table(
-> dsq_id int unsigned auto_increment,
-> title varchar(100) not null,
-> name varchar(20) not null,
-> sex varchar(10) not null,
-> date DATE ,
-> primary key(dsq_id))
-> default charset=utf8;
Query OK, 0 rows affected (0.14 sec)

mysql> desc dsq_table;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| dsq_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(100) | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
| sex | varchar(10) | NO | | NULL | |
| date | DATE | YES | | NULL | |
+--------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

删除数据表

语法为:
DROP TABLE table_name ;

1
2
mysql> drop table test;
Query OK, 0 rows affected (0.05 sec)

插入数据

MySQL 表中使用 INSERT INTO SQL语句来插入数据。
语法为:

1
2
3
INSERT INTO table_name ( field1, field2,...fieldN )  
VALUES
( value1, value2,...valueN );
1
2
3
4
5
6
7
8
9
mysql> insert into dsq_table (title,name,sex,date)
-> values
-> ('study','qwe','m',now());
Query OK, 1 row affected, 1 warning (0.22 sec)

mysql> insert into dsq_table (title,name,sex,date)
-> values
-> ('play','asd','f','2008-02-22');
Query OK, 1 row affected (0.02 sec)

查询数据

MySQL 数据库使用SQL SELECT语句来查询数据。
以下为在MySQL数据库中查询数据通用的 SELECT 语法:

1
2
3
4
SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]
  • 查询语句中可以使用一个或者多个表,表之间使用逗号(,)分割,并使用WHERE语句来设定查询条件。
  • SELECT 命令可以读取一条或者多条记录。
  • 可以使用星号(*)来代替其他字段,SELECT语句会返回表的所有字段数据
  • 可以使用 WHERE 语句来包含任何条件。
  • 可以使用 LIMIT 属性来设定返回的记录数。
  • 可以通过OFFSET指定SELECT语句开始查询的数据偏移量。默认情况下偏移量为0。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> select * from dsq_table;
+--------+-------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+-------+------+-----+------------+
| 1 | study | qwe | m | 2019-02-21 |
| 2 | play | asd | f | 2008-02-22 |
+--------+-------+------+-----+------------+
2 rows in set (0.00 sec)

mysql> select name,sex from dsq_table;
+------+-----+
| name | sex |
+------+-----+
| qwe | m |
| asd | f |
+------+-----+
2 rows in set (0.00 sec)

where子句

  如需有条件地从表中选取数据,可将 WHERE 子句添加到 SELECT 语句中。
语法如下:

1
2
SELECT field1, field2,...fieldN FROM table_name1, table_name2...
[WHERE condition1 [AND [OR]] condition2.....
  • 查询语句中可以使用一个或者多个表,表之间使用逗号, 分割,并使用WHERE语句来设定查询条件。
  • 可以在 WHERE 子句中指定任何条件。
  • 可以使用 AND 或者 OR 指定一个或多个条件。
  • WHERE 子句也可以运用于 SQL 的 DELETE 或者 UPDATE 命令。
  • WHERE 子句类似于程序语言中的 if 条件,根据 MySQL 表中的字段值来读取指定的数据。
  • WHERE 子句的字符串比较是不区分大小写的。 使用 BINARY 关键字来设定 WHERE 子句的字符串比较是区分大小写的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> select * from dsq_table 
-> where sex = 'm';
+--------+-------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+-------+------+-----+------------+
| 1 | study | qwe | m | 2019-02-21 |
+--------+-------+------+-----+------------+
1 row in set (0.01 sec)

mysql> select * from dsq_table
-> where binary sex = 'F';
Empty set (0.00 sec)

mysql> select * from dsq_table
-> where dsq_id > 1;
+--------+-------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+-------+------+-----+------------+
| 2 | play | asd | f | 2008-02-22 |
+--------+-------+------+-----+------------+
1 row in set (0.00 sec)

Update查询

  需要修改或更新 MySQL 中的数据,我们可以使用 SQL UPDATE 命令来操作

1
2
UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]
  • 可以同时更新一个或多个字段。
  • 可以在 WHERE 子句中指定任何条件。
  • 可以在一个单独表中同时更新数据。
1
2
3
4
5
6
7
8
9
10
11
12
mysql> update dsq_table set name = 'zxc',date = '2000-01-01' 
-> where dsq_id = 2;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from dsq_table;
+--------+-------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+-------+------+-----+------------+
| 1 | study | qwe | m | 2019-02-21 |
| 2 | play | zxc | f | 2000-01-01 |
+--------+-------+------+-----+------------+
2 rows in set (0.00 sec)

可以看到第二行已经更新

delect 语句

  使用 SQL 的 DELETE FROM 命令来删除 MySQL 数据表中的记录

1
DELETE FROM table_name [WHERE Clause]

  如果没有指定 WHERE 子句,MySQL 表中的所有记录将被删除。

1
2
3
4
5
6
7
8
9
10
11
mysql> delete from dsq_table  
-> where dsq_id = 1;
Query OK, 1 row affected (0.03 sec)

mysql> select * from dsq_table;
+--------+-------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+-------+------+-----+------------+
| 2 | play | zxc | f | 2000-01-01 |
+--------+-------+------+-----+------------+
1 row in set (0.00 sec)

like子句

  有时候我们需要根据某个字符去匹配某个字段(field)中的所有记录,即模糊查询、模式匹配,这时我们就需要在 WHERE 子句中使用 SQL LIKE 子句。
   SQL LIKE 子句中使用百分号 %字符来表示任意字符,类似于UNIX或正则表达式中的星号 *。
如果没有使用百分号 %, LIKE 子句与等号 = 的效果是一样的。
语法为:

1
2
3
SELECT field1, field2,...fieldN 
FROM table_name
WHERE field1 LIKE condition1 [AND [OR]] filed2 = 'somevalue'
1
2
3
4
5
6
7
8
9
mysql> select * from dsq_table 
-> where title like '%lab';
+--------+--------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+--------+------+-----+------------+
| 3 | netlab | dsq | f | 2019-03-25 |
| 4 | netlab | dsq | m | 2019-03-25 |
+--------+--------+------+-----+------------+
2 rows in set (0.00 sec)

排序(order by)

  如果我们需要对读取的数据进行排序,我们就可以使用 MySQL 的 ORDER BY 子句来设定按哪个字段哪种方式来进行排序,再返回搜索结果
语法为:

1
2
3
/*ASC 或 DESC 关键字来设置查询结果是按升序或降序排列。 默认情况下,它是按升序排列*/
SELECT field1, field2,...fieldN table_name1, table_name2...
ORDER BY field1, [field2...] [ASC [DESC]]

  下面读取dsq_table表,按照升序和降序的方式排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> select * from dsq_table
-> order by dsq_id;
+--------+--------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+--------+------+-----+------------+
| 2 | play | zxc | f | 2000-01-01 |
| 3 | netlab | dsq | f | 2019-03-25 |
| 4 | netlab | dsq | m | 2019-03-25 |
+--------+--------+------+-----+------------+
3 rows in set (0.00 sec)

mysql> select * from dsq_table
-> order by dsq_id desc;
+--------+--------+------+-----+------------+
| dsq_id | title | name | sex | date |
+--------+--------+------+-----+------------+
| 4 | netlab | dsq | m | 2019-03-25 |
| 3 | netlab | dsq | f | 2019-03-25 |
| 2 | play | zxc | f | 2000-01-01 |
+--------+--------+------+-----+------------+
3 rows in set (0.00 sec)

GROUP BY 语句

  GROUP BY 语句根据一个或多个列对结果集进行分组。在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。
  语法为:

1
2
3
4
SELECT column_name, function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;

  创建表emplotee_tbl,并插入数据,使用 GROUP BY 语句 将数据表按名字进行分组,并统计每个人有多少条记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> SELECT * FROM employee_tbl;
+----+------+---------------------+--------+
| id | name | date | singin |
+----+------+---------------------+--------+
| 1 | ming | 2016-04-22 15:25:33 | 1 |
| 2 | wang | 2016-04-20 15:25:47 | 3 |
| 3 | li | 2016-04-19 15:26:02 | 2 |
| 4 | wang | 2016-04-07 15:26:14 | 4 |
| 5 | ming | 2016-04-11 15:26:40 | 4 |
| 6 | ming | 2016-04-04 15:26:54 | 2 |
+----+------+---------------------+--------+
6 rows in set (0.00 sec)

mysql> SELECT name, COUNT(*) FROM employee_tbl GROUP BY name;
+------+----------+
| name | COUNT(*) |
+------+----------+
| li | 1 |
| ming | 3 |
| wang | 2 |
+------+----------+
3 rows in set (0.00 sec)

  GROUP BY子句 WITH ROLLUP ,可以实现在分组统计数据基础上再进行相同的统计

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select name,sum(singin) as singin_count 
-> from employee_tbl
-> group by name with rollup;
+------+--------------+
| name | singin_count |
+------+--------------+
| li | 2 |
| ming | 7 |
| wang | 7 |
| NULL | 16 |
+------+--------------+
4 rows in set (0.00 sec)

  与上表相比多了一行对每人登录次数的统计,可以使用coalesce设置一个取代Null的名称
语法为:

1
select coalesce(a,b,c);

  返回第一个非零参数或者NULL(Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
mysql> SELECT COALESCE(NULL,1);
+------------------+
| COALESCE(NULL,1) |
+------------------+
| 1 |
+------------------+
1 row in set (0.03 sec)

mysql> SELECT COALESCE(NULL,null,null);
+--------------------------+
| COALESCE(NULL,NULL,NULL) |
+--------------------------+
| NULL |
+--------------------------+
1 row in set (0.00 sec)

mysql> select coalesce(name,'total'),sum(singin) as singin_count
-> from employee_tbl
-> group by name with rollup;
+------------------------+--------------+
| coalesce(name,'total') | singin_count |
+------------------------+--------------+
| li | 2 |
| ming | 7 |
| wang | 7 |
| total | 16 |
+------------------------+--------------+
4 rows in set (0.00 sec)

MySQL连接表

  可以在 SELECT, UPDATE 和 DELETE 语句中使用 Mysql 的 JOIN 来联合多表查询。
  JOIN 按照功能大致分为如下三类:

  • INNER JOIN(内连接,或等值连接):两边表同时有对应的数据,即任何一边缺失数据就不显示。
  • LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
  • RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。

有如下两个表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> select * from dsq_tbl;
+----+-------+--------+------------+
| id | title | author | date |
+----+-------+--------+------------+
| 1 | qwe | 1 | 2000-01-01 |
| 2 | rty | 2 | 2000-01-02 |
| 3 | uiop | 1 | 2000-01-03 |
| 4 | asd | 3 | 2000-01-04 |
| 5 | fghj | 2 | 2000-01-05 |
| 6 | kl | 4 | 2000-01-06 |
+----+-------+--------+------------+
6 rows in set (0.00 sec)

mysql> select * from dsq_tbl2;
+--------+-------+
| author | stars |
+--------+-------+
| 1 | 20 |
| 2 | 35 |
| 3 | 47 |
+--------+-------+
3 rows in set (0.00 sec)

  接下来使用 inner join(也可以省略 inner 使用 join,效果一样)来连接两张表并显示

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select * from dsq_tbl inner join dsq_tbl2 
-> on dsq_tbl.author = dsq_tbl2.author;
+----+-------+--------+------------+--------+-------+
| id | title | author | date | author | stars |
+----+-------+--------+------------+--------+-------+
| 1 | qwe | 1 | 2000-01-01 | 1 | 20 |
| 2 | rty | 2 | 2000-01-02 | 2 | 35 |
| 3 | uiop | 1 | 2000-01-03 | 1 | 20 |
| 4 | asd | 3 | 2000-01-04 | 3 | 47 |
| 5 | fghj | 2 | 2000-01-05 | 2 | 35 |
+----+-------+--------+------------+--------+-------+
5 rows in set (0.00 sec)
以上语句等价于 select * from dsq_tbl,dsq_tbl2 WHERE dsq_tbl.author = dsq_tbl2.author;

  left join 与 join 有所不同。 left join 会读取左边数据表的全部数据,即便右边表无对应数据

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select * from dsq_tbl left join dsq_tbl2  
-> on dsq_tbl.author = dsq_tbl2.author;
+----+-------+--------+------------+--------+-------+
| id | title | author | date | author | stars |
+----+-------+--------+------------+--------+-------+
| 1 | qwe | 1 | 2000-01-01 | 1 | 20 |
| 3 | uiop | 1 | 2000-01-03 | 1 | 20 |
| 2 | rty | 2 | 2000-01-02 | 2 | 35 |
| 5 | fghj | 2 | 2000-01-05 | 2 | 35 |
| 4 | asd | 3 | 2000-01-04 | 3 | 47 |
| 6 | kl | 4 | 2000-01-06 | NULL | NULL |
+----+-------+--------+------------+--------+-------+
6 rows in set (0.00 sec)

  right join 会读取右边数据表的全部数据,即便左边边表无对应数据。

1
2
3
4
5
6
7
8
9
10
11
mysql> select * from dsq_tbl right  join dsq_tbl2 on dsq_tbl.author = dsq_tbl2.author;
+------+-------+--------+------------+--------+-------+
| id | title | author | date | author | stars |
+------+-------+--------+------------+--------+-------+
| 1 | qwe | 1 | 2000-01-01 | 1 | 20 |
| 2 | rty | 2 | 2000-01-02 | 2 | 35 |
| 3 | uiop | 1 | 2000-01-03 | 1 | 20 |
| 4 | asd | 3 | 2000-01-04 | 3 | 47 |
| 5 | fghj | 2 | 2000-01-05 | 2 | 35 |
+------+-------+--------+------------+--------+-------+
5 rows in set (0.00 sec)

下面为一个left join 的应用场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解:
select e.last_name,e.first_name,d.dept_no
from employees as e left join dept_emp as d
on e.emp_no = d.emp_no

https://www.cnblogs.com/leochenliang/p/7364665.html(left join on and 与 left join on where的区别)

关于NULL值

运算符操作:

  • IS NULL: 当列的值是 NULL,此运算符返回 true。
  • IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。
  • <=>: 比较操作符(不同于=运算符),当比较的的两个值为 NULL 时返回 true。

  关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。在 MySQL 中,NULL 值与任何其它值的比较(即使是 NULL)永远返回 false,即 NULL = NULL 返回false 。MySQL 中处理 NULL 使用 IS NULL 和 IS NOT NULL 运算符。

1
2
select * , columnName1 + ifnull(columnName2,0) from tableName;
columnName1,columnName2 为 int 型,当 columnName2 中,有值为 null 时,columnName1+columnName2=null, ifnull(columnName2,0) 把 columnName2 中 null 值转为 0。

  下面为一个left jion 与 null值判断的组合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
获取所有非manager的员工emp_no
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解:先使用LEFT JOIN连接两张表,再从此表中选出dept_no值为NULL对应的emp_no记录
select e.emp_no
from employees e left join dept_manager d
on e.emp_no = d.emp_no
where d.emp_no is null;

ALTER

  修改数据表名或者修改数据表字段时,需要使用到MySQL ALTER命令

1.删除,添加或修改表字段

  如果数据表中只剩余一个字段则无法使用DROP来删除字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mysql> describe dsq_table;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| dsq_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(100) | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
| sex | varchar(10) | NO | | NULL | |
| date | date | YES | | NULL | |
+--------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

mysql> alter table dsq_table drop sex;
Query OK, 0 rows affected (0.56 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> describe dsq_table;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| dsq_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(100) | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
| date | date | YES | | NULL | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

  添加列,并定义字段数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> alter table dsq_table add sex varchar(5);
Query OK, 0 rows affected (0.28 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> describe dsq_table;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| dsq_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(100) | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
| date | date | YES | | NULL | |
| sex | varchar(5) | YES | | NULL | |
+--------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

  如果需要指定新增字段的位置,可以使用MySQL提供的关键字 FIRST (设定位第一列), AFTER 字段名(设定位于某个字段之后)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> alter table dsq_table add hobby varchar(100) after name;
Query OK, 0 rows affected (0.28 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> describe dsq_table;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| dsq_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(100) | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
| hobby | varchar(100) | YES | | NULL | |
| date | date | YES | | NULL | |
| sex | varchar(5) | YES | | NULL | |
+--------+------------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
2.修改字段类型及名称

如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句
语法为:

1
2
ALTER TABLE testalter_tbl MODIFY c CHAR(10); #把字段 c 的类型从 CHAR(1) 改为 CHAR(10)
ALTER TABLE testalter_tbl CHANGE j i INT; #把字段 j 的名称变为 i ,类型为 INT
3.关于Null 值和默认值

  如果不设置默认值,MySQL会自动设置该字段默认为 NULL,如下所示

1
2
3
4
5
6
7
8
9
10
mysql> describe dsq_tbl;
+--------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------+------+-----+---------+----------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(20) | YES | | NULL | |
| author | varchar(20) | YES | | NULL | |
| date | date | YES | | NULL | |
+--------+----------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

  当进行修改字段时,可以指定是否包含值或者是否设置默认值。需要设置not null ,默认值才会有效。语法为 :

1
2
mysql> ALTER TABLE tablename 
-> MODIFY col_name column_definition NOT NULL DEFAULT ***;

  如下,将字段date 默认值更改为当前日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> alter table dsq_tbl modify date timestamp not null default CURRENT_timestamp;
Query OK, 8 rows affected (0.34 sec)
Records: 8 Duplicates: 0 Warnings: 0

mysql> describe dsq_tbl;
+--------+----------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------+------+-----+-------------------+----------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(20) | YES | | NULL | |
| author | varchar(20) | YES | | NULL | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+--------+----------------------+------+-----+-------------------+----------------+
4 rows in set (0.00 sec)
4.修改字段默认值

语法为:

1
ALTER  TABLE tbl_name  ALTER  col_name {SET DEFAULT literal | DROP DEFAULT}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
mysql> alter table dsq_tbl alter author set default 10;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> describe dsq_tbl;
+--------+----------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------+------+-----+-------------------+----------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(20) | YES | | NULL | |
| author | varchar(20) | YES | | 10 | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+--------+----------------------+------+-----+-------------------+----------------+
4 rows in set (0.00 sec)

mysql> alter table dsq_tbl alter author drop default;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> describe dsq_tbl;
+--------+----------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------+------+-----+-------------------+----------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(20) | YES | | NULL | |
| author | varchar(20) | YES | | NULL | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+--------+----------------------+------+-----+-------------------+----------------+
4 rows in set (0.01 sec)
5.修改表名

  如果需要修改表名,可以在 ALTER TABLE 语句中使用 RENAME 子句 ,或者RENAME TABLE语句

语法:

1
2
3
RENAME TABLE
tbl_name TO new_tbl_name
[, tbl_name2 TO new_tbl_name2] ...

  RENAME TABLE重命名一个或多个表。但是必须具有ALTER与 DROP原始表的权限,以及CREATE与 INSERT新表的权限

1
2
3
RENAME TABLE old_table TO new_table;
等价于
ALTER TABLE old_table RENAME new_table;

  RENAME TABLE 与 ALTER TABLE 的不同在于,RENAME TABLE 可以在一个语句中重命名多个表

1
2
3
4
交换两个表的名称
RENAME TABLE old_table TO tmp_table,
new_table TO old_table,
tmp_table TO new_table;

  使用RENAME TABLE将表从一个数据库移动到另一个数据库:

1
RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

表的显示

在进入MYSQL时,提示的第二行有这样一句话” Commands end with ; or \g.”

1
2
3
4
5
6
7
8
9
mysql> select * from dsq_table \g
+--------+--------+------+-------+------------+------+
| dsq_id | title | name | hobby | date | sex |
+--------+--------+------+-------+------------+------+
| 2 | play | zxc | NULL | 2000-01-01 | NULL |
| 3 | netlab | dsq | NULL | 2019-03-25 | NULL |
| 4 | netlab | dsq | NULL | 2019-03-25 | NULL |
+--------+--------+------+-------+------------+------+
3 rows in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
使用 \G 是垂直显示结果(ego       (\G) Send command to mysql server, display result vertically.)。
mysql> select * from dsq_table \G
*************************** 1. row ***************************
dsq_id: 2
title: play
name: zxc
hobby: NULL
date: 2000-01-01
sex: NULL
*************************** 2. row ***************************
dsq_id: 3
title: netlab
name: dsq
hobby: NULL
date: 2019-03-25
sex: NULL
*************************** 3. row ***************************
dsq_id: 4
title: netlab
name: dsq
hobby: NULL
date: 2019-03-25
sex: NULL
3 rows in set (0.00 sec)

MySQL建库建表、数据插入

Posted on 2019-01-29
Words count in article: 2.6k | Reading time ≈ 11

连接与断开服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@docker-study var]#   mysql --host=hostname  --user=user  --password
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 37
Server version: 5.6.43 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

输入查询

  介绍几个输入查询的基本原则来熟悉mysql的工作原理。
  这是一个简单的查询,要求服务器说明它的版本号和当前日期。

1
2
3
4
5
6
7
8
9
mysql>  SELECT VERSION(), CURRENT_DATE;
+-----------+--------------+
| VERSION() | CURRENT_DATE |
+-----------+--------------+
| 5.6.43 | 2019-02-18 |
+-----------+--------------+
1 row in set (0.00 sec)

mysql>

  关键字可以输入任何字母。以下查询是等效的,即不区分大小写:

1
2
3
mysql> SELECT VERSION(), CURRENT_DATE;
mysql> select version(), current_date;
mysql> SeLeCt vErSiOn(), current_DATE;

  这是另一个查询。它演示了您可以将 mysql用作简单的计算器:

1
2
3
4
5
6
7
mysql> SELECT SIN(PI()/4), (4+1)*5;
+------------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+------------------+---------+
| 0.70710678118655 | 25 |
+------------------+---------+
1 row in set (0.02 sec)

  到目前为止显示的查询是相对较短的单行语句。也可以在一行中输入多个语句。用分号结束每一个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> SELECT VERSION(); SELECT NOW();
+-----------+
| VERSION() |
+-----------+
| 5.6.43 |
+-----------+
1 row in set (0.00 sec)

+---------------------+
| NOW() |
+---------------------+
| 2019-02-18 11:01:14 |
+---------------------+
1 row in set (0.00 sec)

  多行的冗长查询不是问题,mysql通过查找终止分号来确定语句的结束位置,而不是查找输入行的结尾。
这是一个简单的多行语句:

1
2
3
4
5
6
7
8
9
10
mysql> select 
-> user()
-> ,
-> current_date;
+----------------+--------------+
| user() | current_date |
+----------------+--------------+
| web@172.19.0.3 | 2019-02-18 |
+----------------+--------------+
1 row in set (0.00 sec)

  如果决定不想执行正在输入的查询,请键入\c以下命令取消它 :

1
2
3
4
mysql> SELECT
-> USER()
-> \c
mysql>

  在这里,也请注意提示。它会mysql>在键入后切换回来 \c,提供反馈以指示mysql已为新查询做好准备。
  下表显示了可能看到的每个提示,并总结了它们对mysql所处状态的含义 。

提示 含义
mysql> 准备好进行新查询
-> 等待下一行的多行查询
‘> 等待下一行,以单引号(’)开头的字符串
“> 等待下一行,以双引号开头的字符串(”)
`> 等待下一行,以反引号(`)开头的标识符
/*> 等待下一行,以/*开头的描述

  在MySQL中,可以编写由任一字符’或”字符包括的字符串(例如’hello’或”goodbye”),并且 mysql允许输入跨越多行的字符串。看到’>或 “>提示时,表示输入的行包含以a ‘ 或”quote字符开头的字符串,但没有输入终止字符串的匹配引号。这通常表明遗漏了引号字符。例如:

1
2
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30;
'>

  通过转义字符取消查询,如果只输入\c,会被认为是引号内的内容

1
2
3
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30;
'> '\c
mysql>

  `>提示类似于 ‘>和”>提示,但表示你已经开始但尚未完成反引号引用的标识符。

创建数据库

1
2
mysql> CREATE DATABASE 16netlab;
Query OK, 1 row affected (0.01 sec)

  在Unix下,数据库名称是区分大小写的(不像SQL关键字)。表名也是如此。(在Windows下,此限制不适用,但必须在给定查询中使用相同的字母表引用数据库和表。但是,出于各种原因,建议的最佳做法始终是使用相同字母。)
注意

  • 如果收到错误 ERROR 1044(42000):ERROR 1044 (42000): Access denied for user ‘micah‘@’localhost’ to database ‘menagerie’,这意味着用户帐户没有必要的权限。

  要使16netlab为当前数据库,请使用以下语句:

1
2
mysql> use 16netlab;
Database changed

  数据库只需创建一次,但每次开始mysql 会话时都必须选择它才能使用。通过如上所示的语句来完成此操作。或者可以在调用mysql时在命令行上选择数据库。需要提供的所有连接参数之后指定其名称。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@docker-study ~]# docker exec -it web mysql -h mysql2 -u web -p 16netlab
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 348
Server version: 5.6.43 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

   SELECT DATABASE() 查看当前选择使用哪个数据库

1
2
3
4
5
6
7
8
9
mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| 16netlab |
+------------+
1 row in set (0.00 sec)

mysql>

创建表

  创建数据库很容易,但此时它是空的

1
2
mysql> SHOW TABLES;
Empty set (0.00 sec)

  更难的部分是决定数据库的结构应该是什么:需要哪些表以及每个表中应该包含哪些列。
  例如一张包含每只宠物记录的表格。这可以称为pet表格,它应该包含每个动物名称以及长度限制值。如果家中有多个人饲养宠物,列出每只动物的主人,记录一些基本的描述性信息,如物种和性别,年龄。随着时间的推移,年龄会发生变化,这意味着必须经常更新记录。相反,最好存储固定值,如出生日期。如果需要年龄,可以将其计算为当前日期和出生日期之间的差异。MySQL提供了进行日期算术的功能。

  你可能会想到在pet表格中有用的其他类型的信息,但到目前为止确定的信息是足够的:名称,所有者,物种,性别,出生和死亡日期。
  使用CREATE TABLE语句指定表的布局:

1
2
3
mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),
-> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
Query OK, 0 rows affected (0.20 sec)

  VARCHAR数据类型对于name、 owner和species 列是不错的选择,因为列值的长度不同。定义列的长度时根据实际情况合理选择。通常,可以选择1-65535中的任何长度。

  可以选择几种类型的值来表示动物记录中的性别,例如’m’和 ‘f’,或者可能’male’和 ‘female’。最简单的是使用单个字符’m’和’f’。
DATE对于birth和death 列 使用数据类型是一个相当明显的选择。
  创建表后,SHOW TABLES应该产生一些输出:

1
2
3
4
5
6
7
mysql> SHOW TABLES;
+--------------------+
| Tables_in_16netlab |
+--------------------+
| pet |
+--------------------+
1 row in set (0.00 sec)

  要验证表是否按预期方式创建,使用DESCRIBE语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 | |
+---------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

mysql>

添加数据到表

  创建表后需要填充它。使用LOAD DATA和 INSERT语句
  假设宠物记录可以如此处所示。

名字 主人 种类 性别 出生日期 死亡日期
Fluffy Harold cat f 1993-02-04
Claws Gwen cat m 1994-03-17
Buffy Harold dog f 1989-05-13
Fang Benny dog m 1990-08-27
Bowser Diane dog m 1979-08-31 1995-07-29
Chirpy Gwen bird f 1998-09-11
Whistler Gwen bird 1997-12-09
Slim Benny snake m 1996-04-29

  因为从空表开始,所以填充它的一种简单方法是为每个动物创建一个包含行的文本文件,然后使用单个语句将文件内容加载到表中。

  可以创建一个文本文件pet.txt,每行包含一个记录,其值由制表符分隔,并按照CREATE TABLE语句中列出的顺序给出 。对于缺失值(例如未知性别或仍然生活的动物的死亡日期),可以使用NULL 值。要在文本文件中表示这些,请使用 \N(反斜杠,大写-N)。例如,惠斯勒鸟的记录看起来像这样(值之间的空格是单个制表符):

1
Whistler        Gwen    bird    \N      1997-12-09      \N

  要将文本文件加载pet.txt到 pet表中,请使用以下语句:

1
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;

  如果需要,可以在LOAD DATA语句中显式指定列值分隔符和行结束标记,但默认值为制表符和换行符。这些语句正确读取pet.txt。

  如果语句失败,则默认情况下MySQL安装可能没有启用本地文件功能。

  如果要一次添加一条新记录,该 INSERT语句很有用。在最简单的形式中,按照CREATE TABLE语句中列出的列的顺序为每列提供值 。假设黛安得到了一只名为“ Puffball ”的仓鼠。可以使用如下INSERT语句添加 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
mysql> INSERT INTO pet
VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
字符串和日期值在此处指定为带引号的字符串。此外,可以直接插入NULL 以表示缺失值。
mysql> INSERT INTO pet
-> VALUES ('Fluffy','Harold','cat','f','1999-02-04',NULL);
Query OK, 1 row affected (0.02 sec)

mysql> INSERT INTO pet VALUES ('Claws','Gwen','cat','m','1994-03-17',NULL);
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO pet VALUES ('Buffy','Harold','dog','f','1989-05-13',NULL);
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO pet VALUES ('Fang','Benny','dog','m','1990-08-27',NULL);
Query OK, 1 row affected (0.06 sec)

mysql> INSERT INTO pet VALUES ('Bowser','Diane','dog','m','1979-08-31','1995-07-29');
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO pet VALUES ('Chirpy','Genw','bird','f','1998-09-11',null);
Query OK, 1 row affected (0.42 sec)

mysql> SELECT * FROM pet;
+--------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+------------+
| Fluffy | Harold | cat | f | 1999-02-04 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| Chirpy | Genw | bird | f | 1998-09-11 | NULL |
+--------+--------+---------+------+------------+------------+
6 rows in set (0.00 sec)

使用Docker在linux上部署MySQL

Posted on 2019-01-25
Words count in article: 3.3k | Reading time ≈ 14

下载MySQL服务器Docker镜像

使用命令下载MYSQL-Community:

1
docker pull mysql/mysql-server:tag

   tag是你想拉的镜像版本的标签(例如5.5, 5.6,5.7, 8.0,或latest)。如果省略则会下载最新GA版本的MySQL-community-server的镜像。

1
2
3
4
5
6
7
8
[root@docker-study ~]# docker pull mysql/mysql-server:5.6
5.6: Pulling from mysql/mysql-server
a8d84c1f755a: Pull complete
36934cee5f0d: Pull complete
5a6871e55c04: Pull complete
7c67030deb6e: Pull complete
Digest: sha256:5a1cfc50ab8d147cb163c32558c7334519f5bb69ea82587d480f9f7050b77047
Status: Downloaded newer image for mysql/mysql-server:5.6

  使用以下命令列出下载的Docker镜像:

1
2
3
4
[root@docker-study ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql/mysql-server 5.6 ad62049ce4ab 6 weeks ago 217MB
[root@docker-study ~]#

启动MySQL服务器实例

   将MySQL镜像启动为容器:

1
2
3
[root@docker-study ~]# docker run --name=mysql1 -d mysql/mysql-server:5.6
321d33b946e7eb8ebea4fe829d1cfb953c6dd5663021088fb9cff21bcea2a112
[root@docker-study ~]#

    –name用于为容器提供自定义名称,该选项是可选的;,如果没有提供容器名称,则生成随机的名称。如果先前的docker pull或docker run 命令未下载指定名称和标记的镜像, 则现在下载该图像。下载完成后,开始初始化容器,并在运行docker ps命令时容器显示在正在运行的容器列表中 ; 例如:

1
2
3
4
[root@docker-study ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
321d33b946e7 mysql/mysql-server:5.6 "/entrypoint.sh mysq…" 3 minutes ago Up 3 minutes (healthy) 3306/tcp mysql1
[root@docker-study ~]#

   初始化完成后,命令的输出将包含为root用户生成的随机密码; 例如,使用以下命令检查密码:

1
2
3
[root@docker-study ~]# docker logs mysql1 2>&1 | grep GENERATED
[Entrypoint] GENERATED ROOT PASSWORD: mOkuHorEKBEh4plym@KYsXYk%Ih
[root@docker-study ~]#

连接到Container内的MySQL服务器

    服务器准备就绪后,可以在刚刚启动的MySQL Server容器中运行 mysql客户端,并将其连接到MySQL服务器。使用docker exec -it命令在已启动的Docker容器中进入 mysql客户端,输入生成的root密码。因为MYSQL_ONETIME_PASSWORD 默认情况下该选项为true,所以在将mysql客户端连接 到服务器之后,重置服务器root密码,如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@docker-study ~]# docker exec -it mysql1 mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 50
Server version: 5.6.43

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456');
Query OK, 0 rows affected (0.00 sec)

容器shell访问

   要使用shell访问MySQL Server容器,请使用 docker exec -it命令在容器内启动bash shell:

1
2
[root@docker-study ~]# docker exec -it mysql1 bash
bash-4.2#

   然后可以在容器内运行Linux命令。例如,要查看容器内server数据目录中的内容

1
2
3
bash-4.2# ls /var/lib/mysql
auto.cnf ib_logfile0 ib_logfile1 ibdata1 mysql mysql.sock performance_schema test
bash-4.2#

停止和删除MySQL容器

   使用以下命令停止创建的MySQL Server容器:

1
2
3
[root@docker-study ~]# docker stop mysql1
mysql1
[root@docker-study ~]#

   docker stop向 mysqld进程发送SIGTERM信号 ,以便正常关闭服务器。

   另请注意,当容器的主进程(MySQL服务器容器中的mysqld)停止时,Docker容器会自动停止。

1
2
3
4
5
6
7
8
9
10
11
12
要再次启动MySQL Server容器:
docker start mysql1

使用单个命令停止并重新启动MySQL Server容器:
docker restart mysql1

要删除MySQL容器,请先将其停止,然后使用 docker rm命令:
docker stop mysql1
docker rm mysql1

如果希望同时删除服务器数据目录的 Docker卷,请将该-v选项添加到 docker rm命令。
docker rm -v mysql1

配置MySQL服务器

   启动MySQL Docker容器时,可以通过docker run命令将配置选项传递给服务器; 例如,对于MySQL服务器:

1
2
3
[root@docker-study ~]# docker run --name mysql1 -d mysql/mysql-server:5.6 --character-set-server=utf8mb4 --collation-server=utf8mb4_col
ae491dde8ad07c8db420facc6a7b6546b3ae375d7e37430e4a01a6b4c34913f3
[root@docker-study ~]#

   该命令启动MySQL服务器 utf8mb4作为默认字符集和 utf8mb4_col数据库的默认排序规则。

   配置MySQL服务器的另一种方法是准备配置文件并将其安装在容器内的服务器配置文件的位置。

持久化数据和配置更改

   Docker容器原则上是短暂的,如果容器被删除或损坏,预计会丢失任何数据或配置。 但是,Docker卷提供了一种机制来保存在Docker容器中创建的数据。在初始化时,MySQL Server容器为服务器数据目录创建一个Docker卷。在容器上运行docker inspect命令的JSON输出有一个 Mount键,其值提供有关数据目录卷的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@docker-study ~]# docker inspect mysql1
[
…………
"Mounts": [
{
"Type": "volume",
"Name": "4ae57cb3823bf75c18b2212530fee42bc7d851446a5fee48406542c04df62221",
"Source": "/var/lib/docker/volumes/4ae57cb3823bf75c18b2212530fee42bc7d851446a5fee48406542c04df62221/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],…………

   输出显示/var/lib/docker/volumes/4ae57cb3823bf75c18b2212530fee42bc7d
851446a5fee48406542c04df62221/_data主机文件夹(主机上持有数据)已安装在 /var/lib/mysql容器内的服务器数据目录中。

   保留数据的另一种方法是 在创建容器时 使用–mount绑定安装主机目录。可以使用相同的技术来持久保存服务器的配置。以下命令创建MySQL Server容器并绑定安装数据目录和服务器配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@docker-study ~]#  ls
anaconda-ks.cfg datadir docker initial-setup-ks.cfg my.cnf src
[root@docker-study ~]# cat my.cnf
[client]
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock
[mysql]
default-character-set=utf8
[mysqld]
basedir = /usr/local/mysql
datadir = /var/lib/mysql
port = 3306
socket = /usr/local/mysql/mysql.sock
character-set-server=utf8
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[root@docker-study ~]# docker run --name=mysql1 \
--mount type=bind,src=/root/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=/root/datadir,dst=/var/lib/mysql \
-d mysql/mysql-server:5.6
58d707e7a9f75b38516d17dc54ee3685e00052969c01c887b40f0ac8f819a936
[root@docker-study ~]# ls datadir/
ibdata1 ib_logfile0 ib_logfile1 mysql performance_schema test
[root@docker-study ~]#

   安装 path-on-host-machine/my.cnf 到/etc/my.cnf(容器内部的配置文件),同时 path-on-host-machine/datadir 到/var/lib/mysql(数据容器内的目录)。必须满足以下条件才能使绑定安装正常工作:

   配置文件 path-on-host-machine/my.cnf 必须已存在,并且必须包含使用用户启动mysql服务器的规范:

1
2
3
[mysqld]
user=mysql
…………

   数据目录 path-on-host-machine/datadir 必须已存在。要进行服务器初始化,目录必须为空。还可以安装预先填充数据的目录并启动服务器; 但是必须确保使用与创建数据的服务器相同的配置来启动Docker容器,并在启动容器时装入所需的任何主机文件或目录。

运行其他初始化脚本

如果在创建数据库后立即要在数据库上运行任何.sh或 .sql脚本,则可以将它们放入主机目录,然后将目录 /docker-entrypoint-initdb.d/挂载在容器内部。例如,对于MySQL Server容器:

1
2
3
docker run --name=mysql1 \
--mount type=bind,src=/path-on-host-machine/scripts/,dst=/docker-entrypoint-initdb.d/ \
-d mysql/mysql-server:tag

从另一个Docker容器中的应用程序连接到MySQL

   通过设置Docker网络,您可以允许多个Docker容器相互通信,以便另一个Docker容器中的客户端应用程序可以访问服务器容器中的MySQL Server。首先,创建一个Docker网络:

1
2
3
[root@docker-study ~]# docker network create my-custom-net
e78c79012d0e865acc06f043f03e9a900a5a478780fc0d7fb30a82ae0c644303
[root@docker-study ~]#

   然后,在创建和启动服务器和客户端容器时,使用该–network选项将它们放在您创建的网络上。例如:

1
2
3
4
5
[root@docker-study ~]# docker run --name=mysql2 --network=my-custom-net -d mysql/mysql-server:5.6
80415ae4ba16a3e89f3b7afc5d1f4ffde028fc65a66ff7f03810828070e6a17f
[root@docker-study ~]# docker run --name=web --network=my-custom-net -d httpd
264833168ac671eda95d0dd10547ce9bfa18bf83bc97531f85de202f72886088
[root@docker-study ~]#

  在mysql容器中设置web用户

1
2
3
4
5
mysql> create user web@172.19.0.3 identified by '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on *.* to web@172.19.0.3;
Query OK, 0 rows affected (0.00 sec)

   然后,web容器可以使用mysql2主机名连接到mysql2容器, 反之亦然,因为Docker会自动为给定的容器名称设置DNS。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@docker-study var]# docker exec -it web  mysql --host=mysql2 --user=web --password
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 37
Server version: 5.6.43 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

服务器错误日志

   首次使用服务器容器启动MySQL服务器时, 如果满足以下任一条件,则不会生成服务器错误日志:

  • 已装入主机的服务器配置文件,但该文件不包含系统变量 log_error。
  • 尚未安装主机的服务器配置文件,但Docker环境变量 MYSQL_LOG_CONSOLE 是true(MySQL 5.6服务器容器的变量的默认状态false)。然后将MySQL服务器的错误日志重定向到 stderr,以便错误日志进入Docker容器的日志,并使用docker logs mysqld-container 命令查看 。

   要使MySQL Server在两个条件之一为真时生成错误日志,请使用该 –log-error 选项 ,配置服务器以在容器内的特定位置生成错误日志。要保留错误日志,请将主机文件挂载到容器内错误日志的位置,如上文中所述。但是必须确保其容器内的MySQL Server具有对挂载的主机文件有写访问权。

Docker环境变量

   创建MySQL Server容器时,可以使用–env选项(-e简而言之)配置MySQL实例,并指定以下一个或多个环境变量。

注意

   如果挂载的数据目录不为空,则以下变量都不会产生任何影响,因为之后不会尝试进行服务器初始化。在容器启动期间,不会修改文件夹中任何预先存在的内容,包括任何旧服务器设置。

   布尔变量包括 MYSQL_RANDOM_ROOT_PASSWORD, MYSQL_ONETIME_PASSWORD和MYSQL_ALLOW_EMPTY_PASSWORD, MYSQL_LOG_CONSOLE 通过使用任何非零长度的字符串设置它们来实现。
例如”0”,”false”或 “no”不会使它们为假,但实际上使它们成立。这是MySQL Server容器的已知问题。

  • MYSQL_RANDOM_ROOT_PASSWORD:当此变量为true(这是默认状态,除非 MYSQL_ROOT_PASSWORD 或MYSQL_ALLOW_EMPTY_PASSWORD 设置为true)时,将在启动Docker容器时生成服务器root用户的随机密码。密码打印到stdout容器中,可以通过查看容器的日志找到。
  • MYSQL_ONETIME_PASSWORD:当变量为true(这是默认状态,除非 MYSQL_ROOT_PASSWORD 已设置或MYSQL_ALLOW_EMPTY_PASSWORD 设置为true)时,root用户的密码设置为expired,必须先更改才能正常使用MySQL。
  • MYSQL_DATABASE:此变量允许指定要在镜像启动时创建的数据库的名称。如果用户名和密码均由 MYSQL_USER 和MYSQL_PASSWORD提供,创建用户并授予该数据库(对应于超级用户权限GRANT ALL)。指定的数据库由 CREATE DATABASE IF NOT EXIST语句创建,因此如果数据库已存在,则该变量无效。
  • MYSQL_USER, MYSQL_PASSWORD:这些变量结合使用来创建用户并设置该用户的密码,并为该用户授予该MYSQL_DATABASE 变量指定的数据库的超级用户权限 。MYSQL_USER 和 MYSQL_PASSWORD 用于创建用户,如果这两个变量没有设置,则忽略。如果两个变量都已设置但未设置 MYSQL_DATABASE ,则创建用户时没有任何权限。

注意

  没有必要使用这种机制创建root用户,这是MYSQL_ROOT_PASSWORD 和 MYSQL_RANDOM_ROOT_PASSWORD两种机制默认创建的,除非 MYSQL_ALLOW_EMPTY_PASSWORD = ture。

  • MYSQL_ROOT_HOST:默认情况下,MySQL会创建 ‘root‘@’localhost’帐户。此帐户只能从容器内部连接。要允许来自其他主机的根连接,请设置此环境变量。例如,该值 为172.17.0.1允许来自运行容器的主机的连接。该选项仅接受一个参数,但允许使用通配符(例如, MYSQL_ROOT_HOST=172...*或MYSQL_ROOT_HOST=%)。
  • MYSQL_LOG_CONSOLE:当变量为true(变量的MySQL 5.6服务器容器的默认状态为false)时,MySQL服务器的错误日志被重定向到 stderr,以便错误日志进入Docker容器的日志,并且可以使用docker logs mysqld-container 命令查看 。

注意

   如果已挂载主机的服务器配置文件,则该变量无效。
MYSQL_ROOT_PASSWORD:此变量指定为MySQL root帐户设置的密码。

警告

   在命令行上设置MySQL root用户密码是不安全的。作为显式指定密码的替代方法,可以使用容器文件路径为密码文件设置变量,然后从主机中装入包含容器文件路径密码的文件。这仍然不是很安全,因为密码文件的位置仍然暴露。最好使用默认设置, MYSQL_RANDOM_ROOT_PASSWORD=true 并且 MYSQL_ONETIME_PASSWORD=true。

  • MYSQL_ALLOW_EMPTY_PASSWORD。将其设置为true以允许使用root用户的空密码启动容器。

警告

   将此变量设置为true是不安全的,因为它会使MySQL实例完全不受保护,从而允许任何人获得完整的超级用户访问权限。最好使用默认设置, MYSQL_RANDOM_ROOT_PASSWORD=true 并且MYSQL_ONETIME_PASSWORD=true 。

MySQL介绍

Posted on 2019-01-23
Words count in article: 1.8k | Reading time ≈ 6

什么是MySQL

    MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的关系数据库管理系统(RDBMS)应用软件之一。

MySQL数据库是关系型的

    关系数据库将数据存储在单独的表中,而不是将所有数据放在一个大的库房中。数据库结构被组织成针对速度优化的物理文件。逻辑模型具有数据库,表,视图,行和列等对象,可提供灵活的编程环境。可以设置管理不同数据字段之间关系的规则,例如一对一,一对多,唯一,必需或可选,以及不同表之间的”指针”。数据库强制执行这些规则,因此使用设计良好的数据库,应用程序永远不会看到不一致,重复,孤立,过时或丢失的数据。

    ”MYSQL” 的SQL部分代表 “ 结构化查询语言 ”。SQL是用于访问数据库的最常用的标准化语言。根据编程环境,可以直接输入SQL(例如,生成报告),将SQL语句嵌入到用其他语言编写的代码中,或使用隐藏SQL语法的特定于语言的API。

MySQL数据库服务器非常快速,可靠,可扩展且易于使用

    MySQL Server最初是为了比现有解决方案更快地处理大型数据库而开发的,并且已经成功地在高要求的生产环境中使用了好几年。虽然在不断发展的今天,MySQL服务器提供了丰富而有用的功能集。它的连接性,速度和安全性使MySQL Server非常适合访问Internet上的数据库。

MySQL Server适用于客户端/服务器或嵌入式系统。

    MySQL数据库软件是一个C/S系统,由支持不同后端的多线程SQL服务器,几个不同的客户端程序和库,管理工具以及各种应用程序编程接口(API)组成。
MySQL Server作为嵌入式多线程库,可以将其链接到应用程序,以获得更小,更快,更易于管理的独立产品。

MySQL特点

  • 内部和可移植性
  • 用C和C ++编写。
  • 经过多种不同编译器的测试。
  • 适用于许多不同的平台。
  • 为了便于携带,在MySQL 5.5及更高版本中使用CMake。以前的系列使用GNU Automake,Autoconf和Libtool。
  • 使用Purify(商业内存泄漏检测器)以及GPL工具Valgrind(http://developer.kde.org/~sewardj/)进行测试。
  • 使用具有独立模块的多层服务器设计。
  • 设计为使用内核线程完全多线程,以便在可用时轻松使用多个CPU。
  • 提供事务性和非事务性存储引擎。
  • 使用非常快的 B-tree 磁盘表 (MyISAM)实现索引压缩。
  • 旨在使添加其他存储引擎相对容易。如果要为内部数据库提供SQL接口,这非常有用。
  • 使用非常快速的基于线程的内存分配系统。
  • 使用优化的嵌套循环连接执行速度非常快。
  • 实现内存中的哈希表用作临时表。
  • 使用应尽可能快的高度优化的类库实现SQL函数。通常在查询初始化之后根本没有内存分配。
  • 将服务器作为单独的程序提供,用于客户端/服务器网络环境,以及作为可嵌入(链接)到独立应用程序的库。此类应用程序可以单独使用,也可以在没有网络的环境中使用。

数据类型

  • 许多数据类型:有符号/无符号整数,8个字节长的数据,float(浮点型), double(双精度型), char(字符), varchar(变长字符串), binary(二进制),varbinary(可变二进制), text(文本), blob, date, time, datetime, timestamp, year, set, enum,和开放GIS空间类型。
  • 固定长度和可变长度的字符串类型。

函数和语句

    SELECT列表和 WHERE子句查询中的 完整运算符和函数支持 。例如:

1
2
3
mysql> SELECT CONCAT(first_name, ' ', last_name)
-> FROM citizen
-> WHERE income/dependents > 10000 AND age > 30;
  • 完全支持SQL GROUP BY和 ORDER BY子句。支持基函数(COUNT(), AVG(), STD(), SUM(), MAX(), MIN(),和GROUP_CONCAT())。
  • 支持LEFT OUTER JOIN和 RIGHT OUTER JOIN使用标准SQL和ODBC语法。
  • 根据标准SQL的要求支持表和列上的别名。
  • 支持DELETE, INSERT, REPLACE,和 UPDATE以返回更改(受影响)的行数,或返回通过连接到服务器时设置标志,而不是匹配的行的数量。
  • 支持特定于MySQL的SHOW语句,用于检索有关数据库,存储引擎,表和索引的信息。支持 INFORMATION_SCHEMA数据库,根据标准SQL实现。
  • 一个EXPLAIN语句来显示优化器如何解决一个查询。
  • 表名或列名中函数名的独立性。例如,ABS是一个有效的列名。唯一的限制是,对于函数调用,函数名和它后面的“ (”之间不允许有空格 。
  • 可以在同一语句中引用来自不同数据库的表。

安全

  • 特权和密码系统,非常灵活和安全,可以进行基于主机的验证。
  • 连接到服务器时加密所有密码流量的密码安全性。

可扩展性和限制

  • 支持大型数据库。我们将MySQL Server与包含5000万条记录的数据库结合使用。
  • 每个表最多支持64个索引。每个索引可以包含1到16列或部分列。InnoDB表的最大索引宽度为767字节或3072字节。MyISAM表的最大索引宽度为1000个字节。索引可使用的柱的前缀CHAR, VARCHAR, BLOB,或 TEXT列类型。

连接

  • 客户端可以使用多种协议连接到MySQL Server:
    i. 客户端可以在任何平台上使用TCP / IP套接字进行连接。
    ii. 在Windows系统上,如果使用该–enable-named-pipe选项启动服务器,则客户端可以使用命名管道进行连接。如果使用该–shared-memory选项启动,Windows服务器也支持共享内存连接。客户端可以使用该–protocol=memory选项通过共享内存进行连接。
    iii. 在Unix系统上,客户端可以使用Unix域套接字文件进行连接。
  • MySQL客户端程序可以用多种语言编写。用C编写的客户端库可用于用C或C ++编写的客户端,或者用于提供C绑定的任何语言。
  • 提供C,C ++,Eiffel,Java,Perl,PHP,Python,Ruby和Tcl的API,使MySQL客户端能够以多种语言编写。

客户端和工具

  • MySQL包括几个客户端和实用程序。这些包括命令行程序,如 mysqldump和 mysqladmin,以及图形程序,如 MySQL Workbench。
  • MySQL Server内置支持SQL语句来检查,优化和修复表。这些语句可以从命令行通过 mysqlcheck客户端获得。MySQL还包括myisamchk,这是一个非常快速的命令行实用程序,用于在MyISAM 表上执行这些操作。
  • 可以使用–help 或-?选项调用MySQL程序以获取在线帮助。

Cisco UCS B200 M2安装操作系统

Posted on 2019-01-19
Words count in article: 304 | Reading time ≈ 1

由于项目需要,要求把上图系统更换为 CentOS7. 踩了不少坑,折腾一天。
服务器的型号为UCS B200 M2 ,需要在网页登录他的管理器,本地的java环境为jdk-6u10。6版本的每一个我都试了,只有这个可以。
在kvm manager的页面可以下载kvm console 的java程序,在本地运行就可以了

该刀片服务器重装\安装系统需要从本地映射镜像到服务器,也是在网上看的服务器配置指导才知道,我还想着拿个显示屏怼上呢。映射步骤如下:

1.点击virtual Medis (如果报错虚拟磁盘本地库无法加载,那就是java版本的问题了)

2.左侧有”Add Images”,选中需要安装的系统就可以了

3.勾选上第一列的Mapped ,即将本地镜像文件映射到 “Virtual CD/DVD”

4.重启

5.在该界面进入boot menu ,更改启动顺序

6.选择”Cisco Virtual CD/DVD 1.22”,不要选择EFI那一项

之后就是安装CentOS的步骤了,除了在分盘的时候把之前的分区先删除干净之外,其他步骤都相同了

编译安装mysql-server5.6.32

Posted on 2019-01-16
Words count in article: 440 | Reading time ≈ 2

摘自:http://www.cnblogs.com/yaohan/p/6288620.html

1
2
wget http://downloads.mysql.com/archives/get/file/mysql-5.6.32.tar.gz  
tar -zxvf mysql-5.6.32.tar.gz

安装编译环境

1
2
3
4
5
6
yum install gcc gcc-c++
yum install -y ncurses-devel
yum install -y cmake
yum install -y libaio
yum install -y bison
yum install -y perl-Module-Install.noarch

编译

1
2
3
4
5
6
7
8
9
10
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql  
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock
-DDEFAULT_CHARSET=utf8
-DDEFAULT_COLLATION=utf8_general_ci
-DWITH_INNOBASE_STORAGE_ENGINE=1
-DWITH_ARCHIVE_STORAGE_ENGINE=1
-DWITH_BLACKHOLE_STORAGE_ENGINE=1
-DMYSQL_DATADIR=/home/mysqldata
-DMYSQL_TCP_PORT=3306
-DENABLE_DOWNLOADS=1

若要重新运行配置,需要删除目录内CMakeCache.txt文件

1
rm CMakeCache.txt
1
make && make install

使用下面的命令查看是否有mysql用户及用户组

1
2
3
4
5
6
7
8
cat /etc/passwd   #查看用户列表
cat /etc/group #查看用户组列表

如果没有就创建
groupadd mysql
useradd -g mysql mysql
修改/usr/local/mysql权限
chown -R mysql:mysql /usr/local/mysql

修改配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
cp support-files/my-default.cnf /etc/my.cnf
vi /etc/my.cnf


-----my.cnf begin------
[client]
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock

[mysql]
default-character-set=utf8


[mysqld]
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M

# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin

# These are commonly set, remove the # and set as required.
basedir = /usr/local/mysql
datadir = /home/mysqldata/
port = 3306
# server_id = .....
socket = /usr/local/mysql/mysql.sock
character-set-server=utf8
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
-----my.cnf end------

初始化数据库

1
2
cd /usr/local/mysql/
./scripts/mysql_install_db --user=mysql --datadir=/home/mysqldata

修改文件和目录权限,否则开启服务会报错

1
2
chown -R mysql:root /usr/local/mysql/mysql.sock
chown -R mysql:root /usr/local/mysql

测试开启编译安装的Mysql

1
/usr/local/mysql/bin/mysqld_safe

运行正常则添加启动脚本

1
2
3
4
cp support-files/mysql.server /etc/init.d/mysql
chkconfig mysql on
service mysql start --启动MySQL
ln -s /usr/local/mysql/bin/mysql /usr/bin

harbor配置文件介绍

Posted on 2019-01-15
Words count in article: 2.9k | Reading time ≈ 13

There are two categories of parameters in harbor.cfg, required parameters and optional parameters.
在harbor.cfg中有两类参数,必需参数和可选参数。

required parameters: These parameters are required to be set in the configuration file. They will take effect if a user updates them in harbor.cfg and run the install.sh script to reinstall Harbor.
required参数:需要在配置文件中设置这些参数。如果用户更新它们harbor.cfg 并运行 install.sh 脚本以重新安装Harbor,它们将生效。

optional parameters: These parameters are optional for updating, i.e. user can leave them as default and update them on Web Portal after Harbor is started. If they are set in harbor.cfg, they only take effect in the first launch of Harbor. Subsequent update to these parameters in harbor.cfg will be ignored.
可选参数:这些参数对于更新是可选的,即用户可以将它们保留为默认值,并在启动Harbour后在Web Portal(门户网站)上更新它们。如果它们已经启用harbor.cfg,它们只会在首次启动Harbour时生效。harbor.cfg将忽略对这些参数的后续更新。

Note: If you choose to set these parameters via the Portal, be sure to do so right after Harbor is started. In particular, you must set the desired auth_mode before registering or creating any new users in Harbor. When there are users in the system (besides the default admin user), auth_mode cannot be changed.
注意:如果你选择通过Portal设置这些参数,请务必在Harbour启动后立即执行此操作。特别是,你必须在Harbour中注册或创建任何新用户之前设置auth_mode。当系统中有用户时(除默认管理员用户外), 无法更改auth_mode。

Required parameters: 必须参数

hostname: The target host’s hostname, which is used to access the Portal and the registry service. It should be the IP address or the fully qualified domain name (FQDN) of your target machine, e.g., 192.168.1.10 or reg.yourdomain.com. Do NOT use localhost or 127.0.0.1 for the hostname - the registry service needs to be accessible by external clients!
hostname:目标主机的主机名,用于访问Portal和registry服务。它应该是目标计算机的IP地址或完全限定的域名(FQDN),例如,192.168.1.10或reg.yourdomain.com。不要使用localhost或127.0.0.1作为主机名 - 外部客户端需要访问registry服务!

ui_url_protocol: (http or https. Default is http) The protocol used to access the Portal and the token/notification service. If Notary is enabled, this parameter has to be https. By default, this is http.
ui_url_protocol :( http或https。默认为http)用于访问Portal和令牌/通知服务的协议。如果启用了公证,则此参数必须为https。默认情况下是http。

db_password: The root password for the PostgreSQL database used for db_auth. Change this password for any production use!
db_password:用于db_auth的PostgreSQL数据库的root密码。生产环境中要修改密码!

max_job_workers: (default value is 10) The maximum number of replication workers in job service. For each image replication job, a worker synchronizes all tags of a repository to the remote destination. Increasing this number allows more concurrent replication jobs in the system. However, since each worker consumes a certain amount of network/CPU/IO resources, please carefully pick the value of this attribute based on the hardware resource of the host.
max_job_workers :(默认值为10)作业服务中的最大复制工作数。对于每个镜像复制作业,工作程序将存储库的所有标记同步到远程目标。增加此数量可以在系统中实现更多并发复制作业。但是,由于每个工作者都消耗一定量的网络/ CPU / IO资源,请根据主机的硬件资源仔细选择该属性的值。

customize_crt: (on or off. Default is on) When this attribute is on, the prepare script creates private key and root certificate for the generation/verification of the registry’s token. Set this attribute to off when the key and root certificate are supplied by external sources.
customize_crt:(开启或关闭,默认为开启),如果此属性开启,在准备脚本创建registry的令牌生成/验证私钥和根证书。当外部源提供密钥和根证书时,将此属性设置为off。

ssl_cert: The path of SSL certificate, it’s applied only when the protocol is set to https.
ssl_cert:SSL证书的路径,仅在协议设置为https时应用。

ssl_cert_key: The path of SSL key, it’s applied only when the protocol is set to https.
ssl_cert_key:SSL密钥的路径,仅在协议设置为https时应用。

secretkey_path: The path of key for encrypt or decrypt the password of a remote registry in a replication policy.
secretkey_path:用于加密或解密复制策略中远程registry密码的密钥路径。

log_rotate_count: Log files are rotated log_rotate_count times before being removed. If count is 0, old versions are removed rather than rotated.
log_rotate_count:日志文件在被删除之前会被轮换log_rotate_count次。如果count为0,则删除旧版本而不会轮转。

log_rotate_size: Log files are rotated only if they grow bigger than log_rotate_size bytes. If size is followed by k, the size is assumed to be in kilobytes. If the M is used, the size is in megabytes, and if G is used, the size is in gigabytes. So size 100, size 100k, size 100M and size 100G are all valid.
log_rotate_size:仅当日志文件大于log_rotate_size字节时才会轮换日志文件。如果大小后跟k,则假定大小以千字节为单位。如果使用M,则大小以兆字节为单位,如果使用G,则大小为千兆字节。尺寸100,尺寸100k,尺寸100M和尺寸100G都是有效的。

http_proxy: Config http proxy for Clair, e.g. http://my.proxy.com:3128.
http_proxy:为Clair配置http代理,例如http://my.proxy.com:3128。

https_proxy: Config https proxy for Clair, e.g. http://my.proxy.com:3128.
https_proxy:为Clair配置https代理,例如http://my.proxy.com:3128。

no_proxy: Config no proxy for Clair, e.g. 127.0.0.1,localhost,core,registry.
no_proxy:为Clair配置无代理,例如127.0.0.1,localhost,core,registry。

Optional parameters 可选参数

Email settings: These parameters are needed for Harbor to be able to send a user a “password reset” email, and are only necessary if that functionality is needed. Also, do note that by default SSL connectivity is not enabled - if your SMTP server requires SSL, but does not support STARTTLS, then you should enable SSL by setting email_ssl = true. Setting email_insecure = true if the email server uses a self-signed or untrusted certificate.
电子邮件设置:Harbor需要这些参数才能向用户发送“密码重置”电子邮件,并且仅在需要该功能时才需要。另外,请注意,在默认情况下SSL连接是禁用的,如果你的SMTP服务器需要SSL,但不支持STARTTLS,那么你应该通过设置启用SSL email_ssl = TRUE。如果电子邮件服务器使用自签名证书或不受信任证书,则设置email_insecure = true。

1
2
3
4
5
6
7
8
email_server = smtp.mydomain.com
email_server_port = 25
email_identity =
email_username = sample_admin@mydomain.com
email_password = abc
email_from = admin sample_admin@mydomain.com
email_ssl = false
email_insecure = false

harbor_admin_password: The administrator’s initial password. This password only takes effect for the first time Harbor launches. After that, this setting is ignored and the administrator’s password should be set in the Portal. Note that the default username/password are admin/Harbor12345 .
harbor_admin_password:管理员的初始密码。此密码仅在Harbor首次启动时生效。之后,将忽略此设置,并且应在Portal中设置管理员密码。请注意,默认用户名/密码为admin / Harbor12345。

auth_mode: The type of authentication that is used. By default, it is db_auth, i.e. the credentials are stored in a database. For LDAP authentication, set this to ldap_auth.
auth_mode:使用的身份验证类型。默认情况下,它是db_auth,即凭据存储在数据库中。对于LDAP身份验证,请将其设置为ldap_auth.
IMPORTANT: When upgrading from an existing Harbor instance, you must make sure auth_mode is the same in harbor.cfg before launching the new version of Harbor. Otherwise, users may not be able to log in after the upgrade.
重要信息:从现有Harbor实例升级时,必须确保在启动新版本的Harbor之前harbor.cfg中的auth_mode相同。否则,用户可能无法在升级后登录。

ldap_url: The LDAP endpoint URL (e.g. ldaps://ldap.mydomain.com). Only used when auth_mode is set to ldap_auth .
ldap_url:LDAP端点URL(例如ldaps://ldap.mydomain.com)。 仅在auth_mode设置为ldap_auth时使用。

ldap_searchdn: The DN of a user who has the permission to search an LDAP/AD server (e.g. uid=admin,ou=people,dc=mydomain,dc=com).
ldap_searchdn:具有搜索LDAP/AD服务器权限的用户的DN(例如uid=admin,ou=people,dc=mydomain,dc=com)。

ldap_search_pwd: The password of the user specified by ldap_searchdn.
ldap_search_pwd:ldap_searchdn指定的用户密码。

ldap_basedn: The base DN to look up a user, e.g. ou=people,dc=mydomain,dc=com. Only used when auth_mode is set to ldap_auth .
ldap_basedn:查找用户的基本DN,例如ou=people,dc=mydomain,dc=com。 仅在auth_mode设置为ldap_auth时使用。

ldap_filter: The search filter for looking up a user, e.g. (objectClass=person).
ldap_filter:用于查找用户的搜索过滤器,例如(objectClass=person)

ldap_uid: The attribute used to match a user during a LDAP search, it could be uid, cn, email or other attributes.
ldap_uid:用于在LDAP搜索期间匹配用户的属性,它可以是uid,cn,email或其他属性。

ldap_scope: The scope to search for a user, 0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE. Default is 2.
ldap_scope:搜索用户的范围,0-LDAP_SCOPE_BASE,1-LDAP_SCOPE_ONELEVEL,2-LDAP_SCOPE_SUBTREE。默认值为2。

ldap_timeout: Timeout (in seconds) when connecting to an LDAP Server. Default is 5.
ldap_timeout:连接LDAP服务器时超时(以秒为单位)。默认值为5。

ldap_verify_cert: Verify certificate from LDAP server. Default is true.
ldap_verify_cert:验证来自LDAP服务器的证书。默认为true。

ldap_group_basedn: The base dn from which to lookup a group in LDAP/AD, e.g. ou=group,dc=mydomain,dc=com.
ldap_group_basedn:在LDAP / AD中查找组的基本dn,例如ou=group,dc=mydomain,dc=com。

ldap_group_filter: The filter to search LDAP/AD group, e.g. objectclass=group.
ldap_group_filter:搜索LDAP / AD组的过滤器,例如objectclass=group。

ldap_group_gid: The attribute used to name a LDAP/AD group, it could be cn, name.
ldap_group_gid:用于命名LDAP / AD组的属性,它可以是cn,name。

ldap_group_scope: The scope to search for ldap groups. 0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE. Default is 2.
ldap_group_scope:搜索ldap组的范围。0-LDAP_SCOPE_BASE,1-LDAP_SCOPE_ONELEVEL,2-LDAP_SCOPE_SUBTREE。默认值为2。

self_registration: (on or off. Default is on) Enable / Disable the ability for a user to register himself/herself. When disabled, new users can only be created by the Admin user, only an admin user can create new users in Harbor. NOTE: When auth_mode is set to ldap_auth, self-registration feature is always disabled, and this flag is ignored.
self_registration :( 打开或关闭。默认打开)启用/禁用用户注册功能。禁用时,新用户只能由管理员用户创建,只有管理员用户可以在Harbor中创建新用户。注意:当auth_mode设置为ldap_auth时,始终禁用自注册功能,并忽略此标志。

token_expiration: The expiration time (in minutes) of a token created by token service, default is 30 minutes.
token_expiration:令牌服务创建的令牌的到期时间(以分钟为单位),默认为30分钟。

project_creation_restriction: The flag to control what users have permission to create projects. By default everyone can create a project, set to “adminonly” such that only admin can create project.
project_creation_restriction:用于控制用户有权创建项目的标志。默认情况下,每个人都可以创建一个项目;设置为“adminonly”,则只有管理员才能创建项目。

Configuring storage backend (optional) 配置存储后端(可选)

By default, Harbor stores images on your local filesystem. In a production environment, you may consider using other storage backend instead of the local filesystem, like S3, OpenStack Swift, Ceph, etc. These parameters are configurations for registry.
默认情况下,Harbor将镜像存储在本地文件系统中。在生产环境中,您可以考虑使用其他存储后端而不是本地文件系统,如S3,OpenStack Swift,Ceph等。这些参数是registry的配置。

registry_storage_provider_name: Storage provider name of registry, it can be filesystem, s3, gcs, azure, etc. Default is filesystem.
registry_storage_provider_name:存储仓库名称,可以是filesystem,s3,gcs,azure等。默认为filesystem。

registry_storage_provider_config: Comma separated “key: value” pairs for storage provider config, e.g. “key1: value, key2: value2”. Default is empty string.
registry_storage_provider_config:配置分隔键值对,例如“key1:value,key2:value2”。默认为空字符串。

registry_custom_ca_bundle: The path to the custom root ca certificate, which will be injected into the truststore of registry’s and chart repository’s containers. This is usually needed when the user hosts a internal storage with self signed certificate.
registry_custom_ca_bundle:当用户使用自签名证书托管内部存储时,通常需要自定义根ca证书的路径,它将注入到registry和image存储库容器的信任库中。
例如,如果使用Openstack Swift作为存储后端,则参数可能如下所示:

1
2
registry_storage_provider_name = swift
registry_storage_provider_config = “ username:admin,password:ADMIN_PASS,authurl:http:// kestone_addr:35357 / v3 / auth,tenant:admin,domain:default,region:regionOne,container:docker_images ”
  • 对于LADP以及证书不理解,需要加入到后续的学习计划。

harbor 企业级docker registry

Posted on 2019-01-12
Words count in article: 3.6k | Reading time ≈ 18

关于Harbor

Harbor is an an open source trusted cloud native registry project that stores, signs, and scans content. Harbor extends the open source Docker Distribution by adding the functionalities usually required by users such as security, identity and management. Having a registry closer to the build and run environment can improve the image transfer efficiency. Harbor supports replication of images between registries, and also offers advanced security features such as user management, access control and activity auditing.
Harbor是一个开源的可信云本机registry项目,用于存储,签名和扫描内容。Harbor通过添加用户通常需要的功能(如安全性,身份和管理)来扩展开源Docker Distribution。使注册表更接近构建和运行环境可以提高图像传输效率。Harbor支持在注册表之间复制映像,还提供高级安全功能,如用户管理,访问控制和活动审计。

Features 特性

Cloud native registry: With support for both container images and Helm charts, Harbor serves as registry for cloud native environments like container runtimes and orchestration platforms.

云本机registry:Harbour支持容器镜像和Helm图表,可用作云本机环境(如容器运行时和业务流程平台)的registry。

Role based access control: Users and repositories are organized via ‘projects’ and a user can have different permission for images under a project.

基于角色的访问控制:用户和存储库通过“项目”进行组织,用户可以对项目下的镜像拥有不同的权限。

Policy based image replication: Images can be replicated (synchronized) between multiple registry instances based on policies with multiple filters (repository, tag and label). Harbor will auto-retry to replicate if it encounters any errors. Great for load balancing, high availability, multi-datacenter, hybrid and multi-cloud scenarios.

基于策略的镜像复制:可以基于具有多个过滤器(存储库,标记和标签)的策略在多个registry实例之间复制(同步)镜像。如果遇到任何错误,Harbor将自动重试进行复制。非常适合负载平衡,高可用性,多数据中心,混合和多云场景。

Vulnerability Scanning: Harbor scans images regularly and warns users of vulnerabilities.

漏洞扫描:Harbor定期扫描镜像并警告用户漏洞。

LDAP/AD support: Harbor integrates with existing enterprise LDAP/AD for user authentication and management, and supports importing LDAP groups into Harbor and assigning proper project roles to them.

LDAP / AD支持:Harbor与现有企业LDAP / AD集成以进行用户身份验证和管理,并支持将LDAP组导入Harbor并为其分配适当的项目角色。

Image deletion & garbage collection: Images can be deleted and their space can be recycled.

图像删除和垃圾收集:可以删除镜像,并可以回收它们的空间。

Notary: Image authenticity can be ensured.

公证:可以确保镜像的真实性。

Graphical user portal: User can easily browse, search repositories and manage projects.

用户图形界面:用户可以轻松浏览,搜索存储库和管理项目。

Auditing: All the operations to the repositories are tracked.

审计:跟踪存储库的所有操作。

RESTful API: RESTful APIs for most administrative operations, easy to integrate with external systems.

RESTful API:适用于大多数管理操作的RESTful API,易于与外部系统集成。

Easy deployment: Provide both an online and offline installer.

易于部署:提供在线和离线安装程序。

企业级Registry项目Harbor是由Vmware公司开发的开源项目,其的目标是帮助用户迅速搭建一个企业级的Docker registry 服务。它以Docker公司开源的registry 为基础,提供了管理UI, 基于角色的访问控制(Role Based Access Control),AD/LDAP集成、以及审计日志(Audit logging) 等企业用户需求的功能,同时还原生支持中文。

Harbor的每个组件都是以Docker 容器的形式构建的,因此很自然地,我们使用Docker Compose来对它进行部署。在源代码中(https://github.com/vmware/harbor), 用于部署Harbor的Docker Compose 模板位于 /Deployer/docker-compose.yml. 打开这个模板文件,会发现Harbor由5个容器组成:

  • proxy: 由Nginx 服务器构成的反向代理。
  • registry:由Docker官方的开源registry 镜像构成的容器实例。
  • ui: 即架构中的core services, 构成此容器的代码是Harbor项目的主体。
  • mysql: 由官方MySql镜像构成的数据库容器。
  • log: 运行着rsyslogd的容器,通过log-driver的形式收集其他容器的日志。

这几个容器通过Docker link的形式连接在一起,这样,在容器之间可以通过容器名字互相访问。对终端用户而言,只需要暴露proxy (即Nginx)的服务端口。(摘自 http://dockone.io/article/1179)

安装及配置

(参考 https://github.com/goharbor/harbor/blob/master/docs/installation_guide.md

下载harbor软件包:https://storage.googleapis.com/harbor-releases/release-1.7.0/harbor-offline-installer-v1.7.1.tgz
harbor软件包较大,建议科学上网

解压后如下

1
2
3
[root@Web2 harbor]# ls
common docker-compose.clair.yml docker-compose.yml harbor.v1.7.1.tar.gz LICENSE prepare
docker-compose.chartmuseum.yml docker-compose.notary.yml harbor.cfg install.sh open_source_license
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@Web2 ~]# yum info docker-compose
已加载插件:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.neusoft.edu.cn
* epel: mirrors.tuna.tsinghua.edu.cn
* extras: mirrors.nwsuaf.edu.cn
* updates: mirrors.tuna.tsinghua.edu.cn
已安装的软件包
名称 :docker-compose
架构 :noarch
版本 :1.18.0
发布 :2.el7
大小 :1.1 M
源 :installed
来自源:epel
简介 : Multi-container orchestration for Docker
网址 :https://github.com/docker/compose
协议 : ASL 2.0
描述 : Compose is a tool for defining and running multi-container Docker
: applications. With Compose, you use a Compose file to configure your
: application's services. Then, using a single command, you create and
: start all the services from your configuration.
:
: Compose is great for development, testing, and staging environments,
: as well as CI workflows.
:
: Using Compose is basically a three-step process.
:
: 1. Define your app's environment with a Dockerfile so it can be
: reproduced anywhere.
: 2. Define the services that make up your app in docker-compose.yml so
: they can be run together in an isolated environment:
: 3. Lastly, run docker-compose up and Compose will start and run your
: entire app.

还需要docker-compose 编排工具,该工具在epel源中提供,所以需要先配置epel源;然后再安装即可

1
2
3
yum install epel-release
yum repolist
yum install docker-compose

python和openssl

1
2
3
4
5
6
7
[root@Web2 ~]# openssl
OpenSSL> version
OpenSSL 1.0.2k-fips 26 Jan 2017
OpenSSL> exit
[root@Web2 ~]# python --version
Python 2.7.5
[root@Web2 ~]#

修改harbor配置文件

1
2
3
[root@Web2 ~]# vim /usr/local/harbor/harbor.cfg 
hostname = 172.18.74.101 //IP地址或域名
max_job_workers = 3 //CPU数减一

Harbor has integrated with Notary and Clair (for vulnerability scanning). However, the default installation does not include Notary or Clair service.
Harbor已与Notary和Clair集成(用于漏洞扫描)。但是,默认安装不包括Notary或Clair服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
执行脚本安装harbor
[root@Web2 harbor]# ./install.sh

[Step 0]: checking installation environment ...

Note: docker version: 18.09.0

Note: docker-compose version: 1.18.0

[Step 1]: loading Harbor images ...
ae18db924eef: Loading layer [==================================================>] 32.92MB/32.92MB
1c06074dba9c: Loading layer [==================================================>] 8.955MB/8.955MB
7a719a639e34: Loading layer [==================================================>] 3.072kB/3.072kB
49f7bca05da9: Loading layer [==================================================>] 2.56kB/2.56kB
e86d69bef97e: Loading layer [==================================================>] 2.56kB/2.56kB
81e122d773f5: Loading layer [==================================================>] 2.048kB/2.048kB
5fe5adb8cf31: Loading layer [==================================================>] 22.8MB/22.8MB
d760045419e4: Loading layer [==================================================>] 22.8MB/22.8MB
Loaded image: goharbor/registry-photon:v2.6.2-v1.7.1
c0f668a21621: Loading layer [==================================================>] 133.2MB/133.2MB
f8cb0bf39ff2: Loading layer [==================================================>] 684MB/684MB
444ac38a117b: Loading layer [==================================================>] 7.68kB/7.68kB
2e16f24ac8bc: Loading layer [==================================================>] 212kB/212kB
Loaded image: goharbor/harbor-migrator:v1.7.1
fa2dcaba747a: Loading layer [==================================================>] 8.955MB/8.955MB
eeaaf4c760eb: Loading layer [==================================================>] 15.6MB/15.6MB
98ffd6175b61: Loading layer [==================================================>] 18.94kB/18.94kB
fc1db6c4f652: Loading layer [==================================================>] 15.6MB/15.6MB
Loaded image: goharbor/harbor-adminserver:v1.7.1
8d55a6a034d6: Loading layer [==================================================>] 8.955MB/8.955MB
01ef68a17913: Loading layer [==================================================>] 27.24MB/27.24MB
f9258cfa4b48: Loading layer [==================================================>] 5.632kB/5.632kB
dcf5c61ede76: Loading layer [==================================================>] 27.24MB/27.24MB
Loaded image: goharbor/harbor-core:v1.7.1
1f65d10893c9: Loading layer [==================================================>] 50.39MB/50.39MB
358f40be2091: Loading layer [==================================================>] 3.584kB/3.584kB
c7f3ef058d0b: Loading layer [==================================================>] 3.072kB/3.072kB
154caf7c7173: Loading layer [==================================================>] 4.096kB/4.096kB
42c7764aa777: Loading layer [==================================================>] 3.584kB/3.584kB
023f3a96f324: Loading layer [==================================================>] 10.24kB/10.24kB
Loaded image: goharbor/harbor-log:v1.7.1
a1b528067504: Loading layer [==================================================>] 8.955MB/8.955MB
2d3d34f3ba5b: Loading layer [==================================================>] 21.51MB/21.51MB
a5da70777097: Loading layer [==================================================>] 21.51MB/21.51MB
Loaded image: goharbor/harbor-jobservice:v1.7.1
ab31dfc84e9d: Loading layer [==================================================>] 8.954MB/8.954MB
b130423af762: Loading layer [==================================================>] 13.43MB/13.43MB
357c059d0598: Loading layer [==================================================>] 17.3MB/17.3MB
fabc6edfac55: Loading layer [==================================================>] 11.26kB/11.26kB
cfaa3b5d445a: Loading layer [==================================================>] 3.072kB/3.072kB
12c73a4b2c7a: Loading layer [==================================================>] 30.72MB/30.72MB
Loaded image: goharbor/notary-server-photon:v0.6.1-v1.7.1
50a6467bd619: Loading layer [==================================================>] 113MB/113MB
6ae61fc91943: Loading layer [==================================================>] 11.46MB/11.46MB
5c840c272f78: Loading layer [==================================================>] 2.048kB/2.048kB
077d16ebcba8: Loading layer [==================================================>] 48.13kB/48.13kB
b822f5ff7858: Loading layer [==================================================>] 3.072kB/3.072kB
4548140152fd: Loading layer [==================================================>] 11.51MB/11.51MB
Loaded image: goharbor/clair-photon:v2.0.7-v1.7.1
232024be30e3: Loading layer [==================================================>] 3.39MB/3.39MB
a73624ae3fad: Loading layer [==================================================>] 4.721MB/4.721MB
96b8c5c532c3: Loading layer [==================================================>] 3.584kB/3.584kB
Loaded image: goharbor/harbor-portal:v1.7.1
e2fd12afe6e8: Loading layer [==================================================>] 63.31MB/63.31MB
e973513bcb58: Loading layer [==================================================>] 40.74MB/40.74MB
4f45af643b2b: Loading layer [==================================================>] 6.656kB/6.656kB
54a84094f024: Loading layer [==================================================>] 2.048kB/2.048kB
2d78cf8a687b: Loading layer [==================================================>] 7.68kB/7.68kB
e96067b83a72: Loading layer [==================================================>] 2.56kB/2.56kB
38a7d304147f: Loading layer [==================================================>] 2.56kB/2.56kB
a36c0cb6a35a: Loading layer [==================================================>] 2.56kB/2.56kB
Loaded image: goharbor/harbor-db:v1.7.1
b0c31ad64c85: Loading layer [==================================================>] 65.01MB/65.01MB
22fbab41769e: Loading layer [==================================================>] 3.072kB/3.072kB
7f28bf5373b2: Loading layer [==================================================>] 59.9kB/59.9kB
abb9969cff2a: Loading layer [==================================================>] 61.95kB/61.95kB
Loaded image: goharbor/redis-photon:v1.7.1
933cd9a15fc5: Loading layer [==================================================>] 3.39MB/3.39MB
Loaded image: goharbor/nginx-photon:v1.7.1
6ee16a137af2: Loading layer [==================================================>] 8.955MB/8.955MB
954443cb7d20: Loading layer [==================================================>] 22.8MB/22.8MB
302a998137db: Loading layer [==================================================>] 3.072kB/3.072kB
e342723aef9b: Loading layer [==================================================>] 7.465MB/7.465MB
4eeb61ed730b: Loading layer [==================================================>] 30.26MB/30.26MB
Loaded image: goharbor/harbor-registryctl:v1.7.1
5b40d957fafd: Loading layer [==================================================>] 12.11MB/12.11MB
63489681dd6c: Loading layer [==================================================>] 17.3MB/17.3MB
696209dcd336: Loading layer [==================================================>] 11.26kB/11.26kB
8dc53997aa1f: Loading layer [==================================================>] 3.072kB/3.072kB
cb6d560a9958: Loading layer [==================================================>] 29.41MB/29.41MB
Loaded image: goharbor/notary-signer-photon:v0.6.1-v1.7.1
dc1e16790c89: Loading layer [==================================================>] 8.96MB/8.96MB
046c7e7a0100: Loading layer [==================================================>] 35.08MB/35.08MB
8c8428e3d6c6: Loading layer [==================================================>] 2.048kB/2.048kB
ebb477ee35a2: Loading layer [==================================================>] 3.072kB/3.072kB
19636f39e29d: Loading layer [==================================================>] 35.08MB/35.08MB
Loaded image: goharbor/chartmuseum-photon:v0.7.1-v1.7.1


[Step 2]: preparing environment ...
Generated and saved secret to file: /data/secretkey
Generated configuration file: ./common/config/nginx/nginx.conf
Generated configuration file: ./common/config/adminserver/env
Generated configuration file: ./common/config/core/env
Generated configuration file: ./common/config/registry/config.yml
Generated configuration file: ./common/config/db/env
Generated configuration file: ./common/config/jobservice/env
Generated configuration file: ./common/config/jobservice/config.yml
Generated configuration file: ./common/config/log/logrotate.conf
Generated configuration file: ./common/config/registryctl/env
Generated configuration file: ./common/config/core/app.conf
Creating harbor-log ... done
The configuration files are ready, please use docker-compose to start the service.


[Step 3]: checking existing instance of Harbor ...
Creating registry ... done
Creating harbor-core ... done
[Step 4]: starting Harbor ...
Creating harbor-portal ... done
Creating nginx ... done
Creating harbor-adminserver ...
Creating harbor-db ...
Creating redis ...
Creating registry ...
Creating registryctl ...
Creating harbor-core ...
Creating harbor-jobservice ...
Creating harbor-portal ...
Creating nginx ...

✔ ----Harbor has been installed and started successfully.----

Now you should be able to visit the admin portal at http://172.18.74.101.
For more details, please visit https://github.com/goharbor/harbor .

在安装 脚本执行过程过程中看到下拉了很多镜像,Harbor的每个组件都是以Docker 容器的形式构建的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@Web2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
goharbor/chartmuseum-photon v0.7.1-v1.7.1 f61c186d5b1b 6 days ago 111MB
goharbor/harbor-migrator v1.7.1 9ec6467899b6 6 days ago 799MB
goharbor/redis-photon v1.7.1 c7aa92fb1c26 6 days ago 96.3MB
goharbor/clair-photon v2.0.7-v1.7.1 832461eef7dd 6 days ago 165MB
goharbor/notary-server-photon v0.6.1-v1.7.1 382cd390eaff 6 days ago 102MB
goharbor/notary-signer-photon v0.6.1-v1.7.1 76486e1aa1a2 6 days ago 99.6MB
goharbor/harbor-registryctl v1.7.1 aefea98e6f92 6 days ago 101MB
goharbor/registry-photon v2.6.2-v1.7.1 13b348ffd0c9 6 days ago 86.4MB
goharbor/nginx-photon v1.7.1 9b9520572494 6 days ago 35.5MB
goharbor/harbor-log v1.7.1 0744800d7a4c 6 days ago 81MB
goharbor/harbor-jobservice v1.7.1 db96ce6ed531 6 days ago 83.8MB
goharbor/harbor-core v1.7.1 8f253c0f9d50 6 days ago 95.2MB
goharbor/harbor-portal v1.7.1 b50162ab177a 6 days ago 40.2MB
goharbor/harbor-adminserver v1.7.1 22d66cccedba 6 days ago 72MB
goharbor/harbor-db v1.7.1 c2a95254c0bf 6 days ago 133MB
[root@Web2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f007d1aae3fa goharbor/nginx-photon:v1.7.1 "nginx -g 'daemon of…" About a minute ago Up About a minute (healthy) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp nginx
bf48e808d152 goharbor/harbor-portal:v1.7.1 "nginx -g 'daemon of…" About a minute ago Up About a minute (healthy) 80/tcp harbor-portal
0d78ea5ff51f goharbor/harbor-jobservice:v1.7.1 "/harbor/start.sh" About a minute ago Up About a minute harbor-jobservice
c07ca8d7cf72 goharbor/harbor-core:v1.7.1 "/harbor/start.sh" About a minute ago Up About a minute (healthy) harbor-core
d6ce992225e9 goharbor/harbor-adminserver:v1.7.1 "/harbor/start.sh" About a minute ago Up About a minute (healthy) harbor-adminserver
86200773e6fc goharbor/harbor-registryctl:v1.7.1 "/harbor/start.sh" About a minute ago Up About a minute (healthy) registryctl
a496f40a1d95 goharbor/harbor-db:v1.7.1 "/entrypoint.sh post…" About a minute ago Up About a minute (healthy) 5432/tcp harbor-db
becbead56360 goharbor/redis-photon:v1.7.1 "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp redis
b66044203146 goharbor/registry-photon:v2.6.2-v1.7.1 "/entrypoint.sh /etc…" About a minute ago Up About a minute (healthy) 5000/tcp registry
d6f266aa5a49 goharbor/harbor-log:v1.7.1 "/bin/sh -c /usr/loc…" About a minute ago Up About a minute (healthy) 127.0.0.1:1514->10514/tcp harbor-log

以admin/Harbor12345 默认登录名密码进行登录

将镜像推送至registry

Harbor的默认安装使用HTTP协议,需要将 –insecure-registry 参数添加进客户端的daemon.json 。

1
2
3
4
5
root@ubuntu16:~# vim /etc/docker/daemon.json
{
"insecure-registries":["172.18.74.101"]
}
root@ubuntu16:~# systemctl restart docker

然后以admin身份登录

1
2
3
4
root@ubuntu16:~# docker login 172.18.74.101
Username: admin
Password:
Login Succeeded

对镜像进行打标 ,使用docker tag 命令

1
2
3
4
5
root@ubuntu16:~# docker tag alpine 172.18.74.101/library/alpine:latest
root@ubuntu16:~# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 196d12cf6ab1 4 months ago 4.41MB
172.18.74.101/library/alpine latest 196d12cf6ab1 4 months ago 4.41MB

推送镜像

1
2
3
4
root@ubuntu16:~# docker push 172.18.74.101/library/alpine
The push refers to a repository [172.18.74.101/library/alpine]
df64d3292fd6: Pushed
latest: digest: sha256:76ebd8b93b384fe8121d87be22c2089843f663fb342f1e6345a0a0bd6424c5c2 size: 528

推送后在Harbor中即可看到alpine镜像

Harbor管理

使用docker-compose命令可以用来管理Harbor,但是必须与docker-compose.yml在同一目录中运行,否则报错如下。

1
2
3
4
5
ERROR: 
Can't find a suitable configuration file in this directory or any
parent. Are you in the right directory?

Supported filenames: docker-compose.yml, docker-compose.yaml

使用 docker-compose stop 来关闭Harbor和docker-compose start 关闭后进行重启。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@Web2 harbor]# docker-compose stop
Stopping nginx ... done
Stopping harbor-portal ... done
Stopping harbor-jobservice ... done
Stopping harbor-core ... done
Stopping harbor-adminserver ... done
Stopping registryctl ... done
Stopping harbor-db ... done
Stopping redis ... done
Stopping registry ... done
Stopping harbor-log ... done
[root@Web2 harbor]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@Web2 harbor]# docker-compose start
Starting log ... done
Starting redis ... done
Starting adminserver ... done
Starting registryctl ... done
Starting registry ... done
Starting core ... done
Starting portal ... done
Starting jobservice ... done
Starting postgresql ... done
Starting proxy ... done

要更改Harbour的配置,要停止现有的Harbor实例并更新 harbor.cfg。然后运行 prepare 脚本以填充配置。最后重新创建并启动Harbor

1
2
3
4
sudo docker-compose down -v
vim harbor.cfg
sudo prepare
sudo docker-compose up -d

默认情况下,注册表数据保留在主机的/data/目录中。即使Harbor的容器被移除和/或重新创建,此数据仍保持不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[root@Web2 data]# ls
ca_download config database job_logs psc redis registry secretkey
[root@Web2 data]# cd registry/
[root@Web2 registry]# tree
.
└── docker
└── registry
└── v2
├── blobs
│ └── sha256
│ ├── 19
│ │ └── 196d12cf6ab19273823e700516e98eb1910b03b17840f9d5509f03858484d321
│ │ └── data
│ ├── 76
│ │ └── 76ebd8b93b384fe8121d87be22c2089843f663fb342f1e6345a0a0bd6424c5c2
│ │ └── data
│ └── c4
│ └── c432c1aab6335df5a9ff6237f8d19627f95ea7dc3f5709c555b2a28cd8df4d0a
│ └── data
└── repositories
└── library
└── alpine
├── _layers
│ └── sha256
│ ├── 196d12cf6ab19273823e700516e98eb1910b03b17840f9d5509f03858484d321
│ │ └── link
│ └── c432c1aab6335df5a9ff6237f8d19627f95ea7dc3f5709c555b2a28cd8df4d0a
│ └── link
├── _manifests
│ ├── revisions
│ │ └── sha256
│ │ └── 76ebd8b93b384fe8121d87be22c2089843f663fb342f1e6345a0a0bd6424c5c2
│ │ └── link
│ └── tags
│ └── latest
│ ├── current
│ │ └── link
│ └── index
│ └── sha256
│ └── 76ebd8b93b384fe8121d87be22c2089843f663fb342f1e6345a0a0bd6424c5c2
│ └── link
└── _uploads

29 directories, 8 files

此外,Harbor使用 rsyslog 来收集每个容器的日志。默认情况下,这些日志文件存储在/var/log/harbor/目标主机上的目录中以进行故障排除。

1
2
3
[root@Web2 registry]# cd /var/log/harbor/
[root@Web2 harbor]# ls
adminserver.log core.log jobservice.log portal.log postgresql.log proxy.log redis.log registryctl.log registry.log

删除Harbor的容器,同时将图像数据和Harbor的数据库文件保存在文件系统上:

1
sudo docker-compose down -v

删除Harbor的数据库和图像数据(用于重新安装):

1
2
rm -r / data / database 
rm -r / data / registry

自定义配置Harbor监听端口

1.修改docker-compose.yml

将默认的80:80 修改为8888:80,访问主机8888端口nginx容器就可以代理至harbor-portal容器的80端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
proxy:
image: goharbor/nginx-photon:v1.6.0
container_name: nginx
restart: always
volumes:
- ./common/config/nginx:/etc/nginx:z
ports:
- 8888:80 //将默认的80:80 修改为8888:80
- 443:443
depends_on:
- postgresql
- registry
- core
- portal
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://127.0.0.1:1514"
tag: "proxy"

2. 修改harbor.cfg

1
hostname = 172.18.74.101:8888

3.重新部署Harbor

见上文

123
戴树谦

戴树谦

29 posts
10 tags
GitHub E-Mail
© 2019 戴树谦
Theme — NexT.Mist v5.1.4
0%