学习笔记22-mysql

数据的存储方法有三种:内存,文件,数据库
内存,优点:访问速度快,操作方便 缺点:不能永久保存,数据是临时状态
文件,优点:数据可以永久保存 缺点:数据的操作不方便,查询慢,不易管理
数据库,优点:数据可以永久保存,查询速度快,管理方便 缺点:占用系统资源,需要购买

所有的关系型数据库都可以通过通用的SQL语言来进行管理 DBMS Database Management System

MySQL开源小型的数据库,已经被Oracle收购 6.x也开始收费
Oracle 收费的大型数据库
DB2 IBM公司的数据库产品(收费),主要用在银行系统
SQL Server 微软的中型数据库 主要 C# .net等语言常使用
SQLite 嵌入式的小型数据库,主要用于手机端(如Android)

连接MySQL时报错码10061 是MySQL服务未启动 解决方法:用管理员身份进入命令行,执行 net start MySQL 或右键我的电脑->管理->服务 中启动MySQL 或者Windows+R后在运行中输入 sevices.msc进入管理界面(msc即微软控制系统服务)

连接MySQL时报错码10060是ip地址不对,确认ip地址是否正确

using password:yes 是账号或密码错误

MySQL的登录,进入命令行后 1.MySQL -u用户名 -p密码
2.MySQL -h本机IP地址或主机名 -u用户名 -p密码
3.连接网络数据库的话 MySQL -h本机IP地址或主机名 -P端口号 -u用户名 -p密码

退出:quit或exit

什么是SQL Structured Quary Langugae 结构化查询语言

SQL语句的分类
数据定义语言 如建库建表 DDL Data Definition Language
数据操纵语言 如对表中数据的增删改 DML Data Manipulation Language
数据查询语言 查询 DQL Data Quary Language
数据控制语言 修改权限等 DCL Data Control Language

MYSQL语法 1.以分号结尾(在SQLyog中可以不加分号) 2.不区分大小写 3.注释 --空格 单行注释, /* */多行注释 , #这是MySQL特有的注释方式

扫描二维码关注公众号,回复: 5895857 查看本文章

DDL创建数据库
1.create database 数据库名; (创建数据库) 2.create database if not exists 数据库名;(数据库不存在则创建数据库,注意数据库名写在最后面) 3.create database 数据库名 character set 字符集;(创建指定字符集的数据库)

按tab 键可以自动补全关键字 在MySQL中int和integer是一样的

show databases;查看所有的数据库列表 show create database db1;查看数据库的定义信息 alter database 数据库名 character set utf8;修改数据库的字符集 drop database 数据库名;删除数据库

select database(); 查询正在使用的数据库,没有返回null(这是MySQL中的一个全局函数) use 数据库名;切换数据库

创建表的格式 create table 表名(字段名1 字段类型1,字段名2 字段类型2);

MySQL常用的数据类型 int/Integer(整形) double(4,1)(浮点型,总长度是4,小数点后是1) varchar(m)(可变长度字符串,使用几个就占用几个字符,m取值是0-65535) char(m)(固定长度的字符串,不论有实际几个字符全部占满,m取值是0-255) data(日期类型 格式为yyyy-MM-dd 只有年月日,没有时分秒) time(时间类型) datatime(同时表示时间和日期) timestamp(时间戳类型)如果不赋值或赋值为null,则采用当前的系统时间 包含时间和日期的

show tables;查看数据库中的所有表 show create table 表名; 查看表的创建语句 desc 表名; 查看表结构

create table 表名 like 已有的表名; 快速创建一个表结构相同的表 drop table 表名;删除一个表 drop table if exists 表名;如果表名存在就删除(程序不会报错)

rename table 表名 to 新表名; 修改表名 alter table 表名 character set 字符集; 修改表的字符集

alter table 表名 add 字段 字段类型; 新增字段
alter table 表名 drop 字段;删除字段
alter table 表名 modify 字段 新字段类型;修改字段类型
alter table 表名 change 原字段名 新字段名 新字段类型;修改字段名及类型
----------------------------------------------------------------------------以上为数据定义语言
DML数据操纵语言
向表中插入数据 insert into 表名 (字段名1,字段名2,字段名3) values (字段值1,字段值2,字段值3); 插入部分字段,未设置的字段默认为null
如果插入的是全字段也可以简写为 insert into 表名 values (字段值1,字段值2,字段值3…); 字段值必须写全
value 和values都可以,建议values 插入多条数据时可以一句话完成,这样效率最高 insert into 表名 value(字段名1,字段名2,字段名3),(字段名1,字段名2,字段名3)…;是一条一条插入的将近3倍.

字符和日期应该包含在单引号中,MySQL中也可以包含在双引号中

使用命令行查询时,有时中文会出现乱码问题,这是因为Windows默认的字符集是GBK,而MySQL客户端的编码是utf8导致的.修改客户端的字符集为GBK便可以.操作如下:
show variables like ‘%character%’; 查询出含有character的系统变量,里面的character_set_client character_set_results character_set_connection 显示是utf8,这是和客户端显示有关的
set names gbk;便修改过来了 也可以一个一个的设置 需要注意的是,退出dos命令就失效了,需要每次都设置

蠕虫复制 复制一张表的内容首先要创建一张表和要复制的表的结构一样 create table 表名 like 旧表名;
insert into 表名 select * from 旧表名;完全复制
insert into 表名(字段1,字段2) select 字段1,字段2 from 旧表名;部分复制

还有一种更简单的完全复制 create table 表名 as select * from 旧表名;
更简单的部分复制 create table 表名 as select 字段1,字段2 from 旧表名;

修改表数据 update 表名 set 字段名=字段值 where 字段名=字段值;
where不加的话就是修改字段的全部的值,where如果加多个条件的话 用and or等来连接 ,set如果是多个值的话用逗号来连接

删除表数据 delete from 表名 ; 删除全部数据
delete from 表名 where 条件; 删除符合条件的数据 如果删除某个字段为null的数据 不能用=号 要用is null 或者is not null
truncate和delete的区别,truncate是直接删除表再创建一个一模一样的空表 delete只是删除了数据,有多少条数据执行多少次删除操作,效率较低
------------------------------------------------------------------------------以上为数据操纵语言
DQL数据查询语言
select 列名 from 表名 where 查询条件; *可以代替所有列名
使用别名的好处:显示字段时显示新的名字,并不改变原来表的结构 as 关键字 可以省略 表名的别名多用于多表查询

distinct 去重 select distinct 字段名 from 表名; distinct去重 如果是多个字段,必须是这几个字段全不一样才能去重,不是或的关系是且的关系

查询的结果可以参与运算,前提是查询的结果是数据类型的 显示的是列名+列名 我们可以给它起个别名 select *,(math+English) ‘总成绩’ from student;

条件查询 select 字段 from 表名 where 条件语句;
比较运算符: > 大于 < 小于 =等于 <>不等于 >=大于等于 <=小于等于
between X and X 在数据之间,包头又包尾
in(X,Y,Z) 在这几个数之间
like ‘%X’ 模糊查询
is null is not null 判断是空不是空
逻辑运算符 and与 or或 not非
通配符 %匹配任意多个字符 _匹配一个字符

查询语句的顺序执行 select * from where groupby(分组) having(分组后条件查询) orderby(排序) limit(分页)
MySQL中凡是有null参与的运算,结果都是null 有一个ifnull(表达式1,表达式2)函数可以将为null的值转为我们想要的值 表达式1就是可能为null的字段 表达式2就是如果为null后我们替换为什么内容

order by 排序 select * from student order by age desc; asc升序排序 desc 降序排序 默认是升序排序不用写asc
单列排序:只按一个字段排序
组合排序:对多个字段进行排序,如果字段1相同则对字段2进行排序 select * from student order by age desc,math asc; 先按照年龄降序排序,如果年龄相同则按照数学成绩,升序排序

之前的查询都是横向查询,聚合函数是纵向查询 五个聚合函数 max( ),min(),avg(),count(),sum() 聚合函数会忽略空值null

count(1)和count(主键)一样只扫描主键 count(*)是扫描整张表 count(1)会快一些

group by 分组,会将分组字段 按内容不同分为n组 只显示每组的第一行数据 单独使用时没什么作用的,需要和聚合函数一起使用

当我们使用哪个字段分组,在查询的时候也需要查询该字段,否则看不到数据属于哪个组

where和having的区别,where是在分组之前过滤数据,后面不可以跟聚合函数 having是在分组之后过滤数据,后面可以跟聚合函数

limit是限制的意思,所以limit语句就是限制查询的条数 limit 起始行数(不包含),返回的条数; 起始行数不写的话,默认是0 如果条数不够,有多少,显示多少

在dos命令中,数据库的备份和还原
备份:未登陆MySQL, 执行: MySQLdump -u账号 -p密码 数据库名 > 导入的文件路径
还原:登陆MySQL后 执行: use 数据库名; source 导入的文件路径;

数据库约束的作用,对表中的数据进行限制,以保证数据的正确性,有效性,完整性

约束种类如下:
约束名 约束关键字 特点 作用
主键 primary key 非空,唯一 用来唯一标识数据库中的每一条记录(主键是给程序和数据库使用的,不是给客户使用的,主键没有意义没关系,只要非空不重复即可,一般用id作为主键)
非空 not null
唯一 unique
外键 foreign key
检查 check(Mysql不支持)

创建表的时候增加主键 create table s1(id int primary key,name varchar(20));
为已有的表增加主键 alter table s1 add primary key (id); 注意作为主键的字段要用括号括起来
删除主键 alter table s1 drop primary key;

一张表中只能有一个主键,但是可以是多个字段组成的联合主键. 一张表中只能有一个自增的字段,该字段可以是主键,也可以是其他字段,但为其他字段时必须显式设置Unique约束,否则会报错,建议主键自增(SQL设置其他字段为自增时会报错,但用SQLyog软件时不报错,这是一个bug)
设置主键自增 auto_increment 自增 默认从1自增,也可以自己设置 自增的字段必须是整数类型的
创建表的时候设置自增主键和自增初始值为1000 create table s1(id int primary key auto_increment,name varchar(10)) auto_increment=1000;
如果已经设置好自增主键但是初始值需要修改 alter table s1 auto_increment=1000;
如果已经有主键未设置自增 alter table (change id/modify) id int primary key auto_increment ;
如果已有自增主键,想要去除主键约束.直接drop primary key 会报错 ,应该先修改字段属性去除自增,再删除主键 alter table s1 modify id int; alter table s1 drop primary key ;

delete和truncate对自增长的影响是:delete对自增长没有影响 truncate让自增长从头开始

unique 唯一约束 表中某一列不能出现重复的值,但是可以都为null,null没有数据也就不存在重复
not null 非空约束 某一列不能是null

default 默认值 在定义字段的时候可以增加默认值,插入数据时写default关键字就可以,写null就会插入null 或者只写插入的字段及值,未写的按默认走 如 address默认 insert into s1(name) values(‘zhangsan’) 这时就会插入默认的地址
主键自增会从插入的数据开始自增,不是按插入的顺序插入,第一次默认id=1,第二次手动插入id=100,下次默认就是101 主键重复会报错

主键可以作为其他表的外键,其他字段不可以

单表存在的问题:
1.数据冗余(部门只有几个,但因为员工很多,所以部门的信息重复出现,造成数据冗余)
2.后期还会出现增删改的问题(维护困难)
解决方法:建议多表 一个员工表,一个部门表 员工表中增加字段来关联部门表 即部门表的主键作为员工表的外键,相互关联 约束别人的就是主表 被约束的就是从表 需要设置约束,从表外键不能随意更改必须是主表主键中存在的数据

外键约束 一个表中的某一个字段引用另一个表的主键,此字段就是该表的外键,需要设置外键约束,保证外键数据在主表主键的范围内
创建外键约束的语法
创建表时创建外键 create table employee(id int,name varchar(10),dep_id int,constraint empid_depid_fk foreign key(dep_id) references department(id));
创建已存在表的外键 alter table employee add constraint empid_depid_fk foreign key (dep_id) references department(id));
删除外键 alter table employee drop foreign key empid_depid_fk;

外键关联后出现一个新的问题,主表的主键不能随意更改和删除,这就是外键的级联,需要进行级联操作.即删除主键时同时删除外键,修改主键时同时修改主键,级联操作需要在表创建时定义
on update cascade 级联更新
on delete cascade 级联删除

表与表之间的关系 建表原则:
一对一:例如 员工表和简历表 1.主表的主键和从表的主键形成主外键关系 2.主表的主键是从表的外键,从表的外键唯一
一对多:例如 部门和员工 在从表(多)创建一个字段作为外键关联主表(1)的主键
多对多:例如 课程和学生 需要创建第三张表,中间表至少有两个字段,分别作为外键关联两张表的主键 在多对多的表关系中,在中间表需要创建一个复合主键(两个外键)

数据库设计的三大范式:
1.原子性:每一列不可再分割
2.不产生局部依赖,每张表只描述一件事情,表中的每一列必须完全依赖于主键
3.不产生依赖传递,表中的每一列都直接依赖于主键,而不是通过其他列间接依赖于主键

笛卡尔积:左表的每条数据和右表的每条数据分别组合,形成的结果

select * from emp,dept where emp.dept_id=dept.id;这就是隐式内连接
select * from emp inner join dept on emp.dept_id=dept.id where emp.name=‘唐僧’;这就是显式内连接 其中inner可以省略 显式内连接的条件用on 在连接完了就是一个新表,可以继续用where进行条件查询

select * from emp e left outer join demp d on e.demp_id=d.id ; 这就是左外连接 outer可以省略 在内连接的基础上,显式左表的全部数据,右表没有内容的显示null
select * from emp e right outer join demp d on e.demp_id=d.id ; 这就是右外连接 outer可以省略 在内连接的基础上,显式右表的全部数据,左表没有内容的显示null

子查询:一个查询的结果,作为另一个查询的条件 查询的嵌套,内部的查询就是子查询 子查询需要使用() 表连接查询效率要比子查询的效率高

子查询的结果可能有三种
1.单行单列 作为where后的条件 使用关系运算符 > <> = < >= <=
2.多行单列 作为where后的条件 使用in
3.多行多列 在from后作为表(表需起别名) 后面跟where条件

MySQL中有两种方式提交事务 手动 自动
手动提交事务的语句 start transaction 开启事务 commit提交 rollback 回滚
开启事务以后成功的话 提交事务 失败的话回滚事务

MySQL默认自动开启和提交事务,每一条DML都是一个独立的事务
select @@autocommit;查询事务的自动提交状态 0表示关闭 1表示开启 @@代表全局变量

  • Oracle 数据库默认是手动提交事务
  • 需要先开启事务,再提交

事务的原理,客户端连接服务器后,服务端会创建一个客户端的临时日志文件,开启事务后,执行的操作会先写入到临时日志文件中,待commit后提交到数据表.如果rollback则清空数据表.查询时从数据表查询的结果会经过临时文件加工后返回客户端,显示操作后的结果.但一旦回滚还将返回事务前的状态.

设置回滚点 savepoint 回滚点名
返回回滚点 rollback to 回滚点名

事务的四大特性:原子性(事务是不可分割的,要成功都成功,要失败都失败),一致性(事务回滚后原来数据表的结果不会发生改变,成功提交后,账户金额的总和也不会发生改变),隔离性(事务和事务之间互相隔离,互不影响),持久性(事务提交后结果是持久的)

事务并发访问出现的问题
脏读:一个事务读取到另一个事务未提交的数据
不可重复读:一个事务两次读取数据的内容不一致,这是由另一个事务update造成的
幻读:一个事务两次读取的数据条数不一致,这是由另一个事务insert 或delete造成的

MySQL数据库有四种隔离级别
读未提交 read uncommitted
读已提交 read committed oracle SQLserver
可重复读 repeatable read mysql默认
串行化 serializable
隔离级别越高,安全性越高,效率越低 串行化可以避免所有问题

设置隔离级别需要退出MySQL再登录猜可以查看到变化
查询隔离级别 select @@tx_isolation;
设置隔离级别 set global transaction isolation level 级别字符串(不带引号); 其它方法都是临时的,这个是永久的

mysqld是MySQL的主程序,服务器端 mysql是MySQL的命令行工具,客户端

grant授权 revoke废除

create user ‘用户名’@‘ip地址’ identified by ‘密码’; 创建用户 本地地址可以写localhost 允许任意远程连接的话ip地址可以写%(通配符) 密码可以为空,则不需要密码登录

新创建的用户,什么权限也没有,需要给用户授权

grant 权限1,权限2 on 数据库名.表名 to ‘用户名’@‘ip地址’;

权限 create insert select update alter 等,如果要授权全部权限的话 用all
数据库名.表名 如果授权全部数据库的全部表则 . db1.*(db1数据库的所有表)

废除权限 revoke 权限 on 数据库名.表名 from ‘用户名’@‘主机ip’;

查询权限show grants for ‘用户名’@‘ip’; 本机直接show grants;

删除用户 drop user ‘用户名’@‘ip’;

修改root 密码 退出MySQL的情况下 mysqladmin -uroot -p password 新密码(不加引号) root账号在登录mysql的情况下也可以修改密码,和普通用户一样

修改普通用户密码 set password for ‘用户名’@‘ip’ = password(‘新密码’) 本机修改可以省略中间的 for ‘用户名’@‘ip’ set password=password(‘新密码’);

修改普通用户也可以修改用户表来修改 update user set password =password(‘新密码’) where user=‘用户名’ and host=‘ip地址’;

如果忘记了root密码 可以这样解决

首先使用管理员账户登录dos命令行->net stop mysql(停止mysql服务)->mysqld --skip-grant-tables(跳过授权表访问mysql服务)->重新打开一个dos命令->mysql(直接mysql回车登录)->use mysql(切换到mysql系统数据库)->update user set password=password(‘新密码’) where user=‘root’;(修改密码)->关闭两个dos命令行->手动从任务管理器关闭mysqld进程->结束

查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询(最后是最终代码)

SELECT e.ename ,e.job_id,e.dept_id,d.id deptid,j.id jid FROM emp e,dept d,job j WHERE e.dept_id=d.id AND e.job_id=j.id
SELECT e.ename ,e.job_id,e.dept_id,d.id deptid,j.id jid FROM emp e,dept d,job j WHERE e.dept_id=d.id AND e.job_id=j.id AND j.id IN(1,2)

SELECT * FROM(SELECT e.ename ,e.job_id,e.dept_id,d.id deptid,j.id jid FROM emp e,dept d,job j WHERE e.dept_id=d.id AND e.job_id=j.id)t1 JOIN (SELECT e.ename ,e.job_id,e.dept_id,d.id deptid,j.id jid FROM emp e,dept d,job j WHERE e.dept_id=d.id AND e.job_id=j.id AND j.id IN(1,2))t2
WHERE t1.dept_id=t2.dept_id

SELECT t1.ename,t2.ename FROM(SELECT e.ename ,e.job_id,e.dept_id,d.id deptid,j.id jid FROM emp e,dept d,job j WHERE e.dept_id=d.id AND e.job_id=j.id)t1 JOIN (SELECT e.ename ,e.job_id,e.dept_id,d.id deptid,j.id jid FROM emp e,dept d,job j WHERE e.dept_id=d.id AND e.job_id=j.id AND j.id IN(1,2))t2
WHERE t1.dept_id=t2.dept_id AND
((t1.job_id >2 AND t2.job_id=2) OR ((t1.job_id =2 AND t2.job_id=1) ) OR(t1.job_id =2 AND t2.job_id=2 AND t1.ename<>‘刘备’) OR(t1.job_id =1 AND t2.job_id=1) );

使用聚合函数的时候,用单引号引起来的别名不能放在having之后 应该用字母简写或者直接写聚合函数,简写的名字不加单引号也可以

起了别名的表名,再使用表名就必须使用别名了 但是字段名只要不产生歧义都可以放在查询条件和判断条件之后 一个order by 后面可以跟两个条件,用逗号隔开

给变量赋值聚合函数 和order by以同一个聚合函数排序,会先执行赋值 再排序(聚合函数的特殊情况)

case when then when then 函数 第一个条件符合就不执行第二个了

now()和sysdate()基本一样,区别是now()在开始执行时值就得到了 sysdate()是动态获取值 都是返回日期+时间

select current_date,current_date(),current_time,current_time(),current_timestamp,current_timestamp(); 获取当前日期,时间,日期+时间

时间和字符串之间的转换 date_format(date,format) time_format(time,format) 前者可以转日期也可以转时间,后者只能转时间,如果加了日期格式,显示格式但日期都是0 %Y%m%d %H%i%s y只有08,M和D显示英文表示法,h是12小时制的时间

str_to_date(str,format) 字符串转时间 注意 格式必须和字符串的格式保持一致

日期和天数的转换 to_days(date) from_days(天数)

时间和秒的转换 time_to_sec(time) sec_to_time(秒数) 仅仅是时间

拼凑日期,时间函数 maketime(h,i,s) makedate(y,dayofyear)

unix时间的转换 Unix_timestamp([date]) 空参返回当前的毫秒数 有参返回有参的毫秒数 from_Unixtime(Unix毫秒数,[格式]) 返回当前时间默认 YYYY-mm-dd HH:ii:ss 自己加格式返回自己要的格式

时间的加减操作 date_add/data_sub(date,interval 数量 类型) 类型可以是year month day hour minute second week hour_second 等 是可以组合的,如果类型不是组合类型 直接写数字参数即可
如果是组合类型需要加单引号,因为里面不止一个值或是日期格式
组合类型出现非时分和秒的组合 必须使用 ‘num x❌x’
出现非时和分的组合必须使用’num x:x’
出现时分秒的组合必须使用’X:X:X’
其他的’num num’中间是空格(组合类出现两个相邻的单位,直接连个数字即可,分秒,时分也是这样)

datediff(date1,date2) timediff(time1,time2) 两个日期相减 返回天数 两个时间相减返回时间

timestamp(date) 将日期转换为时间戳 timestamp(date,time) 在日期上增加时间,后面只能是时间表达式’X:X:X’或’num X:X:X’前者增加时间 后者增加天数+时间
timestampadd(unit,interval,exper) 和date_add类似
timestampdiff(unit,exp1,exp2) 此功能比datediff强大,datediff只能计算天数差 timediff只能计算时间差 它可以计算各种差 但是它用表达式2减一和datediff相反,此处注意
timestampdiff 算出的间隔小于1都是0 如2018-01-01 和2018-12-31 year差0 2018-01-01 和2017-12-31 year差也是0

猜你喜欢

转载自blog.csdn.net/wwzzh1989/article/details/89310135