MySQL的基本使用

数据库的介绍

数据库管理系统:
Mysql,oracle,sqlite,access,sql,server等
数据库服务器:
数据库管理系统运行的机器,就是数据库服务器.
数据库分为两种,
有关系型和非关系型
Redis
Celery

MySQL的初始

1.登录mysql

mysql -u root -p
远程登录
mysql -u root -p -h106.52.85.190 -P端口

# 注意使用命令远程链接mysql,必须使用的地方有mysql
mysql -hIP -P端口 -uroot -p密码

2.修改密码

mysqladmin -uroot -p123 password "新密码"
mysqladmin -uroot -p password "新密码"

3.忘记密码,破解(linux)

# 1. 修改配置文件(linux命令行)
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
# 在[mysqld] 下加上skip-grant-tables

# 2. 重启mysql服务(linux命令行)
systemctl restart mysql

# 3.登录root管理用户,不需要输入密码(linux命令行)
mysql -u root -p # 直接回车,即可进入mysql命令

# 4. 设置新密码(mysql命令行)
mysql> update mysql.user set authentication_string=password('root123') where user="root"
and host="localhost";

# 5. 刷新授权表(mysqL命令行)
mysql> flush privileges;
# 6.进入mysql的配置文件,删除掉先加入的内容,保存退出,重启mysql服务.(linux命令行)
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
# 重启mysql服务(linux命令行)
systemctl restart mysql

4.设置统一字符编码(linux版本)

# 1. 修改mysqld配置文件
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
#加上如下代码
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

# 修改mysql客户端的配置文件
sudo vim /etc/mysql/conf.d/mysql.cnf 
[mysql]
default-character-set=utf8
[client]
default-character-set=utf8
# 2、重启MySQL服务
systemctl restart mysql

# 3、查看一下
show variables like "%char%";
​ 注意有坑:
​ 在配置统一字符编码之前的数据库,建议建表的时候,指定字符编码.

MySQL的操作

增删查改

1.操作数据库(目录)

# 增(添加数据库)
create database db1 default charset utf8;

# 查(查看数据库)
show databases;    				 # 查看所有数据库
show create database db1;		 # 查看指定的数据库

# 改(修改数据库编码)
alter database db1 charset gbk;  # 修改数据库的字符编码

# 删(删除数据库)
drop database db1;

2.操作数据表(文件)

# 增(添加数据表)
create table t1(id int,name varchar(32));   # 指定字段

# 查(查看表和表属性)
show tables; 								# 查看所有表(当前数据库下的)
show create table t1;						# 查看指定表
desc t1; 									# 查看表属性
mysql> desc t1;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(32) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

# 改(修改表)
alter table t1 modify name char(6);           # (modify) 只能修改约束条件和类型
alter table t1 change name Name char(7);	  # (change) 力度更大,可以改字段名加(modify)的功能
alter table t1 add price decimal(5,2) not null;# (add) 新增price字段

# 删(删除表)
drop table t1;								  # 指定对应的表名;
alter table book drop price;				  # 删除指定的字段名
truncate table t1;							  # 清空所有记录,并且重置至初识状态,id从1开始

3.操作表记录(文件内容)

# 增(添加表内容)
1.如果所有字段都添加
insert into t1 values(1,"xiaoming"),(2,"xiaohong");         # 按位置添加
insert into t1(id,name) values(1,'xiaoming'),(2,"xiaohong") # 指定字段添加
2.如果指定字段添加
insert into t1(name) values("xiaoming"),("xiaohong");

# 查(查找表内容)
select * from t1;									# 查看所有字段
select * from t1 where id=1; 						# 指定字段

# 改(更改表内容)
update t1 set name="xiaomi" where id=1;				# 注意,不where指定条件,默认会修改所有name的内容

# 删(删除表内容)
delete from t1 where name="xiaomi";				    # 注意,不where指定id或条件,跟上面说的一样

MySQL的数据类型

1.数值类型

整数类型

""" unsigned 指定该字段为无符号类型 """
		
tinyint    # 2**8(2的8次方范围)1个字节 # 注意:当插入的值超过这个范围,会报1264错误。
'有符号 -128---127
 无符号  0---255 '

'# 有符号例子
mysql> create table t1(num tinyint)	#创建表结构
mysql> desc t1;						#查看表信息
mysql> insert into t1 values(-128),(127); 
mysql> select * from t1;		    #查看表内容
 # 无号例子 #unsigned 指定无符号类型
mysql> create table t2(num tinyint unsigned); 
mysql> desc t2;						#查看表信息
mysql> insert into t2 values(0),(255); 
mysql> select * from t2;			 #查看表内容'

int 	   # 2**32(2的32次方范围)4个字节
' 有符号:-2147483648 ~ 2147483647
  无符号: 0 ~ 4294967295 ' 

bigint     # 2**64(2的64次方范围)8个字节
' 有符号:-9223372036854775808 ~ 9223372036854775807    
  无符号:0  ~  184467440737 '

浮点型

decimal:
'''
定义:
  	准确的小数值,m是数字总个数(负号不算),d是小数点后个数。 m最大值为65,d最大值为30。m:65d:30

精确度:
       **** 随着小数的增多,精度始终准确 ****
           	对于精确数值计算时需要用此类型
           	decaimal能够存储精确值的原因
# 例子
mysql> create table t1(num decimal(5,2));
mysql> insert into t1 values(456.12);
mysql> select * from t1;
'''

2.日期类型

year   				#(年) 无论year指定何种宽度,最后都默认是year(4)

'''  # 例子
mysql> create table t1(born_year year);
mysql> desc t1;
mysql> insert into t1 values(1901),(2155);# 超出这个范围会报1264错误。
mysql> select * from t1;   '''
date			    # (日期格式)
'''  # 例子
mysql> create table t1(born_date date);
mysql> desc t1;
mysql> insert into t1 values("2019-5-5");
mysql> select * from t1;     '''
time			    # (时间格式)
datetime		    #(***)(日期时间格式)(1000-01-01 00:00:00/9999-12-31 23:59:59)
timestamp			#(了解)(1970-01-01 00:00:00/2037 年某时)
'''
#三个集合语句
mysql> create table t1(d date,t time,dt datetime);
mysql> desc t1;
mysql> insert into t1 values(now(),now(),now());#当前日期时间
mysql> select * from t1;
1. 单独插入时间时,需要以字符串的形式,按照对应的格式插入
2. 插入年份时,尽量使用4位值
3. 插入两位年份时,<=69,以20开头,比如50,  结果2050     
                >=70,以19开头,比如71,结果1971    '''

3.字符串类型

char:    # 字符长度范围:0-255
	     # 定长,执行效率高,浪费空间.
	
varchar: # 字符长度范围:0-65535
	     # 不定长,速度慢,范围大,节省空间.
# 根据实际场景,来平衡使用,char要放在varchar的前面
char_length:# 查看字符数

'''# 例子,查看
mysql> create table t1(c char(5),v varchar(5));
mysql> desc t1;
mysql> insert into t1 values('字符串 ','字符串 ');          # 增加了空白格
mysql> select c,char_length(c),v,char_length(v) from t1;  # 查询字符长度
# char填充空格来满足固定长度,但是在查询时却会很不要脸地删除尾部的空格(装作自己好像没有浪费过空间一样),然后修改sql_mode让其现出原形。
# 略施小计,让char现出原形
mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';          # 让它显示原先的字符长度



'''
				#length:		#查看字节数
mysql> select c,length(c),v,length(v) from t1;

4.枚举类型和集合类型

1. # 枚举类型(单选)	enum("xxx", "xxx"....)
2. # 集合类型(多选)	set("xxx", "xxx","xxx"...)
enum # 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female

set  # 多选 在给定的范围内可以选择一个或一个以上的值(爱好1,爱好2,爱好3...)

'''# 枚举和集合例子
mysql> create table t1(id int,name varchar(32),sex enum('male','female'),hobby set('music','read','run','movie'));
mysql> desc t1;
mysql> insert into t1 values(1,'alex','female','music,movie,aaaa'),
    -> (2,'egon','female','read,run,music');
mysql> select * from t1;
'''

mysql语法严格模式

插入字段不在列表中,值为空,如果报错,mysql为严格模式
ERROR 1265 (01000): Data truncated for column 'hobby' at row 1
严格模式:
严格模式主要有以下场景:
不支持对not null字段插入null值
不支持对自增长字段插入”值
不支持text字段有默认值

1.开启与关闭Strict Mode方法
找到MySQL安装目录下的my.cnf(windows系统则是my.ini)文件

在sql_mode中加入STRICT_TRANS_TABLES则表示开启严格模式,如没有加入则表示非严格模式,修改后重启mysql即可

例如这就表示开启了严格模式: 
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

MySQL字段类型

# 约束条件
not null 	 	# 字段不能为空
default   		# 设置默认值
unique	 		# 主键,字段唯一
auto_increment  # 自增长,默认为1 该字段必须为主键.主键自增长,被约束的字段必须同时被key约束,一般用于id
primary key		# 外键,建立表之间的关系

1.not null 和 defult的用法

not null # 约束字段不能为空

default  # 设置默认值

         # 用法: (字段名称  数据类型  约束条件)

mysql> create table t1(id int,name varchar(32),sex enum('male','female') not null default 'male');
mysql> desc t1;
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | YES  |     | NULL    |       |
| name  | varchar(32)           | YES  |     | NULL    |       |
| sex   | enum('male','female') | NO   |     | male    |       |
+-------+-----------------------+------+-----+---------+-------+
mysql> insert into t1(id,name) values(1,'egon'); # 插入数据
mysql> select * from t1;
+------+------+------+
| id   | name | sex  |
+------+------+------+
|    1 | egon | male |
+------+------+------+

2.unique的用法

# 单列唯一
# 方式一:
# 直接在字段后加约束条件
mysql> create table t3(id int unique auto_increment,name varchar(32) unique);
mysql> desc t3;
mysql> insert into t3(name) values('it','id'); # 指定字段,auto_increment自增长,默认为1
mysql> insert into t3 values(7,'ip'),(8,'ip'); # 插入相同的名字会报错
ERROR 1062 (23000): Duplicate entry 'ip' for key 'name'

# 方式二:#两着效果相同
unique(字段名)
mysql> create table t3(id int,name varchar(32),unique(id),unique(name));
mysql> desc t3;
mysql> insert into t3 values(1,'IT'),(2,'IT');  # 插入相同的名字会报错
ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'


# 多列联合唯一
unique(字段名1,字段名2...)  # 联合唯一的,只有两两相等,才会报错,and的关系
mysql> create table t3(id int,ip char(15),port int,unique(id),unique(ip,port)); 
mysql> desc t3;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  | UNI | NULL    |       |
| ip    | char(15) | YES  | MUL | NULL    |       |
| port  | int(11)  | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
mysql> insert into t3 values(1,'192.168.0.1',8080),
	 -> (2,'192.168.0.1',8090),				
	 -> (3,'192.168.0.2',8080);					
mysql> select * from t3;
#报错例子
mysql> insert into t3 values(4,'192.168.0.1',8080);  # 插入数据
ERROR 1062 (23000): Duplicate entry '192.168.0.1-8080' for key 'ip'


3.primary key

# 用法同unique
# auto_increment自增长,默认起始值为1
mysql> create table t3(id int primary key auto_increment,name varchar(32));
mysql> desc t3;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(32) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
mysql> insert into t3(name) values('alex'),('egon');
mysql> select * from t3;
+----+------+
| id | name |
+----+------+
|  1 | alex |
|  2 | egon |
+----+------+
# 重复键值,会报错
mysql> insert into t3 values(2,'yuan');
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'

4.auto_increment

''' 前提:字段必须为主键.
    作用:是主键自增长
    被约束的字段必须同时被key约束。'''
mysql> create table t3(id int primary key auto_increment,name varchar(32));
mysql> desc t3;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(32) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
mysql> insert into t3(name) values('alex'),('egon');
mysql> select * from t3;
+----+------+
| id | name |
+----+------+
|  1 | alex |
|  2 | egon |
+----+------+
mysql> insert into t3 values(5,'yuan');  # 可以自己指定id只要不违反约束条件即可。
# 对于自增的字段,在用delete删除后,再插入值,该字段仍按照删除前的位置继续增长,一般情况下,delete后面会接where条件,对指定的内容进行删除。
mysql> delete from t3;   # 清空表 再重新插入数据起始位置不会从1开始
mysql> truncate table t3;# 清空所有记录,并且重置至初识状态(ID归零)清空auto_increment的索引值

# 关于起始偏移量和步长(了解)
# 1. 查看默认值
mysql> show variables like 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |  # 默认步长为1
| auto_increment_offset    | 1     |  # 默认起始偏移量为1
+--------------------------+-------+
# 2. 设置步长
 mysql> set session auto_increment_increment=5;  # 当前会话级别
 mysql> set global auto_increment_increment=5;   # 设置全局,需要退出重新加载才能生效。
# 3.设置起始偏移量
 mysql> set session auto_increment_offset=3;
 mysql> set global auto_increment_offset=3;
# 注意:起始偏移量要<=步长,否则设置无效。


5.foreign key

foreign key,# 外键 ,建立表之间的关系。
# 1、建立表关系
# a、先建被关联的表,且保证被关联的字段唯一
 mysql> create table department(
    -> id int primary key ,
    -> name varchar(32),
    -> comment varchar(128)
    -> );
mysql> desc department;
+---------+--------------+------+-----+---------+--------+
| Field   | Type         | Null | Key | Default | Extra  |
+---------+--------------+------+-----+---------+--------+
| id      | int(11)      | NO   | PRI | NULL    |		 |
| name    | varchar(32)  | YES  |     | NULL    |        |
| comment | varchar(128) | YES  |     | NULL    |   	 |
+---------+--------------+------+-----+---------+--------+

# b、再建关联的表
 mysql> create table employee(
    -> id int primary key auto_increment,            # 主键自增长
    -> name varchar(32),
    -> age tinyint unsigned,
    -> dep_id int,
    -> foreign key(dep_id) references department(id) # 指定外建字段,跟哪张表哪个字段建立关系。
    -> );
mysql> desc employee;
+--------+---------------------+------+-----+---------+----------------+
| Field  | Type                | Null | Key | Default | Extra          |
+--------+---------------------+------+-----+---------+----------------+
| id     | int(11)             | NO   | PRI | NULL    | auto_increment |
| name   | varchar(32)         | YES  |     | NULL    |                |
| age    | tinyint(3) unsigned | YES  |     | NULL    |                |
| dep_id | int(11)             | YES  | MUL | NULL    |                |
+--------+---------------------+------+-----+---------+----------------+

# 2、插入数据
  # a、先往被关联表插入记录
mysql> insert into department values
    ->  (1,'公关部','公关能力有限部门'),
    ->  (2,'销售部','销售能力有限部门'),
    ->  (3,'技术部','靠技术吃饭部门');
  # b、再往关联表插入记录
mysql> insert into employee values
    -> (1,'任盈盈',18,1),
    -> (2,'张无忌',23,2),
    -> (3,'令狐冲',25,2),
    -> (4,'小龙女',24,1),
    -> (5,'灭绝师太',56,1),
    -> (6,'欧阳锋',53,3);
  # 3.删除数据和更新数据
  # a、先删除关联的数据
  mysql> delete from employee where dep_id=2;
  # b、再删除被关联的数据
  mysql> delete from department where id=2;
  # c、因为有外建约束,无法进行更新操作。
  # mysql> update employee set id=5 where dep_id=3;
  # ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY'
  # mysql> update department set id=8 where id=2
  
# 4、解决上面的问题,只需在建  关联表  的时候,指定一下同步即可。
# 建立关联表
  mysql> create table employee(
    -> id int primary key,
    -> name varchar(32),
    -> age tinyint unsigned,
    -> dep_id int,
    -> foreign key(dep_id) references department(id) 
       on delete cascade  # 删除时同步
       on update cascade  # 更新时同步
    -> );

# 删除部门
mysql> delete from department where id =1;
mysql> select * from department ;
+----+-----------+--------------------------+
| id | name      | comment                  |
+----+-----------+--------------------------+
|  2 | 销售部    | 销售能力有限部门         |
|  3 | 技术部    | 靠技术吃饭部门           |
+----+-----------+--------------------------+

mysql> select * from employee; # 与之关联的员工一并删除了。
+----+-----------+------+--------+
| id | name      | age  | dep_id |
+----+-----------+------+--------+
|  2 | 张无忌    |   23 |      2 |
|  3 | 令狐冲    |   25 |      2 |
|  6 | 欧阳锋    |   53 |      3 |
+----+-----------+------+--------+
# 更新部门
mysql> update department set id=8 where id=2;
mysql> select * from department;
+----+-----------+--------------------------+
| id | name      | comment                  |
+----+-----------+--------------------------+
|  3 | 技术部    | 靠技术吃饭部门           |
|  8 | 销售部    | 销售能力有限部门         |
+----+-----------+--------------------------+
# 与之关联的表也会更改
mysql> select * from employee;

MySQL的查询语法

# 1.单表查询语法
SELECT 字段1,字段2...
FROM 表名
WHERE 条件
GROUP BY field
HAVING 筛选
ORDER BY field
LIMIT 限制条数

2.关键字的执行优先级(重点)
# 注解:
1.from     # 找到表:from

2.where    # 拿着where指定的约束条件,去文件/表中取出一条条记录

3.group by # 将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组

4.having   # 将分组的结果进行having过滤

5.select   # 执行select

6.distinct # 去重

7.order by # 将结果按条件排序:order by

8.limit    # 限制结果的显示条数

单表查询

数据结构准备

# 插入数据结构
mysql> create table employee(
    -> id int primary key auto_increment,
    -> name varchar(32) not null,
    -> sex enum('male','female') not null default 'male',
    -> age tinyint unsigned not null default 28,
    -> hire_date date not null,
    -> post varchar(32),
    -> post_comment varchar(128),
    -> salary decimal(9,2),
    -> office int,  # 一个部门一个屋子
    -> dep_id int
    -> );

# 插入数据
mysql> insert into employee(name,sex,age,hire_date,post,post_comment,salary,office,dep_id) 
values
('任盈盈','female',18,'2018-11-14','sale',null,8000,401,1),
('小龙女','female',23,'2017-11-24','sale',null,9000,401,1),
('王语嫣','female',22,'2016-1-14','sale',null,7000,401,1),
('黄蓉','female',21,'2018-12-14','sale',null,8000,401,1),
('秋香','female',19,'2019-1-11','sale',null,8000,401,1),
('周芷若','female',20,'2018-11-11','sale',null,7000,401,1),
('赵敏','female',21,'2017-2-18','sale',null,8000,401,1),

('令狐冲','male',24,'2017-1-24','operation',null,7000,402,2),
('张无忌','male',23,'2016-5-21','operation',null,7500,402,2),
('郭靖','male',25,'2016-7-28','operation',null,8000,402,2),
('杨康','male',24,'2016-8-28','operation',null,7000,402,2),
('杨铁心','male',54,'2015-4-18','operation',null,9000,402,2),
('杨过','male',27,'2017-5-28','operation',null,7000,402,2),

('张三丰','male',68,'2014-8-8','teacher','主授太极拳',11000,403,3),
('任我行','male',54,'2015-2-4','teacher','主授吸星大法',10000,403,3),
('岳不群','male',50,'2016-12-24','teacher','主授华山剑法',9000,403,3);

1.简单查询

# 查看全部,复杂写法(字段一个个写)
select id,name,sex,age,hire_date,post,post_comment,salary,office,dep_id from employee;

# 查看全部表内容(实际不推荐这种,按上面那种来写)
select * from employee; 

# 查看指定表字段内容
select id ,name,salary from employee;

# 避免重复distinct
select distinct post from employee; # 查看指定内容,只显示单个不重复内容


# 通过四则运算查询(加减乘除)
select name,salary * 12 from employee; # 原样显示(salary*12)
# 修改样式用as 取别名,不加as 默认后面就是别名
select name,salary * 12 as annual_salary from employee;

2.where用法

# where约束条件
'''
where字句中可以使用:
比较运算符:><>= <= <> !=
between         80 and 100 值在80到100之间
in(80,90,100)   值是80或90或100
like '姓%' '姓_' 可以是%或_,%表示匹配任意多字符, _表示匹配一个字符
逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not
'''
# 1、单条件查询
# 查询销售的所有员工
select name from employee where post='sale';
# 2、多条件查询
# 查询销售中工资大于等于8000的员工姓名和薪资
select name,salary from employee where post='sale' and salary >=8000;
# 3、关键字between and
# 查询不在8000到10000的员工姓名 ,只需在between 前面加not  ---> (not between)
# 查询工资在8000到10000的员工姓名
select name from employee where salary between 8000 and 10000;

# 4、关键字is null(判断某个字段是否为null不能用等号,需要用is)
# 查询值位不为空的员工,只需在is后面加not ---> (is not) 
# 查询职位描述为空的员工
select name,post_comment from employee where post_comment is null;
# 特殊符号 '' 是空字符串,不是null
# 更新
update employee set post_comment='' where id=1;
# 查询
select name ,post_comment from employee where post_comment='';

# 5、关键字IN集合查询
# or 原型(复杂)
select name,salary from employee where salary=8000 or salary=9000 or salary=10000;
#查询工资不为8000或9000或10000的,只需在in前面加not ---> (not in)
# 查询工资为8000或9000或10000的员工姓名和工资
select name,salary from employee where salary in (8000,9000,10000);

# 6、关键字LIKE模糊查询
# a、通配符"%",查找'杨'开头的
select name from employee where name like '杨%';

# b、通配符"_" #查找以"杨"开头的两个字符,'__',查找杨的三个字符
select naem from employee where name like '杨_'

3.group by用法

# 单独使用GROUP BY关键字分组
# 注意:我们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数。如:select post from employee group by post;

# GROUP BY关键字和GROUP_CONCAT()函数一起使用
# 按照岗位分组,并查看组内成员名
SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;
#更改别名
SELECT post,GROUP_CONCAT(name) as emp_members FROM employee GROUP BY post;
# 聚合函数
# MAX:最大值
# MIN:最小值
# AVG:平均值
# SUM:求和
# COUNT:计数 

# 查询每个职位最高的薪资
select post,max(salary) from employee group by post;
# 查询每个职位共有多个员工
select post,count(id) from employee group by post;

4.having用法

# having过滤

# HAVING与WHERE不一样的地方在于:
# !!!执行优先级从高到低:where > group by > having 
# 1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。
# 2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数

# 查询各岗位内包含的员工个数小于4的岗位名、岗位内包含员工名字、个数
select post,group_concat(name),count(id) from employee group by post having count(id) < 4;

5.order by用法

# 按单列排序
	select * from employee order by salary;       # 默认为升序
    SELECT * FROM employee ORDER BY salary ASC;   # 升序
    SELECT * FROM employee ORDER BY salary DESC;  # 降序

# 按多列排序:先按照age排序,如果年纪相同,则按照薪资排序
    SELECT * from employee ORDER BY age,salary DESC;

6.limit用法

# 限制查询的记录数 limit
select * from employee order by salary desc limit 3;	#默认初始位置为0 #查询第三条
select * from employee order by salary desc limit 0,5	#从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
SELECT * FROM employee ORDER BY salary DESC LIMIT 5,5;  #从第5开始,即先查询出第6条,然后包含这一条在内往后查5条

7.regexp用法

# 使用正则表达式查询
SELECT * FROM employee WHERE name REGEXP '^任'; #以任开头匹配

SELECT * FROM employee WHERE name REGEXP '女$'; #以女结尾匹配

# 小结:对字符串匹配的方式
WHERE name = '任盈盈';
WHERE name LIKE '杨%';
WHERE name REGEXP '女$';

多表查询

表关系说明

'''
一对一
一对多
多对多
'''
# 表连接方式
    inner join # 内连接
    left join  # 左连接
    right join # 右连接
    union	   # 全连接(mysql中用左连接右连接实现)
# 子查询
    #1:子查询是将一个查询语句嵌套在另一个查询语句中。
    #2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
    #3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
    #4:还可以包含比较运算符:= 、 !=、> 、<等

一对一

# 一对一关系
# 两张表:学生表和客户表
# 一对一:一个学生是一个客户,一个客户有可能变成一个学校,即一对一的关系
# 关联方式 :foreign key + unique

# 一定是student来foreign key表customer,这样就保证了:
# 1 学生一定是一个客户,
# 2 客户不一定是学生,但有可能成为一个学生

# 1.创建表
# 先建客户表
create table customer(
id int primary key auto_increment,
name varchar(32) not null,
qq varchar(32) not null,
tel varchar(32) not null
);

# 再建学生表
create table student(
id int primary key auto_increment,
class_name varchar(32) not null,
customer_id int unique,             #该字段一定要是唯一的,#也可以建在客户表
foreign key(customer_id) references student(id)
on delete cascade on update cascade # 关联同步删除同步更新
);

# 2.插入记录
# 先插被关联的客户表
insert into customer(name,qq,tel) values
('alex',1223,135666544),
('egon',34322,13438895),
('yuan',84322,13954893);

# 再插关联的表
insert into student(class_name,customer_id) values
('脱产2期',1),
('脱产3期',2),
('周末13期',3);

一对多

# 以出版社和书籍为例
# 1.创建表
create table press(
id int primary key auto_increment,
name varchar(32)
);

create table book(
id int primary key auto_increment,
name varchar(32),
press_id int,
foreign key(press_id) references press(id) 
on delete cascade on update cascade   # 关联同步删除同步更新
);

# 2.插入记录
# 先插被关联的表
inser into press(name) values
('华山出版社'),
('少林出版社'),
('明教出版社'),
('武当出版社'),
('丐帮出版社');

# 再插关联的表
insert into book(name,press_id) values
('独孤九剑',1),
('华山剑法',1),
('九阳神功',2),
('九阴真经',2),
('易筋经',2),
('葵花宝典',3),
('乾坤大挪移',3),
('太极拳',4),
('天罡北斗阵',4),
('吸星大法',5);


多对多

# 1.创建表
# 先创建作者表
create table author(
id int primary key auto_increment,
name varchar(32),
);

# 再建存放作者与书的关系表,即查询二者的关系查这表就可以了.
# author2book 建二者关系表时,用2把二者连接起来,约定熟成这样标识
create table author2book(
id int not null unique quto_increment,
author_id int,
book_id int,
foreign key(author_id) references author(id)
on delete cascade on update cascade,
foreign key(book_id) references book(id)
on delete cascade on update cascade,
primary key(author_id,book_id)
);

# 2.插入记录
# 插入作者记录
insert into author(name) values
('张无忌'),
('令狐冲'),
('东方不败'),
('张三丰'),
('冲虚道长');

# 再插入对应的关系记录
insert into author2book(author_id,book_id) values
(1,3),
(1,7),
(2,1),
(2,2),
(3,6),
(4,8);

表连接方式(join..)

# 外连接语法
SELECT 字段列表
  FROM 表1 INNER|LEFT|RIGHT JOIN 表2
  ON 表1.字段 = 表2.字段;
交叉连接(笛卡尔积)
# 注意:这种连接毫无意义
mysql> select * from book,press;  # 简单粗暴的将两张表连接起来
# 如果只想取到两表有关系的记录用where条件
mysql> select * from book,press where book.press_id=press.id;
#也可以用sql对应的语法实现.

1.inner join内连接用法
# 内连接,只取两表的共同部分
select * from book inner join press on book.press_id = press.id;
+----+------------+----------+----+------------+
| id | name       | press_id | id | name       |
+----+------------+----------+----+------------+
|  1 | 独孤九剑   |        1 |  1 | 华山出版社 |
|  2 | 华山剑法   |        1 |  1 | 华山出版社 |
|  3 | 九阳神功   |        2 |  2 | 少林出版社 |
|  4 | 九阴真经   |        2 |  2 | 少林出版社 |
|  5 | 易筋经     |        2 |  2 | 少林出版社 |
|  6 | 葵花宝典   |        3 |  3 | 明教出版社 |
|  7 | 乾坤大挪移 |        3 |  3 | 明教出版社 |
|  8 | 太极拳     |        4 |  4 | 武当出版社 |
|  9 | 天罡北斗阵 |        4 |  4 | 武当出版社 |
+----+------------+----------+----+------------+

2.left join 左连接用法
#先插入一条新的book记录
insert into book(name) values('降龙十八掌');
# 左连接,在内连接的基础上保留左边的记录。
select * from book left join press on book.press_id = press.id;
+----+------------+----------+------+------------+
| id | name       | press_id | id   | name       |
+----+------------+----------+------+------------+
|  1 | 独孤九剑   |        1 |    1 | 华山出版社 |
|  2 | 华山剑法   |        1 |    1 | 华山出版社 |
|  3 | 九阳神功   |        2 |    2 | 少林出版社 |
|  4 | 九阴真经   |        2 |    2 | 少林出版社 |
|  5 | 易筋经     |        2 |    2 | 少林出版社 |
|  6 | 葵花宝典   |        3 |    3 | 明教出版社 |
|  7 | 乾坤大挪移 |        3 |    3 | 明教出版社 |
|  8 | 太极拳     |        4 |    4 | 武当出版社 |
|  9 | 天罡北斗阵 |        4 |    4 | 武当出版社 |
| 10 | 吸星大法   |    5     |    5 | 丐帮出版社 |
| 11 | 降龙十八掌  |    NULL | NULL  | NULL    |
+----+------------+----------+------+------------+


3.right join 右连接用法
# 先插入一条新的press记录
insert into press(name) values('峨眉出版社');
# 右连接,在内连接的基础上保留右边的记录。
select * from book right join press on book.press_id = press.id;
+------+------------+----------+----+------------+
| id   | name       | press_id | id | name       |
+------+------------+----------+----+------------+
|    1 | 独孤九剑   |        1 |  1 | 华山出版社 |
|    2 | 华山剑法   |        1 |  1 | 华山出版社 |
|    3 | 九阳神功   |        2 |  2 | 少林出版社 |
|    4 | 九阴真经   |        2 |  2 | 少林出版社 |
|    5 | 易筋经     |        2 |  2 | 少林出版社 |
|    6 | 葵花宝典   |        3 |  3 | 明教出版社 |
|    7 | 乾坤大挪移 |        3 |  3 | 明教出版社 |
|    8 | 太极拳     |        4 |  4 | 武当出版社 |
|    9 | 天罡北斗阵 |        4 |  4 | 武当出版社 |
| 10   |吸星大法    |        5 |  5 | 丐帮出版社 |
| NULL | NULL      |  NULL    |  6 | 峨眉出版社 |
+------+------------+----------+----+------------+

4.union全连接用法
# 全外连接,在内连接的基础上保留左右两表没有对应关系的记录。
# 注意:mysql不支持全外连接 full JOIN
mysql> select * from book full join press on book.press_id = press.id;
#报错
ERROR 1054 (42S22): Unknown column 'book.press_id' in 'on clause'
# 强调:mysql可以使用此种方式间接实现全外连接(自己实现全外连接的效果)
# union 连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。
select * from book left join press on book.press_id = press.id
union
select * from book right join press on book.press_id = press.id;

+------+-----------------+----------+------+-----------+
| id   | name            | press_id | id   | name      |
+------+-----------------+----------+------+-----------+
|    1 | 独孤九剑        |     1     |  1  | 华山出版社   |
|    2 | 华山剑法        |     1     |   1 | 华山出版社   |
|    3 | 九阳神功        |     2     |   2 | 少林出版社   |
|    4 | 九阴真经        |     2     |   2 | 少林出版社   |
|    5 | 易筋经          |     2     |   2 | 少林出版社   |
|    6 | 葵花宝典        |     3     |   3 | 明教出版社   |
|    7 | 乾坤大挪移      |      3    |    3 | 明教出版社  |
|    8 | 太极拳          |     4    |    4 | 武当出版社  |
|    9 | 天罡北斗阵      |      4    |   4 |  武当出版社  |
|   10 | 吸星大法        |     5    |    5  | 丐帮出版社 |
|   11 | 降龙十八掌      |     NULL | NULL | NULL      |
|   12 | 如来神掌        |     NULL |NULL | NULL       |
| NULL | NULL           |    NULL  |    6 | 峨眉出版社  |
+------+-----------------+----------+-------+------+- -+

添加数据多表查询

# 为book表新增单价字段
alter table book add price decimal(5,2) not null;
# 查看表结构
mysql> desc book;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| name     | varchar(32)  | YES  |     | NULL    |                |
| press_id | int(11)      | YES  | MUL | NULL    |                |
| price    | decimal(5,2) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
# 更新新增字段的值
update book set price=60 where id=1;
update book set price=30 where id=2;
update book set price=70 where id=3;
update book set price=40 where id=4;
update book set price=80 where id=5;
update book set price=40 where id=6;
update book set price=50 where id=7;
update book set price=80 where id=8;
update book set price=30 where id=9;
update book set price=40 where id=10;

简单连表查询

# 示例一;
# 以内连接的方式查询book和press表,并且book表中的price字段值必须大于50,即找出单价大于50元的书籍以及书籍的出版社名称
select book.name,press.name from book inner join press on book.press_id =
press.id where price >50;
+--------------+-----------------+
| name         | name            |
+--------------+-----------------+
| 独孤九剑     | 华山出版社      |
| 九阳神功     | 少林出版社      |
| 易筋经       | 少林出版社      |
| 太极拳       | 武当出版社      |
+--------------+-----------------+

# 示例二:
# 以内连接的方式查询book和press表,并且以price字段的降序方式显示书籍名称、价格和出版社名称。
select book.name,book.price,press.name from book inner join press on 
book.press_id = press.id order by price desc;
+-----------------+-------+-----------------+
| name            | price | name            |
+-----------------+-------+-----------------+
| 太极拳          | 80.00 | 武当出版社      |
| 易筋经          | 80.00 | 少林出版社      |
| 九阳神功        | 70.00 | 少林出版社      |
| 独孤九剑        | 60.00 | 华山出版社      |
| 乾坤大挪移      | 50.00 | 明教出版社      |
| 九阴真经        | 40.00 | 少林出版社      |
| 葵花宝典        | 40.00 | 明教出版社      |
| 吸星大法        | 40.00 | 丐帮出版社      |
| 天罡北斗阵      | 30.00 | 武当出版社      |
| 华山剑法        | 30.00 | 华山出版社      |
+-----------------+-------+-----------------+


子查询 (in...)

# 1:子查询是将一个查询语句嵌套在另一个查询语句中。
# 2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
# 3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
# 4:还可以包含比较运算符:= 、 !=、> 、<等

1.in 或者 = 用法
# 1、查询书籍平均价格在45元以上的出版社的id和名称
#子查询
select id ,name from press where id in
(select press_id from book group by press_id having avg(price) > 45);

#连表查询
select press.id,press.name from press inner join book on press.id = book.press_id group by book.press_id having avg(book.price) > 45;

# 2、查看少林出版社的所有书籍名称
#子查询
select name from book
where press_id in
(select id from press where name ='少林出版社');
#连表查询
select book.name from book inner join press on book.press_id =
press.id where press.name = '少林出版社';

#3.查询出版书籍大于2的出版社名称
#子查询
select name from press
where id in 
(select press_id from book group by press_id having count(press_id) > 2);

#连表查询
select press.name from press inner join book on press.id = book.press_id group by book.press_id having count(book.id) > 2;

2.比较运算符 > < != 用法
# 查询书籍价格大于所有书籍平均价格的书名与单价
select name,price from book
where price > 
(select avg(price) from book);

# 查询大于出版社里平均价格的书名与单价
select name , price from book as t1
inner join
(select press_id,avg(price) avg_price from book group by press_id) as t2
on t1.press_id = t2.press_id
where t1.price > t2.avg_price;

3.exists查询
# EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。
# 而是返回一个真假值。True或False
# 当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询
# press表中存在name="少林出版社",Ture
mysql> select * from book
    ->  where exists
    ->  (select * from press where name="少林出版社");

# press表中存在name="峨眉出版社",False不进行查询
mysql> select * from book
    ->  where exists
    ->  (select * from press where name="峨眉出版社");
Empty set (0.00 sec)

PyMySQL模块

 import pymysql

# from pymysql import *

# 创建和数据库服务器的连接  connection 
conn = pymysql.connect(
    				   host='localhost',
                       port=3306,
                       user='root',
                       password='root123456',
                	   db='students',
                       charset='utf8')

# 创建游标对象
cursor = conn.cursor()

# 中间可以使用游标完成对数据库的操作
sql = "select * from student;"

# 执行sql语句的函数  返回值是该SQL语句影响的行数
count = cursor.execute(sql)
print("操作影响的行数%d" % count)
# print(cursor.fetchone())   # 返回值类型是元祖,表示一条记录

# 获取本次操作的所有数据
for line in cursor.fetchall():
    print("数据是%s" % str(line))

# 关闭资源 先关游标
cursor.close()
# 再关连接
conn.close()

posted on 2019-08-10 00:39  new_wsh  阅读(164)  评论(0编辑  收藏  举报

导航