数据存储演变史
数据存储的演变其实是对数据的存储格式和数据存储的位置进行演变的
过程:
1.文本文件
基于我们之前所学,数据要想永久保存,都是保存于文件中,毫无疑问,一个文件仅仅只能存在于某一台机器上。
如果我们暂且忽略直接基于文件来存取数据的效率问题,并且假设程序所有的组件都运行在一台机器上,那么用文件存取数据,并没有问题。
但是事实上它会存在许多问题:
·文件路劲不一致 C:\a.txt D:\aaa\b.txt E:\ccc.txt
·数据格式不一致 jason|123 tony$123 kevin@123
2.软件开发目录规范
规定了数据文件的大致位置:db文件夹
针对数据格式还是没有完全统一,比如统一json文件但是内部键值对不同
3.数据库服务
统一了存取位置,也统一了数据格式(完全统一)
数据软件应用史
1.单机游戏
不同计算机上的相同程序,数据无法共享
数据库服务全部在本地完成
2.网络游戏
不同计算机的相同程序,数据可以共享
数据库服务单独在网络上架设
数据库的本质
'数据库' 这三个字在不同的角度下描述的意思是不一样的
1.站在底层原理的角度
数据库指的是专用于操作数据的进程
即:运行在内存中的代码
2.站在现实应用的角度
数据库指的是拥有操作界面的应用程序
即:用于操作数据进程的快捷界面
我们不做特殊说明的情况下提出的数据库其实是在指数据库软件
我们也称数据库软件本质是一款cs架构的应用程序
即:所有的程序员理论上都可以编写>>>:市面上已经有许多数据库软件了
数据库的分类
1.关系型数据库
·数据的组织方式有明确的表结构
·表与表之间可以建立代码层面的关系
'''
MySQL、PostgreSQL、MariaDB、Oracle、sqlite、db2、sql、server
MySQL:开源,使用最为广泛、入门必学
PostgreSQL:开源,支持二次开发
MariaDB:开源,与MySQL是同一个人写的,用法极其相似
Oracle:收费,安全性非常高,主要用于银行各大重要机关
sqlite:小型数据库,主要用于本地色测试
'''
2.非关系型数据库
·数据的组织方式没有明确的表结构,是以K:V键值对的形式组织的
·数据之间无法直接建立代码层面的关系
'''
redis、mongoDB、memcache
redis:目前最火,使用频率最高,是一个缓存型数据库
mongoDB:稳定型数据库,最像关系型的非关系型,主要用于爬虫、大数据
memcache:已经被redis淘汰
'''
数据库的作用
1.实现数据共享
数据共享包含所有用户可同时存取数据库中的数据,也包括用户可以用各种方式通过接口使用数据库,并提供数据共享。
2.减少数据的冗余度
同文件系统相比,由于数据库实现了数据共享,从而避免了用户各自建立应用文件。减少了大量重复数据,减少了数据冗余,维护了数据的一致性。
3.保持数据的独立性
数据的独立性包括逻辑独立性(数据库中数据库的逻辑结构和应用程序相互独立)和物理独立性(数据物理结构的变化不影响数据的逻辑结构)。
4.数据实现集中控制
文件管理方式中,数据处于一种分散的状态,不同的用户或同一用户在不同处理中其文件之间毫无关系。利用数据库可对数据进行集中控制和管理,并通过数据模型表示各种数据的组织以及数据间的联系。
5.数据一致性和可维护性
以确保数据的安全性和可靠性:主要包括:安全性控制、完整性控制、并发控制,使在同一时间周期内,允许对数据实现多路存取,又能防止用户之间的不正常交互作用。
6.故障恢复
由数据库管理系统提供一套方法,可及时发现故障和修复故障,从而防止数据被破坏。数据库系统能尽快恢复数据库系统运行时出现的故障,可能是物理上或是逻辑上的错误。比如对系统的误操作造成的数据错误等。
MySQL数据库简介
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司
MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一
1.MySQL版本问题
5.6X:前几年使用频率最高版本
5.7X:最近尝试迁移的版本问题
8.0X:最新版,功能很强大,但是线上环境几乎不用(本地自己用非常好用)
'''虽然版本上有区别,但是操作几乎没有区别,主要体现在底层运作'''
2.下载与安装
1.访问官网
2.点击DOWNLOADS
3.点击GPL
4.点击community server
5.点击archives
6.点击download
3.解压安装
上述方式下载的压缩包里含有服务端和客户端 支持本地操作
4.主要文件介绍
bin文件夹
mysqld.exe服务端 mysql.exe客户端
data文件夹
存取数据
my-default.ini
默认配置文件
基本使用
1.首先切换到mysql的所在盘
C:\Users\***>D:
2.查找MySQL文件位置
D:\>cd mysql-5.6.44-winx64\bin
3.输入MySQL启动文件
D:\mysql-5.6.44-winx64\bin>mysqld
4.再开启新的从cmd窗口
作为客户端使用,直接敲mysql回车是游客模式
5.用户密码登录
mysql -u用户名 -p密码(mysql默认密码为空)
6.使用游客登录和使用管理员密码登录是有区别的
管理员用户密码登录:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.00 sec)
游客登录:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| test |
+--------------------+
2 rows in set (0.00 sec)
7.退出
exit、quit
系统服务制作
1.如何解决每次都需要切换路径查找文件的缺陷
添加环境变量(D:\mysql-5.6.44-winx64\bin)
2.将mysql服务端制作成系统服务(随着计算机的开启而启动 关闭而结束)
·以管理员身份打开cmd窗口
·执行系统服务命令
mysqld --install
Service successfully installed.
·启动服务端
1.右键直接点击启动
2.命令启动
net start mysql
'''
1.查看系统服务的命令
services.msc
2.关闭mysql服务端
net stop mysql
3.移除系统服务
1.先确保服务已经关闭
2.执行移除命令
mysqld --remove
'''
密码相关操作
1.修改密码
mysqladmin命令
通用方式: # 直接在cmd中写
mysqladmin -u用户名 -p原密码 password 新密码
'Warning: Using a password on the command line interface can be insecure.'提示这个不是报错,而是提醒你=我们此时这么更改密码是不安全的,密码暴露在了外面
第一次修改:mysqladmin -uroot -p password 123,首次修改因为mysql默认密码为空所以-p后面什么都没有
第二次修改:mysqladmin -uroot -p123 password 321
偏门方式(有些版本无法使用): 需要先登录,更改的是当前登录的这个账号的密码
set password=PASSWORD('新密码');引号必须要加
2.忘记密码
直接重装\拷贝对应文件(user.frm、user.MYD、user.MYI)
了解知识:
先关闭服务端 然后以不需要校验用户身份的方式启动 再修改 最后再安装正常方式启动
1.net stop mysql
2.mysqld --skip-grant-tables(跳过授权表,不校验用户的密码,可以直接进去)
3.mysql -uroot -p
4.update mysql.user set password=password(123) where Host='localhost' and User='root';
5.net stop mysql
6.net start mysql
SQL和NoSQL
数据库的服务端支持各种语言充当客户端
MySQL服务端仅仅是用来管理数据的,没有其他操作
eg:以MySQL服务端为例
MySQL客户端、python代码编写的客户端、java代码编写的客户端
为了能够兼容所有类型的客户端 有两种策略
1.服务端兼容
不合理 消耗数据库服务端资源!!!
2.制定统一标准
SQL语句、NoSQL语句
SQL与NoSQL
SQL语句的意思是操作关系型数据库的语法
NoSQL语句的意思操作非关系型数据库的语法
ps:SQL有时候也用来表示关系型数据库 NoSQL也用来表示非关系型数据库
基本SQL语句
1.SQL语句结束符是分号
;
2.取消SQL语句的执行
\c
3.将查询结果进行按列打印,可以使每个字段打印到单独的行
\G
4.基本常用语句
show databases; 查看所有的数据库
show tables; 查看所有的表
select * from mysql.user; 查看user表里面所有的记录
---------------------------针对库的基本SQL------------------------------
1.新增库
create database 库名;
2.查看库
show databases;
show create database 库名;
3.修改库名
alter database 库名 charset='gbk';
4.删除库
drop database 库名;
---------------------------针对表数据的基本SQL语句------------------------
'''对表进行操作的时候,首先得先选择一个库,在库的下面去操作表'''
use 库名
1.新增表
create table 表(字段 字段类型,...); 创建表的时候至少要写一条字段
2.查看表
show tables; 查看所有的表
show create table 表名; 查看表结构,里面含有存储引擎,字符编码
describle 表名;等同于(desc 表名),查看出一个完整的表结构
3.修改表的名字
alter table 旧表名 rename 新表名;
rename table 表名 to 新表名;
4.删除表
drop table 表名;
5.新增字段
alter table 表名 add 字段名 字段类型(数字) 约束条件;
alter table 表名 add 字段名 字段类型(数字) 约束条件 after 已有的字段; 在指定字段后添加新字段,使用关键字after
alter table 表名 add 字段名 字段类型(数字) 约束条件 first; 在表的最前面添加字段,使用关键字first
6.添加一列、删除一列
alter table 表名 add column(字段 字段类型(数字))
alter table 表名 drop column(字段 字段类型(数字))
7.删除字段
alter table 表名 drop 字段名;
8.复制表
复制表的结构和记录 (key不会复制:主键key 外键key及索引key都不会复制)
create table new_service select * from service;
解释:创建一个new_service表 内容为service表里的内容
只拷贝表结构(不包含键)
create table new2_service select * from service where 1=2;
解释:这里呢是创建一个条件判定为假的条件 1肯定不等于2 所以只复制了表的框架 没有键也没有内容
拷贝表的结构并且包含键
create table new3service like service;
解释:运用到like关键字 使新表的表结构完全一样 但是没有拷贝内容。
9.格式化表
truncate 表名;
---------------------------争对记录的基本SQL语句------------------------------
1.增
insert into 表名 value(数据,数据),(数据,数据);
一条大数据内,每个小数据之间用逗号隔开,每个大数据使用一个括号包起来。然后用逗号隔开。一次性可以插入一条数据也可以插入多条数据
2.查找
select * from 表名; 查看表中所有字段
select 字段1,字段2 from 表名;
如果表中内容过多,出现错乱,可以使用'\G'查看表数据
3.修改
update 表名 set 字段名=新数据 where 筛选条件;
4.删除
delete from 表名; 删除表中所有的数据
delete from 表名 where 筛选条件; 按照条件删除数据
字符编码与配置文件
1.\s 查看数据库基本信息
2.my-default.ini 它是windows下MySQL默认的配置文件
拷贝上述文件并且重命名为my.ini,必须是以my开头的mysql才能识别
3.由于5.6版本编码不统一 会造成乱码 我们需要统一修改>>>:utf8
将my.ini里的内容修改为:
'''
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
'''
注意如果配置文件涉及到了mysqld相关的配置修改 那么需要重启服务端才可以生效
4.在配置文件中的mysql下提前写好用户名和密码,之后直接用mysql登录就好,不需要再输用户名和密码
存储引擎
1.针对相同的数据采用的不同的存取策略
2.show engines;
3.需要掌握的存储引擎
MyISAM
MySQL5.5及之前版本默认的存储引擎
存取数据的速度 快 但是功能较少 安全性较低
InnoDB
MySQL5.5之后版本默认的存储引擎
存取数据的速度没有MyISAM快 但是支持事务、行锁、外键等诸多功能
安全性较高
Memory
基于内存的存储引擎 存取数据极快 但是断电立刻丢失
BlackHole
黑洞 任何写进去的数据都会立刻丢失 类似于垃圾站
4.不同存储引擎之间底层文件的区别
create table t1(id int) engine=innodb;
create table t2(id int) engine=MyISAM;
create table t3(id int) engine=Memory;
create table t4(id int) engine=BlackHole;
创建表其实就是在mysql文件夹下面的data文件夹里的某个数据库文件夹里创建了文件
不同的存储引擎产生的文件也是不一样的
InnoDB
.frm 表结构
.ibd 表数据、表索引(加快数据查询)
MyISAM
.frm 表结构
.MYD 表数据
.MYI 表索引(加快数据查询)
Memory
.frm 表结构
BlackHole
.frm 表结构
创建表的完整语法
create table 表名(
字段名1 字段类型(数字) 约束条件1 约束条件2,
字段名2 字段类型(数字) 约束条件,
字段名3 字段类型(数字) 约束条件,
字段名4 字段类型(数字) 约束条件
)ENGINE=存储引擎 DEFAULT CHARSET=utf8;
'''
1.字段名和字段类型是必须要写的(至少写一个)
2.数字跟约束条件是可选的(可有可无)
3.约束条件可以写多个,空格隔开
4.最后一个字段的结尾不能加逗号
'''
字段类型
1.字段类型之整形
tinyint、smallint、int、bigint
整形涉及到一个负号的知识点:如果设置的字段类型对应字段的输入值的时候,输入的数超出了原本类型的取值范围,那么就会产生数据失真,会字动填写为该字段类型的俩个边界值,那么此时就没有了实际的意义,并且,上述整形类型默认都会带有负号
例子:
insert into t6 values(-129),(256);
mysql> desc t6;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id | tinyint(4) | YES | | NULL | |
+-------+------------+------+-----+---------+-------+
1 row in set (0.01 sec)
mysql> select * from t6;
+------+
| id |
+------+
| -128 |
| 127 |
+------+
2 rows in set (0.00 sec)
[自定义移除负号]
使用约束条件:unsigned,他的作用是可以将负号去掉
我们移除负号是因为插入的数据超出数据类型的范围的话,那么插入的数据就没有意义,因此在这种情况下我们应该让它报错,不应该叫它插入数据进去
方式一:命令临时修改
set session sql_mode = 'strict_trans_tables' 当前客户端操作界面有效
set global sql_mode = 'strict_trans_tables' 服务端不重启的情况下就会一直有效
方式二:配置文件永久有效
[mysqld]
sql_mode='STRICT_TRANS_TABLES'
2.字段类型之浮点类型
float、double、decimal
三者都可以存储浮点型数据,但是各自的精确度不一致
使用方式:
float(255,30)
double(255,30)
decimal(65,30)
括号里第一个数字是总共有多少位,第二个数字表示的是小数占多少位
精确度的顺序:
float < double < decimal
一般情况下float就够了,如果想要精确度更完美一点的话,可以使用字符串来代替
3.字段类型之字符类型
char(4) -----称之为定长
最大只能存储四个字符,如果超过范围则直接报错
如果不超出范围,则用空格填充至四个字符
例如:如果要存储 'a',那么它就会被存储为'a空格空格空格'
使用char(4)的时候,存进去的时候确实是'a空格空格空格',但是在取出来的时候会自动删掉这三个空格
然后在读取的时候又会自动将填充的空格移除,如果想取消该机制,需要
sql_mode set global sql_mode='strict_trans_tables,pad_char_to_full_length';
varchar(4) --称之为变长
最大只能存储四个字符,如果超过范围则直接报错
如果不超出范围,则有几位就存几位
统计字符串中的长度:char_length()
它们俩之间的区别:
char
整存整取 速度快
浪费存储空间
varchar
节省存储空间
存取数据的速度慢于char
"""
char(4)
在硬盘上存储:a空格空格空格son空格jacktom空格lili
取得时候就是4个4个拿
varchar(4)
在硬盘上存储:asonjacktomlili
拿的时候就不对了
1bytes+a1bytes+son1bytes+jack1bytes+tom1bytes+lili
存取数据都需要操作报头(耗时)
"""
两者使用频率都很高 现在默认很多时候是varchar
3.字段类型之枚举和集合
枚举(多选一)
mysql> create table t15(
-> id int,
-> name varchar(32),
-> gender enum('male','female')
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> desc t15;
+--------+-----------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-----------------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(32) | YES | | NULL | |
| gender | enum('male','female') | YES | | NULL | |
+--------+-----------------------+------+-----+---------+-------+
3 rows in set (0.05 sec)
mysql> insert into t15 values(1,'zuzu','女');
ERROR 1265 (01000): Data truncated for column 'gender' at row 1
mysql> insert into t15 values(1,'zuzu','female');
Query OK, 1 row affected (0.04 sec)
总结:提前规定好到底将来可以插入哪些数据
集合(多选多)
create table t16(
id int,
name varchar(32),
hobbies set('read','run','music','rap')
);
mysql> insert into t16 values(1,'titi','read,run');
Query OK, 1 row affected (0.04 sec)
mysql> insert into t16 values(1,'xixi','read');
Query OK, 1 row affected (0.04 sec)
mysql> select * from t16;
+------+------+----------+
| id | name | hobbies |
+------+------+----------+
| 1 | zuzu | read,run |
| 1 | titi | read,run |
| 1 | xixi | read |
+------+------+----------+
3 rows in set (0.00 sec)
总结:提前规定好到底将来可以插入哪些数据,可以选择多个,但是只能是提前录入好的
4.字段类型之日期类型
date(年月日)、datetime(年月日时分秒)、time(时分秒)、year(年份)
mysql> create table t17(
-> id int,
-> name varchar(32),
-> birth date,
-> reg_time datetime,
-> study_time time,
-> join_time year
-> );
Query OK, 0 rows affected (0.07 sec)
mysql> insert into t17 values(1,'jason','2022-8-15','1999-10-02 08:13:11','11:11:11','1995');
Query OK, 1 row affected (0.03 sec)
mysql> select * from t17;
+------+-------+------------+---------------------+------------+-----------+
| id | name | birth | reg_time | study_time | join_time |
+------+-------+------------+---------------------+------------+-----------+
| 1 | jason | 2022-08-15 | 1999-10-02 08:13:11 | 11:11:11 | 1995 |
+------+-------+------------+---------------------+------------+-----------+
1 row in set (0.00 sec)
字段类型之约束条件
(1).unsigned-----取消负号
id int unsigned
'作用于整形,去掉负数'
(2).zerofull-----零填充
id int zerofill
'作用于整形,不超出范围0填充'
(3).not null-----非空
name varchar(32) not null
'非空不一定是有值,比如说空字符串'
(4).default------默认值
name varchar(32) default 'jason'
'给一些字段提前设置一些默认值,如果后期我们添加数据的时候没有给值,那就使用默认值'
(5).unique-------唯一
'单列唯一' id int unique
'联合唯一' unique(host,port)
可以分别单独给俩个联合的字段分别添加重复数据,但是如果俩个字段一起重复添加数据的话就会报错
(6).primary key-----主键
我们在建立数据库的时候,需要为每张表指定一个主键,所谓主键就是能够唯一标识表中某一行的属性或属性组,一个表只能有一个主键,因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。所以数据库在设计时,主键起到了很重要的作用。
主键特点:
单从约束角度上而言主键等价于非空且唯一 not null unique。
InnoDB存储引擎规定一张表必须有且只有一个主键
·如果创建的表中没有主键也没有非空且唯一的字段,那么InnoDB存储引擎会自动采用一个隐藏的字段作为主键(主键可以加快数据查询:新华字典的目录)。
·如果创建的表中没有主键但是有非空且唯一的字段,那么InnoDB存储引擎会自动将该字段设施为主键
创建表的时候都应该有一个'id'字段,并且该字段应该作为主键。
争对主键有且只有一个的说法
单列主键
id int primary key
联合主键:
primary key(sid, nid)
实操:
mysql> alter table t2 add primary key(nid,sid);
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| nid | int(11) | NO | PRI | NULL | |
| sid | int(11) | NO | PRI | NULL | |
| uid | int(11) | NO | UNI | NULL | |
| name | varchar(32) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.03 sec)
没有办法更新主键,主键需先删除才能增加
alter table [表名] drop primary key;
(7)auto_increment-----自增
当对应的字段不给值,或者说给默认值或者给null的时候,会自动的被系统触发,系统会从当前字段中已有的最大值再进行+1操作,得到一个新的再不同的字段,自增长字段必须是数字,而且是整型。
自增长如果对应的字段输入了值,那么自增长失效;但是下一次还是能够正确的自增长(从最大值+1)。
该约束条件不能单独使用,必须配合键使用。
主键字段不需要添加,自动生成,只需要去添加数据就好。
这里需要注意的主键只会向后增加,不管中途是怎么操作了数据,它只会向后增加,例如:如果删除了id=3的数据,接下来在向里面添加数据它也是从4开始,那么这样也好,如果中途删了数据,我们就会从id号上查看到,总而言之就是自增不会因为删除的操作而进行回退,只会向后增加
'''
针对自增以上的这个特性,如果我们非要重置,那么可以使用格式化表
truncate 表名; 它的作用就是删除表数据并重置主键值
'''
(7)forign key-----外键
专门用于记录表与表之间'数据'的关系
数据的关系有四种
一对多关系、多对多关系、一对一关系、没有关系
表数据关系的判定 >>>: '换位思考'
针对员工表和部门表判断数据关系
1.先站在员工表的角度
问:一条员工数据能否对应多条部门数据
翻:一名员工能否属于多个部门
答:不可以
2.再站在部门表的角度
问:一条部门数据能否对应多条员工数据
翻:一个部门能否拥有多个员工
答:可以
完成换位思考之后得出的答案 一个可以一个不可以
那么表关系就是"一对多"
部门是一 员工是多
针对'一对多'的关系 外键字段建在多的一方
'''
ps:没有多对一 统一称为'一对多
涉及到外键字段,先写普通字段,然后再写外键字段
''''
表中数据关系(一对多关系、多对多关系、一对一关系、没有关系)
1.创建表的时候需要先创建被关联的表(没有外键) 然后再是关联表(有外键)
2.插入表数据的时候 针对外键字段只能填写被关联表字段已经出现过的数据值
3.被关联字段无法修改和删除
有点不太好 操作限制性太强
"""
级联更新、级联删除
被关联数据一旦变动 关联的数据同步变动
on update cascade # 级联更新
on delete cascade # 级联删除
级联更新、级联删除
被关联数据一旦变动 关联的数据同步变动
"""
在实际工作中 很多时候可能并不会使用外键
因为外键增加了表之间的耦合度 不便于单独操作 资源消耗增加
我们为了能够描述出表数据的关系 又不想使用外键
自己通过写SQL 建立代码层面的关系
如果表少的话使用外键会方便一点,但是如果表多的话就不建议使用外键了,那样的话就会乱
(1).一对多关系
"""针对'一对多'的关系 外键字段建在多的一方"""
(2).多对多关系
"""针对多对多表关系 外键字段不能建在任意一方!需要建立第三张表去通过第三张表连接俩张表"""
(3).一对一关系、没有关系
"""针对'一对一'的表关系 外键字段建在任何一张表都可以 但是建议你建在查询频率较高的表中便于后续查询"""
查询关键字
模糊查询:
关键字 like
%:匹配任意个数的任意字符
_:匹配单个个数的任意字符
group_concat:用来做分组以后,获取除分组依据以外的一些字段,可以是一个也可以是多个,字段与字段之间可以设置一些分割符号
concat:用户分组之前的拼接操作
concat_w:当多个字段链接符相同的情况下推荐使用
分组起别名:
在查看结果的时候可以给字段起别名
select post as '部门',max(salary) as '最高薪资' from emp group by post;
省略as:
select post '部门',max(salary) as '最高薪资' from emp group by post;
as可以省略但是为了语义更加明确建议不要省略
(1).where筛选
'''就是对数据进行筛选'''
例子:
select * from emp where id >=3 and id <=6;
select * from emp where salary =20000 or salary =18000 or salary =17000;
select name,salary from emp where name like '%o%';
(2).group by 分组
'''按照某个指定的条件将单个单个的数据分为一个个的整体,分组之后我们研究的对象应该是以组为单位 不应该再直接获取单个数据项 如果获取了应该直接报错 select后面可以直接填写的字段名只能是分组的依据(其他字段需要借助于一些方法才可以获取)'''
set global sql_mode='strict_trans_tables,only_full_group_by';添加之后展示的只是指认分组的信息
例子:
select post,max(salary) from emp group by post;
select post,avg(salary) from emp group by post;
select post,sum(salary) from emp group by post;
select post,count(id) from emp group by post;
select post,group_concat(name) from emp group by post; # 查询分组之后的部门名称和每个部门下所有的员工姓名
(3).having过滤
'''where与having的功能其实是一样的 都是用来筛选数据
只不过where用于分组之前的筛选 而having用于分组之后的筛选
为了人为的区分 所以叫where是筛选 having是过滤'''
例子:
select post,avg(salary) from emp where age>30 group by post having avg(salary)>10000; # 统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000
关键字的使用顺序:where--group by--having
(4).distinct去重
'''去重的前提是存在一摸一样的数据,如果针对于主键肯定无法去重'''
(5).order by排序
'''关键字需要用在指定字段之后
asc升序(默认)、desc降序 '''
例子:
select * from emp order by salary asc; #默认升序排
select * from emp order by salary desc; #降序排
select * from emp order by age desc; #降序排
(6).limit分页
'''在查看的数据太多情况下,使用分页来限制每次查看数据的数量。'''
用法:
1、limit后只跟一个数字:从头开始展示多少行
select * from emp limit 5; # 从头开始展示5行
2、limit后跟两个数字:第一个数字为起始位,第二个数字为从起始位开始展示多少行
select * from emp limit 5,5; # 从第5行开始展示5行
(7).regexp正则表达式
'''正则表达式:使用一些符号的组合产生一些特殊的含义,然后去字符串中筛选出符合条件的数据'''
例子:
select * from emp where name regexp '^j.*(n|y)$';
(8).exists判断
'''exists关键字表示存在,在使用在使用exists关键字时,内层查询语句不返回查询的记录,而是返回一个真假值,True或False'''
当返回为True时,外层查询语句将进行查询、
返回值为False时,外层查询语句不进行查询。
用法:sql语句 exists(判断语句)
判断语句为True则执行sql语句 如果返回为False则不执行
例子:
select * from emp where exists (select id from emp where id > 3);
解释:括号内判断语句为True有结果则会执行exists前的sql语句
select * from emp where exists (select id from emp where id > 20);
解释:括号内判断语句为False没有结果则不会执行exists前的sql语句
多表查询
思路:
子查询:将一张表的查询结果括号括起来当做另外一条SQL语句的条件
eg:类似以日常生活中解决问题的方式
第一步干什么
第二步基于第一步的结果在做操作 ...
连表操作:先将所有涉及到结果的表全部拼接到一起形成一张大表 然后从大表中查询数据
子查询:
其实就是分布操作 将一张表的查询结果当作另外一条sql语句的查询条件
多表查询连表操作:
1、from 后可跟多个表用逗号隔开,使两张表拼接
eg :from emp1,dep1-----这个现象称为笛卡儿积
2、在涉及到多表操作的时候 为了避免表字段重复
需要在字段名的前面加上表名限制
'''专门的语法:'''
inner join 内连接
只拼接两边都有的字段数据
left join 左连接
以左表为基准 展示所有的数据 没有对应则NULL填充
right join 右连接
以右表为基准 展示所有的数据 没有对应则NULL填充
union 全连接
MySQL可视化软件(Navicat)部署与使用
1.什么是可视化软件?
数据可视化可将文本数字数据转化为可视化的图标,图形和表格通过将重要数据引入中央界面,它被用作创建应用程序/系统性能或操作仪表板的方法。
2.什么是Navicat?
Navicat是一个可多重连接的数据库管理工具,它可以连接到MySQL、Oracle、PostgreSQL、SQLite、SQL Server和/或MariaDB数据库,让数据库管理更加方便。Navicat的功能可以满足专业开发人员的所有需求,对数据库服务器的新手来说学起来也不会很难。有了极完备的图形用户界面(GUI),Nacivat可以简便、安全地创建、组织、访问和共享信息。
Navicat Premium是一套数据库管理工具,结合了其它Navicat成员的功能,Navicat Premium可满足现今数据库管理系统的使用功能,包括存储过程、事件、触发器、函数、视图等。
Nacivat该软件是收费的,但是有许多破解版可以去下载破解版,正式版只能免费试用14天。它虽然很好用,但是为了我们以后提高我们的开发的效率,不能过于依赖这个软件,其实这些软件的底层还是执行的SQL语句来操作数据库的,只不过是将SQL语句封装到了软件内。
3.使用Navicat操作MySQL
连接Navicat(点击连接,点击MySQL),连接名可以不设置,用户名跟密码要设置好,用户名建议设置为root,密码是数据库的密码,点击测试连接,要确保数据库能正常连接
连接成功后,可以看到当前所拥有的数据库,同时右键可以创建新的库,设置库的名称,选择编码(选择MySQL,或者MySQLmb4(支持图像)),
创建新表,右键点击创建新表,增加字段,设置字段类型、外键、主键、自增、null、注释(comment),点击左上的保存输入表的名字。可以查看创表的SQL语句。
创建外键,在创建表的时候上面有外键的设置,然后点击设置关联表的id、当前的库、被关联的表、被关联表的id,在表中填写关联的表的id,保存刷新
点击数据库,右键选择逆向数据库到模型,可以看到所有表的关系。
转储SQL文件,点击数据库右键导出SQL文件,有俩种选项,可以是只导出结构与数据,另一种是仅结构
运行SQL文件,点击数据库右键运行SQL文件,将本地SQL文件导入到MySQL中
python操作MySQL数据库连接
1.python如何操作MySQL?
为了使python连接上数据库,你需要一个驱动,这个驱动是用于与数据库交互的库。
PyMySQL:这是一个使Python连接到MySQL的库,它是一个纯Python库(文件夹)。
PyMySQL是一个纯 Python 实现的 MySQL 客户端操作库,支持事务、存取过程、批量执行,实现增删改查等。
2.什么是PyMySQL?
PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2 中则使用 mysqldb。
PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。
3.PyMySQL的安装
1.命令行输入(下载模块 pymysql)
pip3 install pymysql
2.切换下载的源(仓库)
pip3 install pymysql -i 源地址
下载第三方模块的方式
4.PyMySQL基本使用
import pymysql
# 创建链接
conn = pymysql.connect( # 赋值给 conn连接对象
host='127.0.0.1', # 本地地址
port=3306, # 默认端口
user='root', # 用户名
password='123456', # 密码
database='db1', # 连接数据库名称
charset='utf8mb4' # 编码
)
# 生成一个游标对象(相当于cmd打开mysql中的 mysql>)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 让数据自动组织成字典
# 定义SQL语句
sql = 'select * from userinfo'
# 执行SQL语句
cursor.execute(sql)
# 获取返回结果
res = cursor.fetchall()
print(res)
5.pymysql主要方法
import pymysql
# 创建链接
conn = pymysql.connect( # 赋值给 conn连接对象
host='127.0.0.1', # 本地地址
port=3306, # 默认端口
user='root', # 用户名
password='123456', # 密码
database='db1', # 连接数据库名称
charset='utf8mb4' # 编码
)
# 生成一个游标对象(相当于cmd打开mysql中的 mysql>)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 让数据自动组织成字典
# 定义SQL语句
sql = 'select * from userinfo'
# 执行SQL语句
ret = cursor.execute(sql)
print(ret) # 返回值是执行SQL语句之后受影响的行数
# 获取返回结果
# res = cursor.fetchall() # 列表套字典
# res = cursor.fetchone() # 数据字典
# res = cursor.fetchmany(3) # 列表套字典
print(res)
'''
execute返回值是执行SQL语句之后受影响的行数
fetchall()获取所有的结果
fetchone()获取结果集第一个结果
fetchmany()括号内可以指定获取几个结果集
'''
6.验证光标的存在
import pymysql
# 创建链接
conn = pymysql.connect( # 赋值给 conn连接对象
host='127.0.0.1', # 本地地址
port=3306, # 默认端口
user='root', # 用户名
password='123456', # 密码
database='db1', # 连接数据库名称
charset='utf8mb4' # 编码
)
# 生成一个游标对象(相当于cmd打开mysql中的 mysql>)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 让数据自动组织成字典
# 定义SQL语句
sql = 'select * from userinfo'
# 执行SQL语句
ret = cursor.execute(sql)
print(ret) # 返回值是执行SQL语句之后受影响的行数
# 获取返回结果
res = cursor.fetchall()
res1 = cursor.fetchall()
print(res)
print(res1)
7.二次确认
针对增删改查这四个方法,它们的优先级是不一样的
查---查看数据
增删改---需要去修改数据库
PyMySQL争对'增删改'有一个二次确认的操作
需要在操作数据后面加上conn.commit();
也可以在conn = pymysql.connect()里面添加 autocommit=True,执行增删改自动执行conn.commit()
8.相对移动与绝对移动
'''
相对移动:相对当前位置移动
绝对移动:从起始位置移动
'''
import pymysql
# 创建链接
conn = pymysql.connect( # 赋值给 conn连接对象
host='127.0.0.1', # 本地地址
port=3306, # 默认端口
user='root', # 用户名
password='123456', # 密码
database='db1', # 连接数据库名称
charset='utf8mb4' # 编码
)
# 生成一个游标对象(相当于cmd打开mysql中的 mysql>)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 让数据自动组织成字典
# 定义SQL语句
sql = 'select * from userinfo'
# 执行SQL语句
ret = cursor.execute(sql)
print(ret) # 返回值是执行SQL语句之后受影响的行数
# 获取返回结果
res = cursor.fetchone() # 获取结果集的第一个结果
# cursor.scroll(1, 'relative') # 相对当前位置移动(相对移动)
# cursor.scroll(0, 'absolute') # 相对数据开头位置移动(绝对移动)
res1 = cursor.fetchall() # 获取所有结果
print(res)
print(res1)
9.注入问题
前戏
只需要用户名即可登录
不需要用户名和密码也能登录
问题
SQL注入
select * from userinfo where name='jason' -- haha' and pwd=''
select * from userinfo where name='xyz' or 1=1 -- heihei' and pwd=''
本质
利用一些特殊符号的组合产生了特殊的含义从而逃脱了正常的业务逻辑
措施
针对用户输入的数据不要自己处理 交给专门的方法自动过滤
sql = "select * from userinfo where name=%s and pwd=%s"
cursor.execute(sql, (username, password)) # 自动识别%s 并自动过滤各种符合 最后合并数据
execute方法,自动将 用户名和密码放在对应的%s内,并且放之前会自动对用户名和密码做特殊符号的校验,确保安全性
补充
cursor.executemany()
--------------------------------------------------
import pymysql
# 创建链接
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123456',
database='db1',
charset='utf8'
)
# 生成一个游标对象
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 让数据自动组织成字典
登录功能
1.获取用户名和密码
2.基于用户名和密码直接精准查找
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 构造SQL语句
sql = "select * from info where name=%s and password=%s" # 针对核心数据 不要自己拼接 交由execute方法帮你筛选再拼接
print(sql)
# 执行sql语句
cursor.execute(sql,(username, password))
# 获取所有返回结果
res = cursor.fetchall()
# if判断
if res:
print(res)
print('登录成功')
else:
print('用户名或密码错误')
标签:语句,cursor,第十,python,数据库,SQL,学习,mysql,数据
From: https://www.cnblogs.com/zxr1002/p/16610413.html