1.mysql的简介mysql
2.增删改查操做linux
3.单表查询正则表达式
4.多表查询常见的三种方式sql
5.pymysql模块操做数据库数据库
概述:mysql是一个关系型数据库,关系型数据库模型是把复杂的数据结构归结为简单的二元关系(即二维表格形式,不是excel,可是和excel的形式很像)windows
mysql安装目录说明:性能优化
配置文件里面主要分三段:服务器
[mysqld] 配置mysql服务端相关的信息数据结构
[mysql] 配置mysql客户端相关的信息ide
[client] 配置其余客户端相关的信息
安装数据库后会有四个自带的数据库:
information_schema数据库是MySQL自带的,它提供了访问数据库元数据的方式。什么是元数据呢?元数据是关于数据的数据,如数据库名或表名,
列的数据 类型,或访问权限等。有些时候用于表述该信息的其余术语包括“数据词典”和“系统目录”。
mysql:这个是mysql的核心数据库,相似于sql server中的master表,主要负责存储数据库的用户、权限设置、关键字等mysql本身须要使用的控制和管理
信息。不能够删除,若是对mysql不是很了解,也不要轻易修改这个数据库里面的表信息。
performance_schema mysql 5.5 版本 新增了一个性能优化的引擎: PERFORMANCE_SCHEMA这个功能默认是关闭的: 须要设置参数: performance_schema 才能够启动该功能,这个参数是静态参数,只能写在my.ini 中 不能动态修改。
这里的数据表分为几类:
1) setup table : 设置表,配置监控选项。
2) current events table : 记录当前那些thread 正在发生什么事情。
3) history table 发生的各类事件的历史记录表
4) summary table 对各类事件的统计表
5) 杂项表,乱七八糟表
test: 安装mysql自带的测试表,默认为空,没什么用。
给mysql root用户设置密码的三种方式
方法1: 用SET PASSWORD命令
首先登陆MySQL,使用mysql自带的那个客户端链接上mysql。
格式:mysql> set password for 用户名@localhost = password('新密码');
例子:mysql> set password for root@localhost = password('123');
方法2:用mysqladmin
格式:mysqladmin -u用户名 -p旧密码 password 新密码
例子:mysqladmin -uroot -p123456 password 123
方法3:用UPDATE直接编辑那个自动的mysql库中的user表
use mysql
mysql> update user set password=password('123') where user='root' and host='localhost';
mysql> flush privileges; 刷新权限,让其生效,不然不生效,修改不成功。
忘记root的解决方案以windows为例:
先关闭mysql服务:
方法一:net start/stop MySQL ps:须要以管理员的身份运行cmd才行
方法二:tasklist | findstr mysql
taskkill /F /PID id
切换的安装mysql的bin下
G: ps:windows下切换到盘符不用写cd,直接写盘符便可
cd MySQL/bin
--skip-grant-table 跳过权限表
update user set password=password("new password") where user="root"
flush privileges
最后重启服务便可
修改字符集:
\s 查看mysql初始信息
show create database dbname; 查看建立库的信息
show variables like "%char%"; 查看各个角色的编码
解决乱码:注意一下其中的character_set_client、character_set_connection、character_set_results这三项就是由于这三和服务端的编码不一致致使的,因此咱们须要将这三项改成和服务端一致的字符集就能够了。
在windows下查看sqlite的utf-8中文须要先执行chcp 65001把当前页换为utf-8编码
chcp 命令:
chcp 65001 就是换成UTF-8代码页,在命令行标题栏上点击右键,选择"属性"->"字体",将字体修改成True Type字体"Lucida Console",而后点击肯定将属性应用到当前窗口
chcp 936 能够换回默认的GBK
chcp 437 是美国英语
linux系统查看系统默认编码的指令:
执行指令:cat sysconfig i18n
结果中有一条是:LANG="zh_CN.utf8"
关于引擎知识: mysql默认引擎是Innodb,不一样的引擎在目录下会生成不一样的文件,不一样的引擎会生成不一样的文件,Innodb支持事务操做
1.后缀名为.frm的文件:这个文件主要是用来描述数据表结构(id,name字段等)和字段长度等信息 2.后缀名为.ibd的文件:这个文件主要储存的是采用独立表储存模式时储存数据库的数据信息和索引信息; 3.后缀名为.MYD(MYData)的文件:从名字能够看出,这个是存储数据库数据信息的文件,主要是存储采用独立表储存模式时存储的数据信息; 4.后缀名为.MYI的文件:这个文件主要储存的是数据库的索引信息; 5.ibdata1文件:主要做用也是储存数据信息和索引信息,这个文件在mysql安装目录的data文件夹下。 从上面能够看出,.ibd储存的是数据信息和索引信息,ibdata1文件也是存储数据信息和索引信息,.MYD和.MYI也是分别储存数据信息和索引信息,那他们之间有什么区别呢? 主要区别是再于数据库的存储引擎不同,若是储存引擎采用的是MyISAM,则生成的数据文件为表名.frm、表名.MYD、表名的MYI;而储存引擎若是是innoDB,开启了innodb_file_per_table=1,也就是采用独立储存的模式,生成的文件是表名.frm、表名.ibd,若是采用共存储模式的,数据信息和索引信息都存储在ibdata1中; 在进行数据恢复的时候,若是用的是MYISAM数据引擎,那么数据很好恢复,只要将相应.frm, .MYD, .MYI文件拷贝过去便可。可是若是是innodb的话,则每个数据表都是一个单独的文件,只将相应的.frm和.ibd文件拷贝过去是不够的,必须在你的ibd文件的tablespace id和ibdata1文件中的元信息的tablespace id一致才能够。
开启事务:start transaction 开启事务 begin也是开启事务
事务回滚:rollback
提交:commit
简单操做:
SQL语句主要是针对数据库里面三个角色进行操做,对象是:库、表、行,操做包括:增删改查。
一、库(data文件夹中的文件夹,每建立一个库,这个库的名称就是文件夹的名称,文件夹里面保存着一些这个库相关的初始信息)
增:create database db1 charset utf8; #建立一个库,能够指定字符集
查:show databases; #查看数据库中全部的库
show create database db1; #查看单独某个库db1的信息
改:alter database db1 charset latin1; #修改库的字符集,注意语句的格式(其余语句也是这么个格式),alter(修改) database(修改数据库) db1 (哪一个数据库) charset(字符集) latin1(改为哪一个字符集)
删除: drop database db1; #删除数据库
二、表(操做文件,表是上面库文件夹里面的文件)
先切换库:use db1; #要操做表文件,要先切换到对应的库下才能操做表
查看当前所在的是哪一个库:select database();
增:create table t1(id int,name char(10) );
查:show tables; #查看当前库中全部的表
show create table t1; #查看单表的建立信息
desc t1;查看表信息,以表格的形式展现结果:
describe t1;#上下这两句是同样的结果
改:alter table t1 modify name char(3); #修改字段属性的,将name字段的char长度改成3
删:drop table t1;
3. 行(操做文件(表)中的内容/记录)(*****未来的重中之重)
增:insert into t1 values(1,'dsb1'),(2,'dsb2'),(3,'dsb3'); #往t1表中插入三行数据
查:select * from t1; #查看t1表中全部字段的数据
改:update t1 set name='sb' where id=2;
删:delete from t1 where id=1; #删除id为1的行
清空表:
delete from t1; #若是有自增id,新增的数据,仍然是以删除前的最后同样做为起始。
truncate table t1;数据量大,删除速度比上一条快,且直接从零开始, 通常用于设置了自增而后想从id 1起始的。
auto_increment 表示:自增
primary key 表示:约束(不能重复且不能为空);加速查找
建立语法:
一、建立数据库
CREATE DATABASE 数据库名 charset utf8;
命令规则:
能够由字母、数字、下划线、@、#、$
区分大小写
惟一性
不能使用关键字如 create select
不能单独使用数字
最长128位
2.建立表语法:
create table 表名( 字段名1 类型[(宽度) 约束条件], 字段名2 类型[(宽度) 约束条件], 字段名3 类型[(宽度) 约束条件] );
1. 在同一张表中,字段名是不能相同 2. 宽度和约束条件可选、非必须,宽度指的就是字段长度约束,例如:char(10)里面的10 3. 字段名和类型是必须的
经常使用的数据类型:
1. 数字: 整型:tinyinit int bigint
适用范围:存储年龄,等级,id,各类号码等
tinyint[(m)] [unsigned] [zerofill] ps:unsigned 表明无符号不设置unsigned默认有符号 zerofill 0填充
小数: float :在位数比较短的状况下不精准 double :在位数比较长的状况下不精准
decimal:(若是用小数,则用推荐使用decimal)
精准,内部原理是以字符串形式去存
2. 字符串:
char(10):简单粗暴,浪费空间,存取速度快,以三个字节来存储数据,小于三的,自动补零
varchar:精准,节省空间,存取速度慢
sql优化:建立表时,定长的类型往前放,变长的日后放好比性别 好比地址或描述信息 >255个字符,超了就把文件路径存放到数据库中。 好比图片,视频等找一个文件服务器,数据库中只存路径或url。
3.时间:
data: 年月日
time: 时分秒
datetime 年月日加时分秒
4.枚举和集合:
enum:多选一
set:复选
扩展:MySQL的mode设置,用于限制一些无效的输入
设置的三种方法: 方法3须要重启服务才能生效
1.临时:set sql_mode='strict_trans_tables'
2.数据库重启失效:set global sql_mode='strict_trans_tables'
3.永久设置:my.cnf文件(windows系统是my.ini文件),新增 sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
查看当前mode模式:
select @@global.sql_mode
select @@sql_mode
表的完整性约束
约束条件与数据类型的宽度同样,都是可选参数,做用:用于保证数据的完整性和一致性
主要分为如下:
PRIMARY KEY (PK) 标识该字段为该表的主键,能够惟一的标识记录 FOREIGN KEY (FK) 标识该字段为该表的外键 NOT NULL 标识该字段不能为空 UNIQUE KEY (UK) 标识该字段的值是惟一的 AUTO_INCREMENT 标识该字段的值自动增加(整数类型,并且为主键) DEFAULT 为该字段设置默认值 UNSIGNED 无符号 ZEROFILL 使用0填充
设置unique的两种方法:
方法一: create table department1( id int, name varchar(20) unique, comment varchar(100) ); 方法二: create table department2( id int, name varchar(20), comment varchar(100), constraint uk_name unique(name) );
联合惟一的设置:
create table service( id int primary key auto_increment, name varchar(20), host varchar(15) not null, port int not null, unique(host,port) #联合惟一 ); ps:若是插入的值host和port都重复才会报错
主键primary key字段的值不为空且惟一
主键primary key是innodb存储引擎组织数据的依据,innodb称之为索引组织表,一张表中必须有且只有一个主键。
单列作主键=============== #方法一:not null+unique
create table department1( id int not null unique, #主键 name varchar(20) not null unique, comment varchar(100) );
#方法二:在某一个字段后用primary key create table department2( id int primary key, #主键 name varchar(20), comment varchar(100) );
#方法三:在全部字段后单独定义primary key create table department3( id int, name varchar(20), comment varchar(100), constraint pk_name primary key(id)); #建立主键并为其命名pk_name
==================多列作主键================ create table service( ip varchar(15), port char(5), service_name varchar(10) not null, primary key(ip,port) );
自增 auto_increment
默认起始位置为1,步长也为1.
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);
对于自增的字段,在用delete删除后,再插入值,该字段仍按照删除前的位置继续增加
应该用truncate清空表,比起delete一条一条地删除记录,truncate是直接清空表,在删除大表时用它
truncate student;
在建立完表后,修改自增字段的起始值
alter table student auto_increment=3;
#也能够建立表时指定auto_increment的初始值,注意初始值的设置为表选项,应该放到括号外 create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' )auto_increment=3;
外键:foreign key
一 快速理解foreign key(外键其实就是标明表和表之间的关系,表和表之间若是有关系的话就三种:一对一,多对一,多对多
foreign key的下面几个约束做用:
一、先要创建被关联的表才能创建关联表
二、在插入数据记录的时候,要先想被关联表中插入数据,才能往关联表里面插入数据
三、更新或者删除数据的时候,都须要考虑关联表和被关联表的关系
解决方案:
a.删除表的时候,先删除关联表,再删除被关联表
b.重建表的时候,在加外键关联的时候加上这两句:on delete cascade 和 on update cascade
建立:
表类型必须是innodb存储引擎,且被关联的字段,即references指定的另一个表的字段,必须保证惟一 create table department( id int primary key, name varchar(20) not null )engine=innodb; #dpt_id外键,关联父表(department主键id),同步更新,同步删除 create table employee( id int primary key, name varchar(20) not null, dpt_id int, constraint fk_name foreign key(dpt_id) #这句话的意思是constraint 是声明咱们要创建一个约束啦,fk_name是约束的名称。 on delete cascade on update cascade )engine=innodb;
总结: #多对一: 若是只有步骤1成立,则是左表多对一右表 若是只有步骤2成立,则是右表多对一左表 #多对多 若是步骤1和2同时成立,则证实这两张表时一个双向的多对一,即多对多,须要定义一个这两张表的关系表来专门存放两者的关系 #一对一: 若是1和2都不成立,而是左表的一条记录惟一对应右表的一条记录,反之亦然。这种状况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique便可
查看全部外键的名称的方法: select REFERENCED_TABLE_SCHEMA,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME,table_name,CONSTRAINT_NAME from
information_schema.key_column_usage;
#包含咱们建立外键的时候,mysql帮咱们自动生成的外键名称。
修改表alter table
语法:
1. 修改表名
ALTER TABLE 表名 RENAME 新表名;
2. 增长字段
ALTER TABLE 表名
ADD 字段名 数据类型 [完整性约束条件…];
增长数据字段的时候指定位置经过first和after控制
ALTER TABLE 表名
ADD 字段名 数据类型 [完整性约束条件…] FIRST;
ALTER TABLE 表名
ADD 字段名 数据类型 [完整性约束条件…] AFTER 字段名;
3. 删除字段
ALTER TABLE 表名 DROP 字段名;
4. 修改字段
ALTER TABLE 表名 MODIFY 字段名 数据类型 [完整性约束条件…]; 改字段类型和约束条件
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…]; 改字段名
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…]; 除了改了字段名,还改了数据类型、完整性约束等等的内容
5. 增长约束(针对已有的主键增长auto_increment) mysql> alter table student10 modify id int(11) not null primary key auto_increment; ERROR 1068 (42000): Multiple primary key defined mysql> alter table student10 modify id int(11) not null auto_increment; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 6. 对已经存在的表增长复合主键 mysql> alter table service2 -> add primary key(host_ip,port); 7. 增长主键 mysql> alter table student1 -> modify name varchar(10) not null primary key; 8. 增长主键和自动增加 mysql> alter table student1 -> modify id int not null primary key auto_increment; 9. 删除主键 a. 删除自增约束 mysql> alter table student10 modify id int(11) not null; b. 删除主键 mysql> alter table student10 -> drop primary key;
复制表:
语法:复制表结构+记录 (key不会复制: 主键、外键和索引)
mysql> create table new_service select * from service;
只复制表结构,不要数据
mysql> select * from service where 1=2;
行记录操做
1.插入
插入完整数据(顺序插入) 语法一: INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n); #指定字段来插入数据,插入的值要和你前面的字段相匹配
语法二: INSERT INTO 表名 VALUES (值1,值2,值3…值n); #不指定字段的话,就按照默认的几个字段来插入数据
插入查询结果 语法: INSERT INTO 表名(字段1,字段2,字段3…字段n) SELECT (字段1,字段2,字段3…字段n) FROM 表2 WHERE …; #将从表2里面查询出来的结果来插入到咱们的表中,可是注意查询出来的数据要和咱们前面指定的字段要对应好
2.更新
语法: UPDATE 表名 SET 字段1=值1, #注意语法,能够同时来修改多个值,用逗号分隔 字段2=值2, WHERE CONDITION; #更改哪些数据,经过where条件来定位到符合条件的数据
3.删除
语法: DELETE FROM 表名 WHERE CONITION; #删除符合条件的一些记录 DELETE FROM 表名;若是不加where条件,意思是将表里面全部的内容都删掉,可是清空全部的内容,通常咱们用truncate ,可以将id置为零,delete不能将id置零,再插入数据的时候,会按照以前的数据记录的id数继续递增
4.查询(写在下一节,由于查询的知识点多)
5.受权
#受权表 user #该表放行的权限,针对:全部数据,全部库下全部表,以及表下的全部字段 db #该表放行的权限,针对:某一数据库,该数据库下的全部表,以及表下的全部字段 tables_priv #该表放行的权限。针对:某一张表,以及该表下的全部字段 columns_priv #该表放行的权限,针对:某一个字段
#受权:对文件夹,对文件,对文件某一字段的权限 查看帮助:help grant 经常使用权限有:select,update,alter,delete all能够表明除了grant以外的全部权限
#建立用户 create user 'egon'@'1.1.1.1' identified by '123'; create user 'egon'@'192.168.1.%' identified by '123'; create user 'egon'@'%' identified by '123';
#针对全部库的受权:*.* grant select on *.* to 'egon1'@'localhost' identified by '123'; #只在user表中能够查到egon1用户的select权限被设置为Y #针对某一数据库:db1.* grant select on db1.* to 'egon2'@'%' identified by '123'; #只在db表中能够查到egon2用户的select权限被设置为Y #针对某一个表:db1.t1 grant select on db1.t1 to 'egon3'@'%' identified by '123'; #只在tables_priv表中能够查到egon3用户的select权限
select * from tables_priv where user='egon4'\G 查看权限 tables_priv能够修改为对应的表
#删除权限 revoke select on db1.* from 'egon'@'%';
三.单表查询
语法:
select * from,这个select * 指的是要查询全部字段的数据。
SELECT distinct 字段1,字段2... FROM 库名.表名 #from后面是说从库的某个表中去找数据,mysql会去找到这个库对应的文件夹下去找到你表名对应的那个数据文件,找不到就直接报错了,找到了就继续后面的操做 WHERE 条件 #从表中找符合条件的数据记录,where后面跟的是你的查询条件 GROUP BY field(字段) #分组 HAVING 筛选 #过滤,过滤以后执行select后面的字段筛选,就是说我要肯定一下须要哪一个字段的数据,你查询的字段数据进行去重,而后在进行下面的操做 ORDER BY field(字段) #将结果按照后面的字段进行排序 LIMIT 限制条数 #将最后的结果加一个限制条数,就是说我要过滤或者说限制查询出来的数据记录的条数
重点中的重点:关键字的执行优先级 from 找到表:from where 拿着where指定的约束条件,去文件/表中取出一条条记录 group by 将取出的一条条记录进行分组group by,若是没有group by,则总体做为一组 having 将分组的结果进行having过滤 select 执行select distinct 去重 order by 将结果按条件排序:order by limit 限制结果的显示条数
1.简单查询
SELECT * FROM employee; #不推荐用* 慢
SELECT DISTINCT post FROM employee; 去重
SELECT name, salary*12 FROM employee; 四则运算查询
SELECT name, salary*12 AS Annual_salary FROM employee; #as + 新字段名,就是起一个别名的意思
CONCAT() 函数用于链接字符串 SELECT CONCAT('姓名: ',name,' 年薪: ', salary*12) AS Annual_salary 按照本身规定的格式查询
SELECT CONCAT('姓名: ',name,' 年薪: ', salary*12) AS Annual_salary,CONCAT('性别:',sex) from employee;#还能够这样分红两列
CONCAT_WS() 第一个参数为分隔符来进行字符串拼接 SELECT CONCAT_WS(':',name,salary*12) AS Annual_salary #经过冒号来将name和salary链接起来
SELECT CONCAT(name,':',salary*12) AS Annual_salary from employee; 能实现跟上面同样的效果
结合CASE语句:结合条件来对查询的结果进行一些加工操做 SELECT ( CASE WHEN NAME = 'egon' THEN NAME WHEN NAME = 'alex' THEN CONCAT(name,'_BIGSB') ELSE concat(NAME, 'SB') END ) as new_name,sex FROM employee;
where约束
where语句中可使用:
1. 比较运算符:> < >= <= <> !=
2. between 80 and 100 值在80到100之间
3. in(80,90,100) 值是80或90或100
4. like 'egon%'
pattern能够是%或_,
%表示任意多字符
_表示一个字符
5. 逻辑运算符:在多个条件直接可使用逻辑运算符 and or not
#1:单条件查询 SELECT name FROM employee WHERE post='sale'; #注意优先级,咱们说where的优先级是否是比select要高啊,因此咱们的顺序是先找到这个employee表,而后按照post='sale'的条件,而后去表里面select数据 #2:多条件查询 SELECT name,salary FROM employee WHERE post='teacher' AND salary>10000; #3:关键字BETWEEN AND 写的是一个区间 SELECT name,salary FROM employee WHERE salary BETWEEN 10000 AND 20000; #就是salary>=10000 and salary<=20000的数据 SELECT name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000; #加个not,就是不在这个区间内,薪资小于10000的或者薪资大于20000的,注意没有等于, #4:关键字IS NULL(判断某个字段是否为NULL不能用等号,须要用IS) 判断null只能用is SELECT name,post_comment FROM employee WHERE post_comment IS NULL; SELECT name,post_comment FROM employee WHERE post_comment IS NOT NULL; SELECT name,post_comment FROM employee WHERE post_comment=''; 注意''是空字符串,不是null,两个是不一样的东西,null是啥也没有,''是空的字符串的意思,是一种数据类型,null是另一种数据类型 ps: 执行 update employee set post_comment='' where id=2; 再用上条查看,就会有结果了 #5:关键字IN集合查询 SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ; #这样写是否是太麻烦了,写一大堆的or,下面咱们用in这个简单的写法来搞 SELECT name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ; SELECT name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ; #6:关键字LIKE模糊查询,模糊匹配,能够结合通配符来使用 通配符’%’ #匹配任意全部字符 SELECT * FROM employee WHERE name LIKE 'eg%'; 通配符’_’ #匹配任意一个字符 SELECT * FROM employee WHERE name LIKE 'al__'; #注意我这里写的两个_,用1个的话,匹配不到alex,由于al后面还有两个字符ex。
Goup by 分组
单独使用GROUP BY关键字分组 SELECT post FROM employee GROUP BY post; 注意:咱们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其余相关信息,须要借助函数 GROUP BY关键字和GROUP_CONCAT()函数一块儿使用,好比说我想按部门分组,每一个组有哪些员工,都显示出来,怎么搞 SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;#按照岗位分组,并查看组内全部成员名,经过逗号拼接在一块儿 SELECT post,GROUP_CONCAT(name,':',salary) as emp_members FROM employee GROUP BY post; GROUP BY通常都会与聚合函数一块儿使用,聚合是什么意思:聚合就是将分组的数据汇集到一块儿,合并起来搞事情,拿到一个最后的结果 select post,count(id) as count from employee group by post;#按照岗位分组,并查看每一个组有多少人,每一个人都有惟一的id号,我count是计算一下分组以后每组有多少的id记录,经过这个id记录我就知道每一个组有多少人了
聚合函数
#强调:聚合函数聚合的是组的内容,如果没有分组,则默认一组 示例: SELECT COUNT(*) FROM employee; #count是统计个数用的 SELECT COUNT(*) FROM employee WHERE depart_id=1; #后面跟where条件的意思是统计一下知足depart_id=1这个的全部记录的个数 SELECT MAX(salary) FROM employee; #max()统计分组后每组的最大值,这里没有写group by,那么就是统计整个表中全部记录中薪资最大的,薪资的值 SELECT MIN(salary) FROM employee; SELECT AVG(salary) FROM employee; SELECT SUM(salary) FROM employee; SELECT SUM(salary) FROM employee WHERE depart_id=3;
having过滤
HAVING与WHERE不同的地方在于!!!!!!
having的语法格式和where是如出一辙的,只不过having是在分组以后进行的进一步的过滤,where不能使用聚合函数,having是可使用聚合函数的
#!!!执行优先级从高到低:where > group by > having #1. Where 发生在分组group by以前,于是Where中能够有任意字段,可是绝对不能使用聚合函数。 #2. Having发生在分组group by以后,于是Having中可使用分组的字段,没法直接取到其余字段,having是可使用聚合函数
需求:统计各部门年龄在30岁及以上的员工的平均薪资,而且保留平均工资大于10000的部门
答案:select post,avg(salary) as new_sa from employee where age>=30 group by post having avg(salary) > 10000;
having只能在group by后面运行
去重:select distinct post from employee; 注意distinct去重要写在查询字段的前面
查询排序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;
限制查询记录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条
有时须要查询出某个字段不重复的记录,这时可使用mysql提供的distinct这个关键字来过滤重复的记录,可是实际中咱们每每用distinct来返回不重复字段的条数(count(distinct id)),其缘由是distinct只能返回他的目标字段,而没法返回其余字段,distinct 想写在其余字段后面须要配合聚合函数来写。 mysql> select id,count(distinct post) from employee; ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause 报错了:是由于distinct不能返回其余的字段,只能返回目标字段 mysql> select count(distinct post) from employee;
有时须要查询出某个字段不重复的记录,这时可使用mysql提供的distinct这个关键字来过滤重复的记录,可是实际中咱们每每用distinct来返回不重复字段的条数(count(distinct id)),其缘由是distinct只能返回他的目标字段,而没法返回其余字段,distinct 想写在其余字段后面须要配合聚合函数来写。 mysql> select id,count(distinct post) from employee; ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause 报错了:是由于distinct不能返回其余的字段,只能返回目标字段 mysql> select count(distinct post) from employee;
正则表达式查询
#以前咱们用like作模糊匹配,只有%和_,局限性比较强,因此咱们说一个正则,以前咱们是否是学过正则匹配,你以前学的正则表达式均可以用,正则是通用的
SELECT * FROM employee WHERE name REGEXP '^ale'; SELECT * FROM employee WHERE name REGEXP 'on$'; SELECT * FROM employee WHERE name REGEXP 'm{2}';
查看全部员工中名字是jin开头,n或者g结果的员工信息
select * from employee where name regexp '^jin.*[g|n]$';
四.多表查询常见的三种方式
多表链接查询
内链接:只链接匹配的行
select * from employee,department where employee.dep_id=department.id;
查出技术部的员工的名字
select employee.name from employee,department where employee.dep_id=department.id and department.name='技术';
缺点:逻辑不太清晰
外连接之左链接:优先显示左表所有记录
#以左表为准,即找出全部员工信息,固然包括没有部门的员工 #本质就是:在内链接的基础上增长左边有右边没有的结果 #注意语法:
select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
外连接之右链接:优先显示右表所有记录
#以右表为准,即找出全部部门信息,包括没有员工的部门 #本质就是:在内链接的基础上增长右边有左边没有的结果 mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
全外链接:在内链接的基础上增长左边有右边没有的和右边有左边没有的结果 #注意:mysql不支持全外链接 full JOIN #强调:mysql可使用此种方式间接实现全外链接 select * from employee left join department on employee.dep_id = department.id union select * from employee right join department on employee.dep_id = department.id;
#示例1:之内链接的方式查询employee和department表,而且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门 select employee.name,department.name from employee inner join department on employee.dep_id = department.id where age > 25; #示例2:之内链接的方式查询employee和department表,而且以age字段的升序方式显示 select employee.id,employee.name,employee.age,department.name from employee,department where employee.dep_id = department.id and age > 25 order by age asc;
select name from employee where dep_id = (select id from department where name='技术');
表示一条id=200的数据,而后咱们经过员工表来查询dep_id=这条数据做为条件来查询员工的name
子查询:
#1:子查询是将一个查询语句嵌套在另外一个查询语句中。 #2:内层查询语句的查询结果,能够为外层查询语句提供查询条件。 #3:子查询中能够包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字 #4:还能够包含比较运算符:= 、 !=、> 、<等
一、带IN关键字的子查询
#查询员工平均年龄在25岁以上的部门名,能够用连表,也能够用子查询,咱们用子查询来搞一下 select id,name from department where id in (select dep_id from employee group by dep_id having avg(age) > 25); #连表来搞一下上面这个需求 select department.name from department inner join employee on department.id=employee.dep_id group by department.name having avg(age)>25; 总结:子查询的思路和解决问题同样,先解决一个而后拿着这个的结果再去解决另一个问题,连表的思路是先将两个表关联在一块儿,而后在进行group by啊过滤啊等等操做,二者的思路是不同的
#查看技术部员工姓名 select name from employee where dep_id in (select id from department where name='技术'); #查看不足1人的部门名(子查询获得的是有人的部门id) select name from department where id not in (select distinct dep_id from employee);
二、带比较运算符的子查询
select name,age from emp where age > (select avg(age) from emp); ps:查询年龄大于平均年的的人
三、带EXISTS关键字的子查询
EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。而是返回一个真假值。True或False
当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询。还能够写not exists,和exists的效果相反。
select * from employee -> where exists -> (select id from department where id=200);
五.pymysql模块操做数据库
#安装 pip3 install pymysql
import pymysql
conn = pymysql.connect(
host='localhost',
port=3306,
user='root',
password='wang',
database='db1',
charset='utf8'
)
cursor = conn.cursor(pymysql.cursors.DictCursor) #建立游标以字典的形式展现,不写值默认是元组
sql = 'select * from department;' #写sql
ret = cursor.execute(sql) #执行sql
print('受影响的行数>>> ',ret)
#print(cursor.fetchall()) #打印全部
# cursor.scroll(3,mode='absolute') #绝对位置移动光标
# cursor.scroll(3,mode='relative') #相对位置移动光标
print(cursor.fetchone()) #打印一行
#cursor.commit() #至关于mysql里面的flush privileges 增删改须要commit才能生效
未完待续......