mysql第二天

Mysql 第二天

  • 补充

  • 索引

  • 增删改查

  • 多表联合查询

补充

表字段改名 change

1.修改字段类型  modify 2.添加字段  add  first/after3.删除字段  drop4.表改名   rename 补充  5.字段改名  change   ?alter table users change 旧字段 新字段 类型(长度);

MySQL 查看帮助

? 关键字

数据类型 排序

最大到最小 字符串类型->时间类型->数值类型

性别 一般存数值类型

时间可以存时间戳

如果精度要求高 选择 decimal 字符串型的浮点数

索引

比如新华字典的 目录 比如书的目录

目的是 快速找到制定的内容

如果不用索引 需要从头到尾轮询 效率慢 索引 就是 先划定一个范围

类型

  • 普通索引

  • 唯一索引

  • 主键索引

  • 全文索引

  • 复合索引

普通索引

最基本的索引没有任何限制的

? index 发现创建索引有两种方式  1.alter table  2.create index ?区别: create index 不能创建主键索引 ?alter table 表名 add index(字段名);#创建索引 这个没有制定索引名称  那么名称跟字段名相同alter table 表名 add index 索引名称(字段名); #创建索引并且指定索引的名称 show index from 表名\G #查看索引   alter table 表名 drop index 索引名字; #删除索引??create index 索引名字 on 表名(字段名); #创建索引  drop index 索引名称 on 表名; #删除索引 show index from 表名\G??
唯一索引 unique

要求这一列不能有重复值 比如年龄 性别 这样的列

alter table 表名 add unique 索引名称(username);alter table 表名 drop index 索引名称;?
主键索引

每个表一定有个主键 不能有重复值 不能有空值 一般创建表的时候 我们就创建主键索引 比如 id

特殊的唯一索引

alter table users drop primary key; #删除主键索引 如果自动递增这一步报错 ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key?alter table users id int(11) unsigned not null;#消除自动递增 alter table users drop primary key; #再次执行成功 ??添加主键索引  ? alter table users add primary key(id);#创建主键索引  alter table users modify id int(11) unsigned not null auto_increment;  #让主键自动递增
全文索引

文章中 或者电商 或者社交网站 对需要全局搜索的内容 进行全文索引

alter table 表名 add fulltext 索引名字(字段名);
复合索引

对多个字段 同时添加索引

text 类型不能添加 普通索引、复合索引

alter table users add index a_test(username,age);

总结 建表的同时添加索引

create table if not exists in_test(    id int(11) unsigned not null primary key auto_increment,    username varchar(50) not null,    password varchar(50) not null,    content text not null,    index pw(password),    unique(username),    fulltext(content))engine=myisam default charset=utf8;?

增删改查

增 insert

mysql> desc in_test;
+----------+------------------+------+-----+---------+----------------+
| Field    | Type             | Null | Key | Default | Extra          |
+----------+------------------+------+-----+---------+----------------+
| id       | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| username | varchar(50)      | NO   | UNI | NULL    |                |
| password | varchar(50)      | NO   | MUL | NULL    |                |
| content  | text             | NO   | MUL | NULL    |                |
+----------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
#上面有几个字段 就要写 对应字段的内容 一个都不能落下  

insert into in_test values(1,‘abc‘,‘123456‘,‘kangbazi666‘); #主键 username不能出现重复值 否则报错  
#只是插入指定字段对应的内容即可  主键自增  sex 默认值 可以不用插入   其它字段不能为空
insert into in_test(username,password,content) values(‘zhangsan‘,‘123456‘,‘kangbazi888‘);


insert into money(username,password,balance,province,age,sex) values(‘laowang‘,‘123456‘,‘1000000‘,‘湖北‘,28,0),(‘laoshen‘,‘aaa‘,123.45,‘湖北‘,40,0),(‘laoning‘,‘11111‘,999999999,‘辽宁‘,38,0),(‘caixukun‘,‘xxxxxxs‘,23456.12,‘日本‘,29,1); #一次性插入多条记录

查 select

select * from 表名; #   *代表 所有的字段的意思  
 select 字段1,字段2 from 表名; # 查看指定的字段 
 
 mysql> select username,content from in_test;
+----------+-------------+
| username | content     |
+----------+-------------+
| abc      | kangbazi666 |
+----------+-------------+
1 row in set (0.00 sec)

mysql> select username as 姓名,content as 内容 from in_test; #as 显示结果的别名
+--------+-------------+
| 姓名   | 内容        |
+--------+-------------+
| abc    | kangbazi666 |
+--------+-------------+

删 delete

delete from 表名#清空表 

原来有3条记录  下次再插入数据  id 从4开始  除非指定id的值  

delete from 表名 where 字段=值;#删除指定的内容  where 是条件

truncate table 清空表

truncate table 表名; #下次插入数据 id下标就从1开始

改 update

update 表名 set 字段=‘新内容‘ where 字段=值; #更新指定的内容

数据库查询 扩展

create table if not exists money(
	id int(11) unsigned not null primary key auto_increment,
	username varchar(64) not null,
	password char(64) not null,
	province varchar(16) not null,
	balance float not null,
	age tinyint default 18,
	sex tinyint default 0
)engine=myisam default charset=utf8;


insert into money(username,password,balance,province,age,sex) values(‘laowang‘,‘123456‘,‘1000000‘,‘湖北‘,28,0),(‘laoshen‘,‘aaa‘,123.45,‘湖北‘,40,0),(‘laoning‘,‘11111‘,999999999,‘辽宁‘,38,0),(‘caixukun‘,‘xxxxxxs‘,23456.12,‘日本‘,29,1); #一次性插入多条记录
distinct 查询单个字段不重复记录
select distinct age from money; #查询money 表年龄唯一的结果
  select distinct 字段 from 表名;
where 条件
select * from money where age=18;
 select 字段 from 表名 where 字段=值;
运算符说明
> 
< 
>= 
<= 
!= 
= 
or或者
and并且
  
select username as ‘姓名‘,balance as ‘余额‘,province as ‘省份‘ from money where id<10 and province=‘湖北‘;
结果集排序 order by
  • asc 升序

  • desc 降序

select id,username,balance,province from money order by balance desc;#按照余额降序排列
select id,username,balance,province from money order by balance asc;#升序
select 字段1,字段2,字段n from 表名 order by 字段 关键词;
多个字段排序  如果第一个字段已经将结果排序ok,那么第二个字段将会被忽略

mysql> select id,username,balance,province,age from money order by balance desc,age asc;
结果集限制 limit
mysql> select * from money limit 5;
限制结果集并且排序
mysql> select id,username,balance,province,age from money order by balance desc,age asc limit 5;
结果集区间选择 limit
select 字段 from 表名 limit 偏移量,数量;
下标从0开始

mysql> select * from money limit 2,5; #下标为2 第三条记录开始 取5条结果
用户从前端提交	  下标 数量(程序员自己设定)   
第1页  		   0    3     
第2页            3    3
第3页            6    3
第4页            9    3

下标 =  (第几页-1)* 每页显示的数量
统计函数
函数作用
count()统计总数
sum()求和
avg()平均数
max()最大值
min()最小值
  
mysql> select count(id) from money; #统计总数
+----------+
| count(id) |
+----------+
|        8 |
+----------+
1 row in set (0.00 sec)

mysql> select sum(balance) from money;
+-------------------+
| sum(balance)      |
+-------------------+
| 9756671443.651169 |
+-------------------+
1 row in set (0.00 sec)

mysql> select avg(balance) from money;
+-------------------+
| avg(balance)      |
+-------------------+
| 1219583930.456396 |
+-------------------+
1 row in set (0.01 sec)



mysql> select max(balance) from money;
+--------------+
| max(balance) |
+--------------+
|   7666670080 |
+--------------+
1 row in set (0.00 sec)

mysql> select min(balance) from money;
+--------------------+
| min(balance)       |
+--------------------+
| 123.44999694824219 |
+--------------------+
1 row in set (0.00 sec)
分组 group by
进入mysql   
select @@sql_mode;
会发现有 ONLY_FULL_GROUP_BY 表名这是按照Oracle的分组规则 也就是说 select 所有的列都要在分组中  
mysql> select @@sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@sql_mode                                                                                                                                |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)



修改配置文件 

sudo vim /etc/mysql/mysqld.conf.d/mysqld.cnf  

[mysqld]

sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION


service mysql restart   


重新登录mysql  
select @@sql_mode; 
就发现 ONLY_FULL_GROUP_BY 取消了 


mysql> select * from money group by province; # 相同的省份只显示一个
+----+------------+----------+------------+----------+------+------+
| id | username   | password | balance    | province | age  | sex  |
+----+------------+----------+------------+----------+------+------+
|  6 | 郭德纲     | 1112212  | 1000000000 | 天津     |   50 |    0 |
|  7 | bingbing   | 1122345  |   88888900 | 山东     |   45 |    1 |
|  4 | caixukun   | xxxxxxs  |    23456.1 | 日本     |   29 |    1 |
|  5 | xiaoyueyue | 11233    |    88888.1 | 河南     |   18 |    0 |
|  1 | laowang    | 123456   |    1000000 | 湖北     |   28 |    0 |
|  3 | laoning    | 11111    | 1000000000 | 辽宁     |   38 |    0 |
+----+------------+----------+------------+----------+------+------+
6 rows in set (0.00 sec)



mysql> select count(province) as ‘人数‘,province from money group by province;
#统计省份的数量以后再显示  
+--------+----------+
| 人数   | province |
+--------+----------+
|      1 | 天津     |
|      1 | 山东     |
|      1 | 日本     |
|      1 | 河南     |
|      3 | 湖北     |
|      1 | 辽宁     |
+--------+----------+
6 rows in set (0.00 sec)



mysql> select count(province) as ‘人数‘,province from money group by province with rollup;
# 相比较上面结果 多了同一总数的统计    
+--------+----------+
| 人数   | province |
+--------+----------+
|      1 | 天津     |
|      1 | 山东     |
|      1 | 日本     |
|      1 | 河南     |
|      3 | 湖北     |
|      1 | 辽宁     |
|      8 | NULL     |  #这里多了一行总的结果 
+--------+----------+
7 rows in set (0.01 sec)
分组的结果过滤一下 having
mysql> select count(province) as result,province from money group by province having result>1; 
+--------+----------+
| result | province |
+--------+----------+
|      3 | 湖北     |
+--------+----------+

总结

select 你选择的列 [as "显示的别名"]
from 表
where 条件
group by 分组 [having 分组过滤的条件]
order by 字段 
limit 偏移量,数量或者 数量

多表联合查询

  • 内连接 inner join on

  • 外连接

    • 左连接 left join on

    • 右连接 right join on

  • 子查询

准备

mysql> create table if not exists users(
    uid int(11) unsigned not null primary key auto_increment,
    username varchar(64) not null,
    password varchar(64) not null
)engine=innodb default charset=utf8;
Query OK, 0 rows affected (0.01 sec)

mysql> create table if not exists order_goods(
    oid int(11) unsigned not null primary key auto_increment,
    uid int(11) not null,
    name varchar(64) not null,
    buytime int(11) not null
)engine=innodb default charset=utf8;
Query OK, 0 rows affected (0.01 sec)

内连接  

1.select 表1.字段1,表1.字段2 as ‘别名‘,表2.字段1 as ‘别名‘,表2.字段2 from 表1,表2 where 表1.字段=表2.字段;


mysql> select users.uid,users.username as ‘用户名‘,order_goods.name as ‘商品名‘,order_goods.buytime from users,order_goods where users.uid=order_goods.uid;
+-----+-----------+------------+---------+
| uid | 用户名    | 商品名     | buytime |
+-----+-----------+------------+---------+
|   2 | zhicheng  | iPhone11   | 1111112 |
|   4 | huwei     | 杜蕾斯     |   12345 |
|   6 | Lee       | wawa       |  123455 |
|   3 | daoke     | jinpingmei | 1121212 |
+-----+-----------+------------+---------+

select u.uid,u.username as ‘用户名‘,o.name as ‘商品名‘,o.buytime from users u,order_goods o where u.uid=o.uid; #上面的简化版   字段显示别名 as 表起别名 空格即可 

2. select 表1.字段1 [as 别名],表n.字段 from 表1 inner join 表n on 条件;


mysql> select users.uid as ID,users.username as ‘姓名‘,order_goods.name as "商品名",order_goods.buytime from users inner join order_goods on users.uid=order_goods.uid;

外连接

1.左连接   select 表1.字段1 [as 别名],表n.字段 from 表1 left join 表n on 条件;
以lef join 左边的表为准  用户表 买东西的 和没买的都给你显示  

mysql> select users.uid as ID,users.username as ‘姓名‘,order_goods.name as "商品名",order_goods.buytime from users left join order_goods on users.uid=order_goods.uid;
+----+----------+------------+---------+
| ID | 姓名     | 商品名     | buytime |
+----+----------+------------+---------+
|  2 | zhicheng | iPhone11   | 1111112 |
|  4 | huwei    | 杜蕾斯     |   12345 |
|  6 | Lee      | wawa       |  123455 |
|  3 | daoke    | jinpingmei | 1121212 |
|  1 | xuelin   | NULL       |    NULL |
|  5 | xinxin   | NULL       |    NULL |
+----+----------+------------+---------+
6 rows in set (0.00 sec)



2.右连接    select 表1.字段1 [as 别名],表n.字段 from 表1 right join 表n on 条件;
以right join 右边的表为准   
mysql> select users.uid as ID,users.username as ‘姓名‘,order_goods.name as "商品名",order_goods.buytime from users right join order_goods on users.uid=order_goods.uid;
+------+----------+------------+---------+
| ID   | 姓名     | 商品名     | buytime |
+------+----------+------------+---------+
|    2 | zhicheng | iPhone11   | 1111112 |
|    4 | huwei    | 杜蕾斯     |   12345 |
|    6 | Lee      | wawa       |  123455 |
|    3 | daoke    | jinpingmei | 1121212 |
+------+----------+------------+---------+
4 rows in set (0.00 sec)


3.如果上面左连接为例子  null 可以显示默认值    

(case when 表.字段 is null then 默认值 else 表.字段 end) as ‘别名‘

mysql> SELECT users.uid,users.username as 用户名,(case when order_goods.`name` is NULL THEN ‘没买东西‘ ELSE order_goods.name END) as 商品名 from users LEFT JOIN order_goods on users.uid=order_goods.uid;
+-----+-----------+--------------+
| uid | 用户名    | 商品名       |
+-----+-----------+--------------+
|   2 | zhicheng  | iPhone11     |
|   4 | huwei     | 杜蕾斯       |
|   6 | Lee       | wawa         |
|   3 | daoke     | jinpingmei   |
|   1 | xuelin    | 没买东西     |
|   5 | xinxin    | 没买东西     |
+-----+-----------+--------------+
6 rows in set (0.00 sec)


4.如果上面左连接为例子  null 可以显示默认值  

ifnull(表.字段,‘默认值‘)

mysql> SELECT users.uid,users.username as 用户名, IFNULL(order_goods.name,"空空 如也") as 商品名 from users LEFT JOIN order_goods on users.uid=order_goods.uid;
+-----+-----------+--------------+
| uid | 用户名    | 商品名       |
+-----+-----------+--------------+
|   2 | zhicheng  | iPhone11     |
|   4 | huwei     | 杜蕾斯       |
|   6 | Lee       | wawa         |
|   3 | daoke     | jinpingmei   |
|   1 | xuelin    | 空空如也     |
|   5 | xinxin    | 空空如也     |
+-----+-----------+--------------+
6 rows in set (0.00 sec)

子查询

1.SELECT * from users where uid in(2,3,4,6);# 查询购买用户的详细信息   括号中的值是写死的


2.SELECT * from users where uid in(select uid from order_goods);#先从一个表中查出记录再 将结果作为条件 从另外表中查询 

in 
not in 
= 
!= 
exists 
not exists

union union all

两个表的数据按照一定条件查询出来 结果并到一起显示

mysql> select uid from users union all select uid from order_goods;
+-----+
| uid |
+-----+
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
|   6 |
|   2 |
|   4 |
|   6 |
|   3 |
+-----+
10 rows in set (0.00 sec)


mysql> select uid from users union select uid from order_goods; #去除重复记录  
+-----+
| uid |
+-----+
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
|   6 |
+-----+
6 rows in set (0.00 sec)

DCL 数据库控制语句

首先选中 mysql

每个数据库服务器都有一个mysql数据库

mysql 数据库存放着 权限用户等 重要信息 每个数据库都是不同的

grant 权限 on 数据库.数据表 to ‘用户名‘@‘主机‘ identified by ‘密码‘ with grant option;

权限: all 所有权限 
	 select 
	 insert 
	 update
	 delete
数据库: 
	 * 所有的数据库
数据表:
	* 所有的数据表
	
用户名:
	用户名如果不是存在的 那么就会新建 
主机: 
	%  任意主机
	
flush privileges; #刷新权限  


mysql> grant select,insert on test.users to ‘mxl‘@‘%‘ identified by ‘666666‘;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)




revoke 权限 on 数据库.数据表 from ‘用户名‘@‘主机‘;
flush privileges; #刷新权限  



mysql> revoke insert on test.users from ‘mxl‘@‘%‘;
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

数据库的备份及恢复 Linux命令

备份 mysqldump

mysqldump -u root -p test > /tmp/test.sql

恢复 mysql

mysql -u root -p test < /tmp/test.sql

计划任务 备份数据库

which mysqldump
crontab -e  
0 2 * * *  /usr/bin/mysqldump -u root -p123456 数据库名 > /tmp/test.sql

Python 操作mysql

python不能直接操作mysql 需要通过 扩展

pymysql(开源)

https://github.com/PyMySQL/PyMySQL

安装pymysql

1.pip install pymysql 

2.sudo apt-get install git 
  git clone https://github.com/PyMySQL/PyMySQL.git
  cd PyMySQL/
  python setup.py install

Python 操作 mysql 五行拳

  • 连接数据库

  • 创建游标

  • 执行sql 语句

  • 获取结果集

  • 关闭连接

#encoding:utf-8
import pymysql

#连接数据库
#主机地址 
#用户名
#密码
#数据库名字

#五行拳第一拳 
db = pymysql.connect("127.0.0.1",‘root‘,‘123456‘,‘test‘)

#第二拳  
cursor =db.cursor()


#准备sql语句 
sql = ‘select * from money order by balance limit 3‘

#执行sql语句
cursor.execute(sql)

#获取结果集  
data = cursor.fetchone()
print(data)

#释放句柄对象  
cursor.close()

#关闭mysql 连接 
db.close()

创建数据表

#encoding:utf-8
import pymysql

#连接数据库
#主机地址 
#用户名
#密码
#数据库名字

#五行拳第一拳 
db = pymysql.connect("127.0.0.1",‘root‘,‘123456‘,‘test‘)

#第二拳  
cursor =db.cursor()


#准备sql语句 
sql = ‘create table if not exists kangbazi(id int(11) unsigned not null primary key auto_increment,username varchar(64) not null)engine=innodb default charset=utf8‘

#执行sql语句
cursor.execute(sql)

#释放句柄对象  
cursor.close()

#关闭mysql 连接 
db.close()

插入数据

#encoding:utf-8
import pymysql

#连接数据库
#主机地址 
#用户名
#密码
#数据库名字

#五行拳第一拳 
db = pymysql.connect("127.0.0.1",‘root‘,‘123456‘,‘test‘)

#第二拳  
cursor =db.cursor()


#准备sql语句 
sql = ‘insert into kangbazi(username) values("kangbazi1"),("kangbazi2")‘
try:
    #执行sql语句
    cursor.execute(sql)
    db.commit()
except:
    db.rollback() #只有innodb引擎才支持事务
#释放句柄对象  
cursor.close()

#关闭mysql 连接 
db.close()

作业

1.封装一个类实现增删改查

相关推荐