关系数据库与非关系数据库
关系数据库 | 非关系数据库 |
---|---|
数据的组织方式有明确的表结构 表里面有一些表的基本信息,关系型数据库存取数据的方式可以看成是表格 |
数据的组织方式没有明确的表结构 是以K:V健值对的形式组织的,{'name':'jason'},{'username':'kevin','pwd':123} |
表与表之间可以建立数据库层面的关系 | 数据之间无法直接建立数据库层面的关系 |
MySQL,PostgreSQL,MariaDB,Oracle,sqlite,db2,sql server MySQL:开源,使用最为广泛,数据库学习必学 PostgreSQL:开源 支持二次开发 MariaDB:开源 与MySQL是同一个作者,用法也极其相似 Oracle:收费,安全性极高,主要用于银行及各大重要机关 sqlite:小型数据库,主要用于本地测试(django框架自带该数据库) |
redis,mongoDB,memcache redis:目前最火,使用频率最高的缓存型数据库 mongoDB:稳定型数据库,最像关系型的非关系型,主要用于爬出,大数据memcache:已经被radis淘汰 |
库 | 文件夹 |
---|---|
表 | 文件夹里面的文件 |
记录 | 文件里一行行数据 |
查看所有的数据库 | show databases; |
查看所有的表 | show tables; |
查看user表里面所有的记录 | select * from mysql.user; |
SQL语句结束符是分号 | ; |
取消SQL语句的执行 | \c |
如果表中字段较多出现了错乱 可以结尾写\G | 可以结尾写\G |
存储引擎 | 简介 |
---|---|
MyISAM | MySQL5.5及之前版本默认的存储引擎 存取数据的速度快,但是功能较少,安全性较低 |
InnoDB | MySQL5.5之后版本默认的存储引擎 存取数据的速度没有MyISAM快,但是支持事物,行锁,外键等诸多功能 安全性较高 |
Memory | 基于内存的存储引擎,存取数据极快,但是断电立刻丢失 |
BlackHole | 黑洞,任何写进去的数据都会立刻丢失,类似于垃圾站 |
存储引擎 | 区别 |
---|---|
InnoDB | .frm 表结构 .ibd 表结构,表索引(加快数据查询) |
MyISAM | .frm 表结构 .MYD 表数据 .MYI 表索引(加快数据查询) |
Memory | .frm 表结构 |
BlackHole | .frm 表结构 |
操作 | 语法 |
---|---|
增 | create database 库名; |
查 | show databases; show creat database 库名; |
改 | alter database 库名 charset='gbk'; |
删 | drop database 库名; |
操作 | 语法 |
---|---|
查看当前所在库名 | select database(); |
使用当前库 | use 库名; |
增 | create table 表名(字段名 字段类型,字段名 字段类型,); |
查 | show tables; show create table 表名; describe 表名; desc 表名; |
改 | alter table 旧表名 rename 新表名; |
删 | drop table 表名; |
操作 | 语法 |
---|---|
增 | insert into 表名 values(数据,数据); insert into 表名 values(数据,数据),(数据,数据); |
查 | select * from 表名; # 查看所有字段 select 字段1,字段2 from 表名; 表中字段较多出现了错乱可以结尾写\G |
改 | update 表名 set 字段名 = 新数据 where 筛选条件; |
删 | delete from 表名; # 删除表中所有的数据 delete from 表名 where 筛选条件; # 按照条件删除数据 |
操作 | 语法 |
---|---|
修改表名 | alter table 表名 rename 新表名; |
新增字段 | alter table 表名 add 字段名 字段类型(数字) 约束条件; alter table 表名 add 字段名 字段类型(数字) 约束条件 after 已经存在的字段; alter table 表名 add 字段名 字段类型(数字) 约束条件 first; |
修改字段 | alter table 表名 change 旧字段 新字段 字段类型(数字) 约束条件; alter table 表名 modify 字段名 新的字段类型(数字) 约束条件;# 只改字段类型 |
删除字段 | alter table 表名 drop 字段名; |
create table 表名( 字段名1 字段类型(数字) 约束条件, 字段名2 字段类型(数字) 约束条件, 字段名3 字段类型(数字) 约束条件 )engine=存储引擎;
unsigned 约束条件之一,意思是不需要负号 create table t7(id tinyint unsigned); insert into t7 values(129),(256);
set session sql_mode='strict_trans_table' 当前客户端操作界面有效 set global sql_mode='STRICT_TRANS_TABLES' 服务端不重启永久有效
[mysqld] sql_mode='STRICT_TRANS_TABLES'
字符类型 | 表现形式 | 例子 |
---|---|---|
char | 定长 | char(4) 最大只能存储四个字符,如果超过范围则直接报错 如果不能超出范围,则用空格填充至四个字符 |
varchar | 变长 | varchar(4) 最大只能存储四个字符,如果超过范围则直接报错 如果不超出范围2,则有几位就存几位 |
create table t11(id int, name char(4)); create table t12(id int, name varchar(4)); desc t11; desc t12;
结果验证,超出范围两者都会报错,默认情况下char在存储的时候针对没有满足固定位数的字符会自动填充空格,
然后在读取的时候又会自动将填充的空格移除,如果想取消该机制,
需要 sql_mode set global sql_mode='strict_trans_tables,pad_char_to_full_length';
上述目录是替换,不是新增,所有之前的配置也要写上
3. 优缺点
类型 | 优缺点 | 案例 |
---|---|---|
char | 整存整取 速度快 浪费存储空间 |
char(4) a bcd aaaaaa 四个一组,空格也算 |
varchar | 节省存储空间 存取数据的速度慢于char |
varchar(4) 1bytes+a1bytes+son1bytes+jack 存取数据都需要操作报头(耗时) |
create table t13(id int(3)); insert into t13 values(1),(123),(12345); create table t14(id int(3) zerofill); insert into t14 values(1),(12);
# eg:性别(男,女,其他) create table t15( id int, name varchar(32), gender enum('male','female','others') ); insert into t15 values(1,'aaaaa','男'); insert into t15 values(1,'bbbb','male')
# eg:爱好(写,跑,听) create table t16( id, int, name varchar(32), hobbies set('read','run','music') )
date | 年月日 |
---|---|
datetime | 年月日时分秒 |
time | 时分秒 |
year | 年份 |
create table t17( id int, name varcher(32), brith date, reg_time datetime, study_time time, join_time year );
insert into 表名 vlaues() # 默认按照创建表字段顺序添加 insert into 表名(字段) vlaues # 可以自定义字段顺序
create table t19(id int,name varchar(32) not null); insert into t19(id) values(1); insert into t19(id,name) values(1,'');
create table t20(id int,name varchar(32) not null default 'jason'); insert into t20(id) values(1); insert into t20(id,name) values(2,'zhang');
create table t21(id int unique,name varchar(32)); insert into t21 values(1,'jason'); insert into t21 values(1,'zhang'); insert into t21 values(2,'zhang');
create table t22(id int,host varchar(32),post int,unique(host,post)); insert into t20 values(1,'127.0.0.1',8080); insert into t22 values(2,'127.0.0.1',8088); insert into t22 values(3,'127.0.0.2',8088); insert into t22 values(4,'127.0.0.1',8080);
外键字段:专用于记录表于表之间数据的关系
一对多关系
两张表完成换位思考之后得出的答案一个可以一个不可以,那么表关系就是"一对多"针对'一对多'的关系 外键字段建在多的一方。
多对多关系
两张表完成换位思考之后得出的答案两边都可以,那么表数据关系就是'多对多',针对多对多表关系 外键字段不能建在任意一方。需要单独开设第三张关系表 存储数据关系。
一对一关系
两张表完成换位思考之后得出的答案两边都不可以,那么先考虑是不是没有关系,如果有关系那么肯定就是'一对一',针对'一对一'的表关系 外键字段建在任何一张表都可以,但是建议建在查询频率较高的表中便于后续查询,还需添加唯一性,要不然和一对多没区别
没有关系
没有多对一,统一称为一对多
# 查询id大于等于3小于等于6的数据 select id,name from emp where id >= 3 id <= 6; select id,name from emp where 3 <= id <= 6; # 错误写法 select * from emp where id between 3 and 6; # 查询薪资是20000或者18000或者17000的数据 select * from emp where salary = 20000 or salary = 18000 or salary = 17000; select * from emp where salary in (20000,18000,17000); # 查询岗位描述为空的员工名与岗位名 针对null不能用等号,只能用is select name,post from emp where post_comment = NULL; # 查询为空! select name,post from emp where post_comment is NULL; select name,post from emp where post_comment is not NULL;
select name,salary from emp where name like '%o%';
select post from emp group by post;
max | 最大值 |
---|---|
min | 最小值 |
sum | 总和 |
count | 计数 |
avg | 平均 |
去重的前提是数据必须一模一样
# age 数据有重复数据 select distinct age from emp;
# 1. 查询工资,排序 select * from emp order by salary asc; # 默认升序排 select * from emp order by salary desc; # 降序排 # 2. 年龄降序排,薪资升序排 select * from emp order by age desc,salary asc;
# 1. 限制展示条数 select * from emp limit 3; # 2. 查询工资最高的人的详细信息 select * from emp order by salary desc limit 1; # 3. 分页显示 # 第一个参数表示起始位置,第二个参数表示的是条数,不是索引位置 select * from emp limit 0,5; select * from emp limit 5,5;
# 查询以j开头,n或y结尾 select * from emp where name regexp '^j.*(n|y)$';
import pymysql # 1.链接服务端 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', database='db3', charset='utf8mb4', autocommit=True # 执行增、改、删操作自动执行conn.commit ) # 2.产生一个游标对象(等待输入命令) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 3.编写sql语句 sql1 = 'select * from t1' # 4.发送给服务端 cursor.execute(sql1) # 5.获取命令2的执行结果 # res = cursor.fetchall() # 获取结果集中所有数据 # res = cursor.fetchone() # 获取结果集中一条数据 # res = cursor.fetchmany(3) # 获取结果集中指定条的数据 res = cursor.fetchone() print(res) # 类似于文件光标的概念 # cursor.scroll(1,mode='relative') # 基于当前位置往后移动 cursor.scroll(0,mode='absolute') # 基于数据集开头的位置往后移动 res = cursor.fetchall() print(res)
import pymysql # 1. 链接服务器 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', database='db3', charset='utf8mb4', autocommit=True ) # 2.产生一个游标对象(等待输入命令) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 3.获取用户数据 username = input('username>>>:').strip() password = input('password>>>:').strip() # 4.编写sql语句 sql = "select * from t1 where name='%s' and pwd='%s'"%(username,password) print(sql) # 5.执行sql语句 cursor.execute(sql) # 6.获取结果 res = cursor.fetchall() if res: print('登录成功') print(res) else: print('用户名或密码错误')
# mysql 三种注释语法 # 号注释 -- --注释 /* 注释*/ where 后面条件如果为True 相当与没有条件
import pymysql # 1. 链接服务器 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', database='db3', charset='utf8mb4', autocommit=True ) # 2.产生一个游标对象(等待输入命令) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'insert into t1(name,pass) values(%s,%s)' # [(),(),()] cursor.executemany(sql,[('jason1',111),('jason2',222),('jaosn',333)])
给字段起别名,起表名
给表、字段添加注释信息
create table t3(id int primary key auto_increment comment '用户id', name varchar(32) comment '用户名') comment ' 用户表'; # 查看注释 show create table t3; # 打开库 use information_schema # 查看库里表 show tables; # 查看以名字筛选 select * from tables where table_name='t3'/G;
exists后面的sql语句如果有结果那么执行前面的sql语句,如果没有结果则不执行
通过help 函数名 查看帮助信息
# 创建视图基本语法(SQL语句为多表查询语句) create view 视图名 as SQL语句; # 修改视图 alter view 视图名 as select 语句 # 显示视图创建情况 show create view 视图名; # 查看视图 show tables; # 删除视图 drop view 视图名[,视图名…]; # 重命名视图 Rename table 视图名 to 新视图名;
触发器是与表有关的数据库对象,针对表数据的增、改、删自动触发的功能(增前、增后、改前、改后、删前、删后)
create trigger 触发器的名字 before/after insert/update/delete on 表名 for each row begin sql语句 end; # before/after:指定是在之前还是之后触发 # insert/update/delete:指定当表发生什么类型(insert/update/delete)的操作时会触发 # 查看触发器 show triggers; # 删除触发器 drop triggers 触发器的名字
触发器内部的SQL语句需要用到分号吗,但是分号又是SQL语句默认的结束符所以为了能够完整的写出触发器的代码,需要临时修改SQL语句默认的结束符
delimiter $$ # 第一次为将mysql默认的结束符由;换成$$ 编写需要用到分号的各种语句 delimiter ; # 第二次为把修改为$$的结束符修改成原来的分号
是将⼀组操作封装成⼀个执行单元(封装到⼀起),这⼀个执⾏单元要么⼀起执行成功,要么⼀起失败,不会出现执行“⼀半”的情况。
存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。储存过程思想上很简单,就是数据库SQL语言层面的代码封装与重用
create procedure 存储过程名称(in/out/inout 参数名 参数类型(长度)) begin SQL语句; end; # in:该类型参数作为输入,也就是需要调用时传入值 # out:该类型参数作为输出,也就是该参数可以作为返回值 # inout:即可以作为输入参数,也可以作为输出参数 # 查看存储过程 show create procedure 存储过程名字; # 查看所有存储过程 show procedure status; # 删除储存过程 drop procedure 存储过程名字;
Trim、LTrim、RTrim
Lower、Upper
Left、Right
Soundex
current_date():当前日期 current_time():当前时间 current_timestamp():当前时间戳 date(datetime):返回datetime参数的日期部分 date_add(date, interval d_value_type):在date中添加日期或时间。interval后的数值单位可以是year/day/minute/second date_sub(date, interval d_value_type): 在date中减去日期或时间。interval后的数值单位可以是year/day/minute/second datediff(date1, date2): 计算两个日期的时间差,单位是天 now(): 当前日期时间
实际开发中,解决复杂的问题是需要执行多个sql语句的,流程控制语句的作用就是用来控制存储过程中SQL语句的执行顺序。流程分为顺序结构,分支结构和循环结构,对应MySQL来说,流程控制语句主要有3类。
# if条件语句 delimiter // CREATE PROCEDURE proc_if () BEGIN declare i int default 0; if i = 1 THEN SELECT 1; ELSEIF i = 2 THEN SELECT 2; ELSE SELECT 7; END IF; END // delimiter ; # while循环 delimiter // CREATE PROCEDURE proc_while () BEGIN DECLARE num INT ; SET num = 0 ; WHILE num < 10 DO SELECT num ; SET num = num + 1 ; END WHILE ; END // delimiter ;
索引是帮助MySql高效获取数据的数据结构。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。索引是数据库优化最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数的MySql的性能优化问题。
# 创建索引 alter table test add index index_name(name); #创建索引 create index index_name on test(name); #查看索引 desc table; #查看索引 show index from table; #删除索引 alter table test drop key index_name; #添加唯一性索引 alter table student add unique key uni_xxx(xxx); #查看表中数据行数 select count(*) from city; #查看去重数据行数 select count(distinct name) from city;