数据库

数据库


本质: 一套C/S socket 软件

分类

关系型数据库:

数据与数据建立关联关系

SQLServe,仅支持Windows

MySQL, 免费 开源 性能不差 先后被sun 和Oracle 收购目前属于Oracle公司

​ mariaDB mysql创始人自己又自己开发的一款数据库

Oracle, 目前较好的数据库 收费高

DB2, IBM 收费

非关系型数据库: MongoDB,Redis,memcache

相关概念:

​ 数据: 记录事物状态的符号

​ 记录: 事物典型特征的组合 (数据行)

​ 表 : 文件

​ 库 : 文件夹

​ 数据库管理系统(DBMS): 用于管理库的软件 C/S程序

​ 数据库服务器 : 运行着DBMS的计算机称为数据库服务器

MySQL数据库


安装

windows版本

1、下载:MySQL Community Server 5.7.16
http://dev.mysql.com/downloads/mysql/

2、解压
如果想要让MySQL安装在指定目录,那么就将解压后的文件夹移动到指定目录,如:C:mysql-5.7.16-winx64

3、添加环境变量
【右键计算机】--》【属性】--》【高级系统设置】--》【高级】--》【环境变量】--》【在第二个内容框中找到 变量名为Path 的一行,双击】 --> 【将MySQL的bin目录路径追加到变值值中,用 ; 分割】

4、初始化
mysqld --initialize-insecure

5、启动MySQL服务
mysqld # 启动MySQL服务

6、启动MySQL客户端并连接MySQL服务
mysql -u root -p # 连接MySQL服务器

上一步解决了一些问题,但不够彻底,因为在执行【mysqd】启动MySQL服务器时,当前终端会被hang住,那么做一下设置即可解决此问题:

注意:--install前,必须用mysql启动命令的绝对路径

制作MySQL的Windows服务,在终端执行此命令:

"c:mysql-5.7.16-winx64inmysqld" --install

移除MySQL的Windows服务,在终端执行此命令:

"c:mysql-5.7.16-winx64inmysqld" --remove

注册成服务之后,以后再启动和关闭MySQL服务时,仅需执行如下命令:

启动MySQL服务

net start mysql

关闭MySQL服务

net stop mysql

其他操作


设置密码
mysqladmin.exe 用于设置密码
mysqladmin -uroot -p旧密码 password 新密码

破解密码
可以在启动服务器时 告诉他 让他不要读取密码文件
1.mysqld --skip-grant-tables
2.无密码登录服务器
3.使用update 来更新你的密码 在msyql.user表中
在客户端 update mysql.user set password = password("321") where user = "root" and host="localhost";
4.重启服务 验证新密码

安装mysql得到两个程序
1.服务器程序
存取数据时服务器的工作
2.客户端程序
命令服务器来完成存取工作
客户端将命令发送给服务器 服务器解析执行命令 返回客户端要的数据

服务器为了保证数据安全需要进行用户验证
默认有一个root 账户 默认没有密码 不安全
需要修改密码:
在服务器的终端中执行
mysqladmin.exe -u要改的用户名 -p旧密码 password 新密码
在服务器上执行命令时 如果看到Install/Remove of the Service Denied! 说明权限不够
得用管理员身份运行
如果忘记密码 要破解 也需要在服务器终端启动mysql服务 并且需要添加跳过授权表的参数

mysql -uroot -padmin 用mysql自带的客户端登录服务器
-u 用户名 -p 密码 -h 服务器的ip -P端口号 在本机上执行客户端不需要指的 -h -P

基础SQL语句

库相关

创建
create database 数据库名 charset 编码名称
修改
alter database 数据库名 charset gbk

show databases; 查看所有数据
show create database 数据库名 查看建库语句
删除
drop database 数据库名

表相关

创建
        create table t1(id int,name char);
    修改
        改结构
        alter table 表名  add | drop | modify | change
        add 后面跟 字段名 数据类型
        drop 后面跟 字段名
        modify 后面跟 字段名  新类型
        change 后面跟 旧字段名 新的字段名 新类型
        该属性
            编码
                alter table t1 charset gbk;
            表名

​                rename table 旧表名 to 新表名
​    查
​        show tables;
​        show create table 表名 查看建表语句
​        desc 表名  查看表结构(字段)
​    删除
​        drop table 表名
​        truncate table 表名,重建表(清空数据)

记录相关

添加
insert into 表名 values(值1...),(值1....)....
插入时注意 值得顺序 和 类型必须与表结构一致
修改
update 表名 set 字段名=新的值 where 条件
可以同时修改多行 用逗号来隔开字段
没有条件就全改

select *|字段名 from 表名 *表示所有字段
删除
delete from 表名 where条件
没有条件就全删

创建表的完整语法
create table 表名(
字段名称 数据类型[(长度) 约束条件],
字段名称 数据类型[(长度) 约束条件]
)

数据存储引擎
什么是引擎 ? 一个功能的核心部分
引擎可以被分类
需求场景的不同催生了不同的引擎类别

mysql
核心功能是存储数据 涉及到存储数据的代码 就称之为存储引擎
根据不同的需求 也有着不同的引擎分类

不同的引擎测试
创建表时在最后指定引擎名称 engine = xxx
create table t1(id int)engine=innodb
create table t1(id int not null)engine=CVS
create table t1(id int)engine=memory
create table t1(id int)engine=blackhole

总结: innodb是默认的引擎 因为 它是永久存储 并且 支持事务,行锁,外键

数据类型

存在不同数据类型好处

1.描述事物 更加准确
2.描述起来更方便
3.节省内存空间

mysql支持的数据类型:

整型


​ tinyint smallint mediumint int bigint
​ 字节数: 1 2 3 4 8
​ 默认情况下整型是有符号的 需要用一个二进制位存储符号
​ 给整型加上 约束 unsigned来表示无符号
​ 如果数据超出范围就尽可能保存最大的 例如 在无符号下 保存256 其实存的255
​ 如果有符号 例如 tinyint 保存-1280 其实存的是 -128 是最小值

浮点型


分类: float double decimal
字节数: 4 8 不确定(手动指定)

给浮点设置宽度限制
float(m,d)
double(m,d)
decimal(m,d)

长度说明
m表示 这个浮点数整体的长度
d表示 小数部分的长度
例如: float(5,3) 最大值: 99.999

异同
相同点: 小数部分最大长度都是30
float和double的最大长度为255
不同点: decimal的整体最大长度65
精度不同
double 比 float 精度高
decimal 是准确的 不会丢失精度

字符型


分类
char 定长字符
varchar 变长字符

char类型的长度是固定 无论你存储的数据有多长 占用的容量都一样
char(3) 存储的数据为 "a" 在硬盘保存的数据还是占3字符长度 实际保存的是"a "
varchar 长度是可变的 存储的数据有多长就占用多长
varchar(3) 存储的数据为 "a" 在硬盘保存的数据还是占1字符长度 实际保存的是"a"
yxx exx lxx zxx cx wxx char(3)
(1bytes+yx)(1bytes+exx)(1bytes+lx)(1bytes+zxx) varchar(3)
如果是可变长度 则有问题 不知道数据从哪里开始到哪里结束 所以需要有一个位置保存数据的长度
vharchar 能支持的最大长度是65535 用于保存数据长度的数据最长两个bytes

如果是char类型 如果你的数据不足指定长度 就在后面用空格补全

验证:
使用一个 char_length的函数 可以查看字符的长度
create table t18(a char(4),b varchar(4));
insert into t18 value("x","x");
select char_length(a),char_length(b) from t18;
两个字段的长度都为1

结论:
这是因为 mysql在存储时 自动加上的空格 对使用者而言是没有意义的 所以mysql自动帮你处理掉空格了
我们可以设置sql模式 来让它现出原形
set global sql_mode = "PAD_CHAR_TO_FULL_LENGTH,STRICT_TRANS_TABLES"
设置完成后重启msyql 再次查询长度

注意:

当你在执行这样的查询语句时 mysql会自动将参数末尾的空格去除
select *from t19 where name = "yh"
当你在使用模糊搜索时 要注意 定长字符 后面可能会有空格 所以最好在后面加上百分号 %
select *from t19 where name like "yh";
% 任意个数的任意字符
_ 1个任意字符

如何选择
char
存取效率高
浪费存储空间
varchar
存取效率低于char
节省存储空间
使用起来感受不到区别 通常用的是char

char和varchar 长度都比较小 最大就是65535

大文本类型:

TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT 文本是带有编码
BLOB 系列 TINYBLOB BLOB MEDIUMBLOB LONGBLOB 也是字符数据 但是不带编码

二进制类型: 用于存储多媒体数据 比如视频 但是我们一般不会将多媒体数据存到数据 而是存储文件路径地址
BINARY系列 BINARY VARBINARY 存储二进制数据

时间类型


分类
time 时分秒 HH:MM:SS
year 年份
date 日期 年月日
datetime 日期加时间 年月日 时分秒 年份最大是9999
timestamp 时间戳 从1970-1-1开始算 年份最大是2037

共同点: 时间的存取通过字符串类型
都可以使用now()函数来插入当前时间

datetime 和 时间戳都能够表示日期和时间
不同之处是: 年份最大范围不同
时间戳可以为空 代表当前时间
时间戳在你更新记录时 会自动更新为当前时间

枚举


用于描述 一个已知范围的数据 例如性别: 只有男 女 或其他
enum("man","woman","other")

总结: 枚举中只能是字符串类型
添加的数据只能是已经出现在枚举中的值
你的值只能是其中的一个
你也可以使用枚举值的序号来插入值 从1开始
多选1

集合
用于描述一堆数据 比如你的兴趣爱好
set("watch movie","listen music","play game")

总结:集合中的数据 只能是字符串
添加的数据只能是已经出现在集合中的值
你的值可以是其中的任意几个
你也可以使用枚举值的序号来插入值 从1开始 但是只能给一个序号
多选多

约束条件

除了数据类型以外额外添加的约束
为了保证数据的合法性 完整性

not null

非空约束 数据不能为空

 create table student (id ind,
                       name char(10) not null);

default

默认值约束 可以指定字段的默认值

create table user (id ind,name char(10) not null,
                 sex char(1) default "woman");

unique

唯一性约束 该字段的值不能重复

是一种索引 可以加速查找

单列唯一:

create table t5(idcard char(18) unique);

联合唯一:

create table t6(idcard char(18),
                phonenumber char(11),
                unique(idcard,phonenumber));

primary key

主键约束

是一种索引 必然存在硬盘上的某个文件中 是物理层面

等价于not nullunique约束

create table stu (stuid int primary key,name char(3));

多列联合主键

 create table t8(idcard char(18),
                 phonenumber char(11),
                 primary key(idcard,phonenumber));

有主键 和没有主键的区别?
1.无法区分两个相同记录
2.有主键则意味有这索引 效率更高
3.可以建立关联关系

auto_increment
自动增长
通常搭配主键字段使用 可以自动为你的数据分配逐渐

create table t9(id int primary key auto_increment,
                name char(3));

修改自动增长的起始位置

alter table t9 auto_increment = 7;

注意: 自动增长 只能用于整型

	如果主键是自动增长  你可以跳过这个字段 也可以为它插入null  都可以

foreign key

表与表之间建立联系

表与表之间的关系

一对一

多对一:

将'多' 一方设为从表 加上外键

多对多:

创建第三张 关联表

语法

 create table dept(id int primary key auto_increment,
                   name char(10),
                   manager char(10));

create table emp(id int primary key auto_increment,
                 name char(10),dept_id int,
                 foreign key(dept_id) references dept(id));

添加外键约束时:
被关联的表需要先被创建
部门数据(主表)应该先插入 员工数据(从表)后插入
在删除部门数据前(主表)前 要保证该部门的员工数据都删除了
在更新部门编号前 要先保证没有员工关联到这个部门

:外键加上以后 主表中的数据 删除 和更新时 都受到限制
解决的方案是为 外键 添加 级联操作

级联操作
指的是就是同步更新和删除
语法:在创建外键时 在后面添加 on update cascade 同步更新
on delete cascade 同步删除

create table class(id int primary key auto_increment,
                   name char(10));
create table student(
    id int primary key auto_increment,
    name char(10),
    c_id int,
    foreign key(c_id) references class(id)
    on update cascade
    on delete cascade
);

查询语句

完整查询语句

select [distinct] {* | 字段名 | 聚合函数 | 表达式} from 表名
[where 条件
group by 字段名
having 条件
order by 字段名
limit 显示的条数]

关键字执行顺序

def select()
from() 打开文件
where() 读取每一行并判断是否满足条件
group() 对数据进行分组
having() 再分组之后进行过滤 having不单独出现 仅用于分组之后进行过滤
distinct() 去重
order() 用于对筛选后的数据 进行排序
limit() 限制显示的条数
最后根据select后制定的字段来显示数据

一、where过滤
where字句中可以使用:

  1. 比较运算符:> < >= <= <> != #不等于用 != 不用 <>

    select id,name from db39.emp where id >= 3 and id <= 6
    
  2. between 80 and 100

    select *  from db39.emp where id between 3 and 6;  # >=3 and <=6
    
  3. in(80,90,100) 值是80或90或100

    select * from emp where salary in (20000,18000,17000); # select * from emp where salary = 20000 or salary = 18000 or salary = 17000;
    
  4. like 'egon%', pattern可以是%或_, %表示任意多字符, _表示一个字符

    select name,salary from db39.emp where name like '%i%'  #要求:查询员工姓名中包含i字母的员工姓名与其薪资
    select name,salary from db39.emp where name like '____';  #要求:查询员工姓名是由四个字符组成的的员工姓名与其薪资
    select name,salary from db39.emp where char_length(name) = 4;   #结果与上一条一致
    
  5. 逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not

    select *  from db39.emp where id not between 3 and 6;
    select * from emp where salary not in (20000,18000,17000);
    

    针对NULL必须用is,不能用=

    select name,post from db39.emp where post_comment is NULL;
    

二、group by分组

如果不设置成only_full_group_by模式,分完组后用*默认取出的是组内的第一个人的数据。但分完组后单独取组内的某个元素是没有意义的,所以,分组前,一般会对模式做如下处理
#设置sql_mode为only_full_group_by,意味着以后但凡分组,只能取到分组的依据

```Python

set global sql_mode="strict_trans_tables,only_full_group_by";
```

聚合函数: max(), min(), avg(), sum(),count()

group_concat:(分组之后用)把想要用的信息取出;字符串拼接操作

as :为字段或表取别名

#聚合函数 group function(一般与分组连用)
select post,max(salary) from emp group by post; #取不出组内的元素name, age..,只能取组名(分组依据)或用聚合函数

select post,min(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;

#group_concat(分组之后用):把想要用的信息取出;字符串拼接操作
select post,group_concat(name) from emp group by post;
select post,group_concat(name,"_SB") from emp group by post;
select post,group_concat(name,": ",salary) from emp group by post;
select post,group_concat(salary) from emp group by post;

# 补充concat(不分组时用):字符串拼接操作
select concat("NAME: ",name) as 姓名,concat("SAL: ",salary) as 薪资 from emp;

# 补充as语法:为字段或表取别名
select name as 姓名,salary as 薪资 from emp;  # as可省略
mysql> select emp.id,emp.name from emp as t1; # 报错
mysql> select t1.id,t1.name from emp as t1;  # 同 mysql> select id,name from emp as t1;

三、having过滤 (一定要用组名(分组依据)或聚合函数)
having的语法格式与where一模一样,只不过having是在分组之后进行的进一步过滤
即where不能用聚合函数,而having是可以用聚合函数,这也是他们俩最大的区别

#统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门
select post,avg(salary) from emp where age >= 30 group by post having avg(salary) > 10000;

#强调:having必须在group by后面使用 (不认默认分组)
select * from emp having avg(salary) > 10000; #报错

四、distinct去重 (在having之后执行,和post,name等属于同一执行级别)
select distinct post,avg(salary) from emp where age >= 30 group by post having avg(salary) > 10000;

五、order by 排序 (默认升序)

select * from emp order by salary asc; #默认升序排
select * from emp order by salary desc; #降序排
select * from emp order by age desc,salary asc; #先按照age降序排,再按照薪资升序排
# 统计各部门年龄在10岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对平均工资进行排序
select post,avg(salary) from emp where age > 10 group by post having avg(salary) > 1000 order by avg(salary);

六、limit 限制显示条数;分页

select * from emp limit 3;
select * from emp order by salary desc limit 1;  #显示薪资最高人的信息
select * from emp limit 0,5; #分页, 从0开始,取5条(1-5)
select * from emp limit 5,5; #分页, 从5开始,取5条(6-10)

七、正则表达式

select * from emp where name regexp '^jin.*(n|g)$';  #调正则;正则表达式通用

多表连接查询

关键字 on

在 多表查询时使用 后边条件 = 号两边全是主键

一、笛卡尔积
from emp,dep,dep2,...

二、内连接:把两张表有对应关系的记录连接成一张虚拟表

select * from emp inner join dep on emp.dep_id = dep.id;

#应用:
    select * from emp,dep where emp.dep_id = dep.id and dep.name = "技术"; # 不推荐;不要用where做连表的活
    select * from emp inner join dep on emp.dep_id = dep.id where dep.name = "技术";   #逻辑与上一条一致

三、左连接:在内连接的基础上,保留左边没有对应关系的记录

select * from emp left join dep on emp.dep_id = dep.id;

四、右连接:在内连接的基础上,保留右边没有对应关系的记录

select * from emp right join dep on emp.dep_id = dep.id;

五、全连接:在内连接的基础上,保留左、右边没有对应关系的记录

select * from emp left join dep on emp.dep_id = dep.id
union   #去重
select * from emp right join dep on emp.dep_id = dep.id;

六、多表连接可以是单表不断地与虚拟表连接

#查找各部门最高工资
select t1.* from emp as t1 
inner join
(select post,max(salary) as ms from emp group by post) as t2  #把虚拟表提成t2
on t1.post = t2.post
where t1.salary = t2.ms
;

select t1.* from emp as t1 
inner join
(select post,max(salary) as ms from emp group by post) as t2
on t1.salary = t2.ms
;

子查询(一个问题一个问题解决)
把一个查询语句用括号括起来,当做另外一条查询语句的条件去用,称为子查询

select name from emp where dep_id = (select id from dep where name="技术");  #子查询
select emp.name from emp inner join dep on emp.dep_id = dep.id where 	dep.name="技术";  #链表

#查询平均年龄在25岁以上的部门名
select name from dep where id in (select dep_id from emp group by dep_id having avg(age) > 25);   #子查询
select dep.name from emp inner join dep on emp.dep_id = dep.id group by dep.name having avg(age) > 25;  #链表

#查看不足2人的部门名(子查询得到的是有人的部门id)
select * from emp where exists (select id from dep where id > 3); #exists用法,当()返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询(empty set)

#查询每个部门最新入职的那位员工
select t1.id,t1.name,t1.post,t1.hire_date,t2.post,t2.max_date from emp 	as t1 inner join (select post,max(hire_date) as max_date from emp group by post) as t2 on t1.post = t2.post where t1.hire_date = t2.max_date;

权限管理

mysql 用户管理
MYSQL 是一个tcp 服务器 用于操作服务器上的文件数据,
接收用户端发送的指令, 接收指令时需要考虑安全问题

在mysql自带的mysql数据库中有4个表用于用户管理的
分别是: 优先级从高到低
user -> db -> tables_priv -> columns_priv

#1.创建用户的语句
    create user  用户名@"主机地址" identified by "密码";

    create user  scote@"127.0.0.1" identified by "123";
    此处的主机地址 不是服务器地址 而是表示 这个账户可以在那台电脑上登录

#2. 授权的语句  
    语法: grant [权限的名称 select insert.... | all ] on 数据库.表名  to 用户名@主机地址;
    # 授予 scote 这个用户所有权限 在所有数据库所有表中
    grant all on *.* to scote@"localhost"; 可以访问 所有库和表
    grant all on day41.* to scote@"localhost";  可以访问day41库的所有表
    grant all on day41.stu to scote@"localhost"; 可以访问day41库的stu表
    grant select(id,name),insert(id,name) on day41.stu to scote@"localhost";
# 仅能查看和添加 day41库的stu表中的 id和name字段
 
# 3.grant [权限的名称 select insert.... | all ] on 数据库.表名  to 用户名@主机地址 with grant option;
    with grant option 这个用户可以将他有的权限授予别的账户
    特点: 如果授权时  用户不存在 直接自动创建用户
 grant all on mydb1.* to testDBA@"%"  identified by "123";
# 4.删除权限
   revoke 权限的名称 on 数据库.表名  from 用户名@"主机名" ;
   revoke all on *.* from scote@"localhost";

   update mysql.user set  Grant_priv = "N" where user ="scote" and host = "localhost";

# *.刷新权限表
    flush privileges;

# 5.删除用户
    drop user 用户名@"主机地址";
原文地址:https://www.cnblogs.com/9527mwz/p/10856626.html