hopeless-dream

导航

SQL基础-DML

insert语句

mysql> insert into students(sid,sname,scardid,saddr,hobby,salary,sdate) values(1000,'lisi','110102','北京市','足 球,羽毛球',10001.00,now());

mysql> create table t1(id int,name varchar(10));
Query OK, 0 rows affected (0.02 sec)

mysql> alter table t1 add primary key (id);
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert into t1 values(1,'tom');
Query OK, 1 row affected (0.01 sec)

使语句可重复执行 insert ignore

mysql> insert into t1 values(1,'jerry');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

mysql> insert ignore into t1 values(1,'jerry');
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+---------------------------------------+
| Level   | Code | Message                               |
+---------+------+---------------------------------------+
| Warning | 1062 | Duplicate entry '1' for key 'PRIMARY' |
+---------+------+---------------------------------------+
1 row in set (0.00 sec)

插入多条数据语句

mysql> insert ignore into t1 values(2,'jerry'),(3,'jack');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

其他插入语句实例

mysql> insert into t1 set id=4,name='lucy';
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 select * from t2;

使用replace替换数据

## 注意,在没有约束的时候,会新插入数据

mysql> replace into t1 values(4,'lily');        
Query OK, 2 rows affected (0.00 sec) 

mysql> select * from t1;
+----+-------+
| id | name  |
+----+-------+
|  1 | tom   |
|  2 | jerry |
|  3 | jack  |
|  4 | lily  |
+----+-------+
4 rows in set (0.00 sec) 

mysql> create table t2 as select * from t1;
Query OK, 4 rows affected (0.03 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from t2;
+----+-------+
| id | name  |
+----+-------+
|  1 | tom   |
|  2 | jerry |
|  3 | jack  |
|  4 | lily  |
+----+-------+
4 rows in set (0.01 sec)

mysql> replace into t2 values(4,'lucy');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t2;
+----+-------+
| id | name  |
+----+-------+
|  1 | tom   |
|  2 | jerry |
|  3 | jack  |
|  4 | lily  |
|  4 | lucy  |
+----+-------+
5 rows in set (0.00 sec)

mysql> alter table t1 add unique key unq_name(name);
Query OK, 0 rows affected (0.16 sec)
Records: 0  Duplicates: 0  Warnings: 0

update

update TABLE_NAME SET xxx=xxx where

注意点: 更新列的个数,where条件最好带索引列,更新索引列的值时,有可能会出现页分片,尽量在业务不繁忙的时候更新索引列。

当有索引的时候update是顺序修改,在做批量修改的时候可以使用order by

mysql> select * from t1;
+----+-------+
| id | name  |
+----+-------+
|  3 | jack  |
|  2 | jerry |
|  4 | lily  |
|  1 | tom   |
+----+-------+
4 rows in set (0.00 sec)
 
mysql> update t1 set id=id+1;
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY' 

mysql> update t1 set id=id+1 order by id desc;
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0

mysql> select * from t1;
+----+-------+
| id | name  |
+----+-------+
|  4 | jack  |
|  3 | jerry |
|  5 | lily  |
|  2 | tom   |
+----+-------+
4 rows in set (0.00 sec)

limit 限制改多少行

mysql> alter table t1 add age int unsigned;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> update t1 set age=20 where id>2 limit 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from t1;
+----+-------+------+
| id | name  | age  |
+----+-------+------+
|  2 | tom   | NULL |
|  3 | jerry |   20 |
|  4 | jack  |   10 |
|  5 | lily  |   10 |
+----+-------+------+
4 rows in set (0.00 sec)

delete

delete from t2 where id=4;

注意点: where 条件,索引

伪删除(在表中添加状态列state,update时加条件)

mysql> alter table t2 add column state int not null default 1;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
| state | int(11)     | NO   |     | 1       |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec) 

mysql> select * from t2;
+----+-------+-------+
| id | name  | state |
+----+-------+-------+
|  1 | tom   |     1 |
|  2 | jerry |     1 |
|  3 | jack  |     1 |
|  4 | lily  |     1 |
|  4 | lucy  |     1 |
+----+-------+-------+
5 rows in set (0.00 sec) 

mysql> update t2 set state=0 where id >=4;
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2  Changed: 2  Warnings: 0 

mysql> select * from t2 where state =1;
+----+-------+-------+
| id | name  | state |
+----+-------+-------+
|  1 | tom   |     1 |
|  2 | jerry |     1 |
|  3 | jack  |     1 |
+----+-------+-------+
3 rows in set (0.00 sec)

select

select 查询参数(变量)值

mysql> select @@innodb_flush_log_at_trx_commit;
+----------------------------------+
| @@innodb_flush_log_at_trx_commit |
+----------------------------------+
|                                1 |
+----------------------------------+
1 row in set (0.00 sec) 

mysql> select @@datadir;
+------------------------+
| @@datadir              |
+------------------------+
| /data/mysql/data_3306/ |
+------------------------+
1 row in set (0.00 sec) 

mysql> show variables like '%trx%'\G
*************************** 1. row ***************************
Variable_name: innodb_api_trx_level
        Value: 0
*************************** 2. row ***************************
Variable_name: innodb_flush_log_at_trx_commit
        Value: 1
2 rows in set (0.00 sec)

select查询函数

mysql> select pi()*2*5 from dual;
+-----------+
| pi()*2*5  |
+-----------+
| 31.415927 |
+-----------+
1 row in set (0.00 sec)

mysql> select current_user();
+----------------+
| current_user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

select标准使用

单表查询

1、 多子句的执行顺序

select

from 从哪来

where 过滤条件

group by 分组条件

select_list 列条件

having 后过滤条件

order by 排序条件

limit 分页

 from子句应用

1. 获取世界上所有城市信息

SELECT * FROM city;

===>

SELECT id,NAME,coutrycode,District ,population FROM city;

select应用举例

1、获取世界上所有城市名和人口数

SELECT NAME,population FROM city;

 2、where 子句应用

 2.1 等值查询

2.1.1 查询中国(CHN)所有的城市

SELECT * FROM city WHERE countrycode='CHN';

2.1.2 查询中国或美国的所有城市信息

SELECT * FROM city WHERE countrycode='CHN' OR countrycode='USA' ;

SELECT * FROM city WHERE countrycode IN ('CHN','USA');

SELECT * FROM city WHERE countrycode='CHN'

UNION ALL

SELECT * FROM city WHERE countrycode='USA' ;

SELECT countrycode,CASE countrycode WHEN countrycode = 'CHN' THEN NAME END FROM city;

2.1.3 UNION和UNION ALL 差别,union 是要去重复的。

说明: union all 语句在索引合理的时候,比in性能好一些

如果说,在索引不合理的时候,需要多次查同一表时,性能肯能不如in

 

例如:以下语句,最好改写为case语句

SELECT SUM(invalid_count) as invalid_count,

SUM(confirm_count) as

confirm_count,SUM(not_confirm_count) as

not_confirm_count,SUM(total_count) as total_count

FROM (

select count(att.LogID) as invalid_count, 0

as confirm_count,0 as not_confirm_count,0 as

total_count,bp.city_id

FROM builder_project_info as bp

JOIN attendentlog as att ON bp.project_id =

att.CompanyID

WHERE att.CompanyID in (SELECT project_id from builder_project_info WHERE city_id = 407) and att.LogTime like "2019-06%" and att.state = 2

GROUP BY bp.city_id

UNION all (

select 0 as invalid_count, count(att.LogID)

as confirm_count,0 as not_confirm_count,0 as

total_count,bp.city_id

FROM builder_project_info as bp

JOIN attendentlog as att ON bp.project_id =

att.CompanyID

WHERE att.CompanyID in (SELECT project_id from

builder_project_info WHERE city_id = 407) and

att.LogTime like "2019-06%" and att.state = 1

GROUP BY bp.city_id

)

UNION all (

select 0 as invalid_count, 0 as

confirm_count,count(att.LogID) as not_confirm_count,0

as total_count,bp.city_id

FROM builder_project_info as bp

JOIN attendentlog as att ON bp.project_id =

att.CompanyID

WHERE att.CompanyID in (SELECT project_id from

builder_project_info WHERE city_id = 407) and

att.LogTime like "2019-06%" and att.state = 0

GROUP BY bp.city_id

)

UNION all (

select 0 as invalid_count, 0 as confirm_count,0 as

not_confirm_count,count(att.LogID) as

total_count,bp.city_id

FROM builder_project_info as bp

JOIN attendentlog as att ON bp.project_id =

att.CompanyID

WHERE att.CompanyID in (SELECT project_id from

builder_project_info WHERE city_id = 407) and

att.LogTime like "2019-06%"

GROUP BY bp.city_id

)

) as a

GROUP BY a.city_id

改写后:

SELECT

COUNT(CASE WHEN att.state=0 THEN 1 END) AS a,

COUNT(CASE WHEN att.state=1 THEN 1 END) AS b,

COUNT(CASE WHEN att.state=2 THEN 1 END) AS c,

sum(att.LogID)

FROM builder_project_info AS bp

JOIN attendentlog AS att ON bp.project_id =

att.CompanyID

WHERE bp.city_id=407

AND att.LogTime LIKE "2019-06%"

AND att.state IN (0,1,2)

GROUP BY bp.city_id;

2.1.3  WHERE + LIKE 使用(字符串列)

--- 查询一下国家的code是CH开头的。

SELECT * FROM city WHERE countrycode LIKE 'CH%';

注意不要出现 LIKE '%CH%',不走索引。

 4. where 不等值查询 (> < >= <=,!= <>,not in)

不等于!=、<>、not in查询不走索引,除非是主键列

例如:

mysql> desc select CountryCode,name from city where id>100;

+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |

+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

|  1 | SIMPLE      | city  | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL | 2094 |   100.00 | Using where |

+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00 sec)

 

SELECT * FROM city WHERE population<100;

SELECT * FROM city WHERE countrycode != 'CHN' ;

SELECT * FROM city WHERE countrycode NOT IN

('CHN','USA');

SELECT * FROM city WHERE Population>=1000000 AND

Population<=2000000;

SELECT * FROM city WHERE Population BETWEEN 1000000 AND

2000000;

 

-- group by + 聚合函数

(sum(),avg(),count(),max(),min(),group_concat())

-- 1. 统计city表中,每个国家的城市个数

SELECT countrycode,COUNT(id) FROM city GROUP BY countrycode;

-- 2. 统计一下每个国家的总人口

SELECT countrycode ,SUM(population)

FROM city

GROUP BY countrycode;

-- 3. 统计一下中国每个省的总人口

SELECT district ,SUM(population)

FROM city

WHERE countrycode='CHN'

GROUP BY district;

-- 4. 统计每个国家的城市个数和城市名

SELECT countrycode,COUNT(id),GROUP_CONCAT(NAME) FROM

city

GROUP BY countrycode;

执行逻辑:

1. 按照group by条件进行排序

2. 去重复

3. 聚合列

 

sql_mode问题:

mysql> SELECT countrycode,id FROM city

-> GROUP BY countrycode;

ERROR 1055 (42000): Expression #2 of SELECT list is not

in GROUP BY clause and contains nonaggregated column

'world.city.ID' which is not functionally dependent on

columns in GROUP BY clause; this is incompatible with

sql_mode=only_full_group_by

 

-- 5.分组聚合group_concat(column_name):将返回的column值按一行显示,避免1对多

 

-- having 后判断(不走索引)

-- 1. 统计一下中国每个省的总人口,将总人口超过500w的显示出来

SELECT district ,SUM(population)

FROM city

WHERE countrycode='CHN'

GROUP BY district

HAVING SUM(population) >5000000;

 

--- order by 子句应用(不走索引)

-- 统计一下中国每个省的总人口,将总人口超过500w的显示出来,总人口

从大到小排序

SELECT district ,SUM(population)

FROM city

WHERE countrycode='CHN'

GROUP BY district

HAVING SUM(population) >5000000

ORDER BY SUM(population) DESC ;

-- 查询中国所有城市人口数,按从大到小排序

SELECT NAME ,population FROM city

WHERE countrycode='CHN'

ORDER BY population DESC;

 

8.0 新姿势: 倒序索引

select * from t1 order by a asc , b desc;

idx_a_b(a,b) ===== > idx(a asc,b desc)

 

--- limit 子句使用

SELECT district ,SUM(population)

FROM city

WHERE countrycode='CHN'

GROUP BY district

HAVING SUM(population) >5000000

ORDER BY SUM(population) DESC

LIMIT 5 OFFSET 1;

 

SELECT district ,SUM(population)

FROM city

WHERE countrycode='CHN'

GROUP BY district

HAVING SUM(population) >5000000

ORDER BY SUM(population) DESC

LIMIT 1,5;

count(*)和count(1)的区别:

count(*)用到局和索引 count(1)全表扫描

 

多表查询

departments # 部门表

dept_no(部门编号),

dept_name(部门名称)

dept_emp #部门-员工关系表

emp_no(员工编号),

dept_no(部门编号),

from_date,to_date

dept_manager #部门-经理关系表

from_date(任职起始)

to_date(任职结束),

dept_no(部门编号),

emp_no(员工编号)

employees #员工表

emp_no(员工编号),

birth_date(生日),

first_name(名),

last_name(姓),

gender(性别),

hire_date(离职日期)

salaries #薪水表

emp_no(员工编号),

salary(年薪),

from_date(起始日期),

to_date(结束日期)

titles #职称表

emp_no(员工编号),

title(职称),

from_date(起始时间),

to_date(结束时间)

 

-- 说明: 别名应用

表别名: 在任意子句中调用表名时,都可以使用别名替代

列别名: 在having和order by子句中可以调用

 

-- 多表连接工作逻辑

1. 优化器,在内连接中,选择驱动表

(1) 多张表时,从左到右,查看表中索引情况,有索引选为驱动表

(2) 如果第一张没有,直到找到第一只张表有索引的表作为驱动表

(3) 如果都没有,则选择行数少的表

 

2. 多表连接算法

SNLJ

BNLJ

BKAJ

3. 优化重点

强制“小表”为驱动表(left join会强制使用左表为驱动表,right join 同理)

建立合适的索引

开启优化算法

set global

optimizer_switch='batched_key_access=ON,mrr_cost_based=

off';

4. letf join 优化not in 语句

 

 

 

 

posted on 2021-04-22 17:40  hopeless-dream  阅读(68)  评论(0编辑  收藏  举报