mysql -hlocalhost -P3306 -uroot -p
整数类型 | 字节 | 最小值(有符号/无符号) | 最大值(有符号/无符号) |
---|---|---|---|
TINYINT | 1 | -128/0 | 127/255 |
SMALLINT | 2 | -32768/0 | 32767/65535 |
MEDIUMINT | 3 | -8388608/0 | 8388607/1677215 |
INT、INTEGER | 4 | -2147483648/0 | 2147483647/4294967295 |
BIGINT | 8 | -9223372036854775808/0 | 9223372036854775807/18446744073709551615 |
int(11)表示一位的符号位,然后10位数字位。
int(M):M表示存储数值显示后的位数,M最大255,不是实际的存储的位数,
bigint(20)如果不是unsigned,表示一个符号位,19个数字位。
bigint(20)如果是unsigned,因为unsigned会扩大为原来最大值的2倍+1。此时少了一个符号位,但是数字位数多了一位。所以还是20。
想要表示宽度需要结合另外的两个参数使用,
如果不加unsigned,直接加zerofill。默认自动添加unsigned。
int(5) unsigned zerofill,表示每一个整数有5位数字,如果不足5位在左边用0填充。
如果只是单独的int(5),不会起作用。
无论int的宽度指定为多少,在内存中都是占4个字节,如果你的数字超过int(5)也可以存储
使用float和double时:
例如:double(5,2)表示的数据范围:[-999.99 , 999.99],如果超过这个范围就会报错
类似于Java的BigDecimal,底层用字符串存储
DECIMAL,DECIMAL(M,D)
date:只能表示日期 YYYY-MM-DD 范围:1000-01-01到9999-12-31
time:表示时间 HH:MM:SS -838:59:59 到 838:59:59:
datetime:表示日期和时间 YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 9999-12-31 23:59:59
year:表示年 YYYY YY(不推荐)1901-2155
timestamp:时间戳,表示日期和时间 YYYY-MM-DD
HH:MM:SS 1970-01-01 00:00:01到2038-01019 03:14:07
MySQL没有但单字符类型,只有字符串类型。注意不是字节单位!一个字母是一个字符,一个汉字也是一个字符
char(M):M个字符就占M个字符的空间
varchar:实际几个字符+2个字节的空间,varchar(20),实际存储的是’张三‘,占的2个字符+1或2个字节(用来记录实际的长度)
varchar节省空间,但是每次存和取,都要数字符个数
char:看起来浪费空间,但是每次存和取,都按照固定的长度去处理。
建议:身份证号,学号,邮编等使用char
类型 | |
---|---|
算术运算符 | +、-、*、/(除也可以写成div,但是会取整,"/"会保留小数部分)%(mod) |
比较运算符 | = > >= < <= !=(<>) <=>(安全等于) |
逻辑运算符 | &&(and)||(or) not(逻辑非) xor(逻辑异或) |
范围 | between……and……(表达式>=…… and 表达式 <=……) not between……and……(表达式<…… || 表达式 >……) |
集合 | in(值,值,值) not in(值,值,值) |
模糊查询 | like 、not like 通配符:%表示0-n个字符,_表示1个字符 |
位运算符 | &(按位与) |(按位或)^(按位异或)~(按位取反)>>(右移)<<(左移) |
NULL值判断 | is null、is not null xxx is null可以使用xxx <=> null,xxx is not null可以使用not xxx <=> null |
xor
#查询薪资大于1000 异或 性别是男的,即他俩只能满足一个。
#即薪资大于1000的女的 和薪资小于1000的男的
select * from t_employee where salary >1000 xor gender ='男'
mysqldump -h主机地址 -P端口号 -uroot -p密码 --database 数据库名 > 文件路径/文件名.sql
source sql脚本路径名.sql
对数据值是否区分大小写,和字符集和校对规则有关。
_ci(case ignore大小写不敏感),_cs(大小写敏感),_bin(二元,即比较是基于字符编码的值而与language无关,最严格,区分大小写,以二进制值存储)
命令:show character set;
在sql语句中的值,除了数值类型(整数,小数),其它类型,都用‘’引起来。
如果在sql中需要给字段取别名,可以给别名加上 “ ”,如果别名中间没有空格可以省略。
select id as “编 号” from t_employee
如果给表名取别名,不能加“ ”。
#数据库
show databases;
user 数据库名;
create database 数据库名;
drop database 数据库名;
#操作表
user 数据库名;show tables;
show tables from 数据库名;
create table [数据库名.]表名(
字段1 数据类型,
字段2 数据类型,
字段3 数据类型
)
#查看表结构 description描述简写
desc 表名称;
#修改表名称
rename table 旧表名 to 新表名;
alter table 旧表名 rename 新表明;
#修改表结构
#增加一列存储电话号码
alter table [数据库名.]表名称 add [column] 字段名 数据类型;#默认添加到最后
#增加到第一列
alter table [数据库名.]表名称 add [column] 字段名 数据类型 first;
#增加一列到指定字段名后
alter table [数据库名.]表名称 add [column] 字段名 数据类型 after 另一个字段名;
#修改字段名的 数据类型或位置
alter table [数据库名.]表名称 modify [column] 字段名 新的数据类型;
alter table [数据库名.]表名称 modify [column] 字段名 数据类型 first;
alter table [数据库名.]表名称 modify [column] 字段名 数据类型 after 另一个字段名;
#修改列的名称
alter table [数据库名.]表名称 change [column] 旧字段名 新的字段名 数据类型;
#删除一列
alter table [数据库名.]表名称 drop [column] 字段名;
#删除表
drop table [数据库名.]表名称;
insert into [数据库名.]表名称 values(值列表);
insert into [数据库名.]表名称(字段列表) values(值列表);
insert into [数据库名.]表名称(字段列表) values(值列表),(值列表),(值列表);
#如果没有where修改所有
update [数据库名.]表名称
set 字段名1 = 值,
字段名1 = 值,
字段名1 = 值
[where 条件];
#删除该表所有数据
delete from [数据库名.]表名称#一行一行的删数据
truncate [数据库名.]表名称 #删除整张表这个效率更高,但是不能回滚。
#底层是把表drop掉,然后新建了一张空表。
select * from [数据库名.]表名称;
#取别名
select 字段名 as "别名" from [数据库名.]表名称;
约束是用来对数据业务规则和数据完整性进行实施、维护。约束的作用范围仅限在当前数据库,约束可以被当做数据库对象来处理,它们具有名称和关联模。是逻辑约束,不会因为设置约束而额外占用空间。
索引是一个单独、物理的存储在数据页上的数据库结构,它是表中一列或若干列值的集合和相应的指向表中数据值的物理标识数据页的逻辑指针清单。索引的存在会增加数据库的存储空间,也会使插入、修改数据的时间开销变多(因为插入和修改数据的时候,索引也要改变),但是可以大大提高查询速度。因此应该在键列、或其它经常要查询、排序、按范围查找的列上建立索引,而对于查询中很少使用和参考的列,修改频繁的列,值很少的列(例如:性别只有男和女)等列上不应该创建索引。
MySQL会再主键、唯一键、外键列上自动创建索引,其它列需要索引的话,需要手动创建。
其中主键删除,对应的索引也会删除。
删除唯一键的方式是通过删除对应的索引来实现的。
删除外键,外键列上的索引还在,如果需要删除,需要单独删除索引。
MySQL不支持;
#mysql虽然可以定义 但是没有效果
create table t_stu(
id int primary key,
name varchar(20),
gender char check('男' or '女')
);
select * from information_schema.table_constraints where table_name = '表名';
#或者
show create table 表名;
alter table [数据库名.]表名 drop foreign key 约束名;
#查询索引名
show index from [数据库名.]表名;
drop index 索引名称(默认是字段名) on [数据库名.]表名;
主键的特点:
alter table [数据库名.]表名 add primary key(字段列表);
create table [数据库名.]表名(
字段1 数据类型,
字段2 数据类型,
字段3 数据类型,
primary key(字段列表)
)
alter table [数据库名.]表名 drop primary key;
特点:
create table [数据库名.]表名(
字段1 数据类型 ,
字段2 数据类型 ,# unique key只适用于单列的唯一键
字段3 数据类型,
primary key(字段列表),
unique key(字段列表)
);
alter table [数据库名.]表名 add unique key(字段列表);
alter table [数据库名.]表名 drop index 索引名;
特点:
create table [数据库名.]表名(
字段1 数据类型 ,
字段2 数据类型 not null,只适用于单列的唯一键
字段3 数据类型,
primary key(字段列表),
unique key(字段列表)
);
alter table [数据库名.]表名 modify 字段名 数据类型 not null;
alter table [数据库名.]表名 modify 字段名 数据类型;
特点:
create table [数据库名.]表名(
字段1 数据类型 ,
字段2 数据类型 [unique key] [not null] default 默认值,
字段3 数据类型 default 默认值,
primary key(字段列表),
unique key(字段列表)
);
insert into [数据库名.]表名(值,default,default);
insert into [数据库名.]表名(id)values(值);
alter table [数据库名.]表名 modify 字段名 数据类型 default 默认值 [not null];
alter table [数据库名.]表名 modify 字段名 数据类型;#default 和 not null 都会删除
特点:
一个表只能有一个自增约束。因为一个表只能有一个维护自增值的变量。
自增约束的列必须是整数列。
自增约束的列必须是键列(主键,唯一键,外键)。实际中主键最多。
自增列如何自增
如果指定值(如果不是unsigned 可以是负数),就按照指定的来,没有指定就自增。
如果指定的值为0或null,按照自增的来。
如果中间有空余的比方说1 2 3 7 8中间没有4 5 6。插入一次4后下次不指定值以最大的8自增。
create table [数据库名.]表名(
字段1 xxInt primary key auto_increment,
字段2 数据类型 ,
字段3 数据类型 default 默认值,
);
alter table [数据库名.]表名 modify 字段名 xxxint auto_increment;
alter table [数据库名.]表名 modify 字段名 数据类型;
特点:
建表先建主表,再键从表;
删表先删从表,再删主表;
从表、子表:参考别人的,依赖别人的。
主表、父表:被参考的,被依赖的。
举例:
1、部门表和员工表。员工表中有一个字段,表示该员工所在的部门。
部门表是主表
员工表是从表,说员工选择进入哪个部门。
外键建立在员工表中
2、学生,课程,选课表
学生,课程是主表
选课表是从表
删除外键后,索引还会存在。
create table [数据库名.]表名(
字段1 xxInt primary key auto_increment,
字段2 数据类型 ,
字段3 数据类型 default 默认值,
。。。,
[constraint 外键约束名] foreign key(从表的某字段) references 主表名(被参考的字段) [on update 等级] [on delete 等级]
#外键约束名可以是 从表名_主表名_字段名_fk
);
#修改
alter table [数据库名.]表名 add [constraint 外键约束名] foreign key(从表的某字段) references 主表名(主表被引用字段) [on update 等级] [on delete 等级];
#删除先查看外键约束名
select * from information_schema.table_constraints where table_name = '表名';
alter table [数据库名.]表名 drop foreign key 约束名;
函数 | 用法 |
---|---|
concat(s1,s2,…) | 连接s1,s2,s3…为一个字符串 |
concat_ws(s,s1,s2,s3,…) | 同concat函数,但是以s作为连接符。 |
char_length(s) | 返回字符串的s的字符数 |
length(s) | 返回字符串s的字节数,和字符集有关 |
insert(str,index,len,instr) | 将字符串str从第index位置开始,len个字符长的子串替换为字符串instr |
upper(s)或ucase(s) | 所有字母转化成大写字母 |
lower(s)或lcase(s) | 所有字母转化为小写字母 |
left(s,n) | 返回字符串最左边n个字符 |
right(s,n) | 返回字符串最右边n个字符 |
lpad(str,len,pad) | 用字符串pad对str最左边进行填充,直到str的长度为len个字符 |
rpad(str,len,pad) | 用字符串pad对str最右边进行填充,直到str的长度为len个字符 |
ltrim(s) | 去掉字符串s左侧的空格 |
rtrim(s) | 去掉字符串s右侧的空格 |
trim(s) | 去掉字符串s开始与结尾的空格 |
trim([both] s1 from s) | 去掉字符串s开始与结尾的s1 |
trim([leading] s1 from s) | 去掉字符串s开始处的s1 |
trim([trailing] s1 from s) | 去掉字符串s结尾处的s1 |
repeat(s,n) | 返回字符串s重复n次的结果 |
replace(str,a,b) | 用字符串b替换字符串str中所有出现的字符串a |
strcmp(s1,s2) | 比较字符串s1,s2 |
substring(s,index,len) | 返回从字符串s的index位置起len个字符,index不是下标,是第几个字符。 |
函数 | 用法 |
---|---|
abs(x) | 返回x的绝对值 |
ceil(x) | 返回大于x的最小整数值 |
floor(x) | 返回小于x的最大整数值 |
mod(x,y) | 返回x/y的模 |
rand() | 返回0到1之间的随机值。 |
round(x,y) | 返回参数x的四舍五入,有 |
truncate(x,y) | x截断y位小数,多的直接舍去,少的填0。 |
pow(x,y) | x的y次方 |
sqrt(x) | 返回x的平方根 |
函数 | 用法 |
---|---|
now(), sysdate(), current_timestamp(), localtime(), localtimestamp() |
当前系统时间yyyy-MM-dd HH:mm:ss |
curdate(), current_date() | 只有日期 |
curtime(), current_time() | 只有时间 |
year(date), month(date), day(date), hour(time), minute(time), seconde(time) |
yyyy-MM-dd HH:mm:ss |
week(date), weekofyear(date) | 一年中的第几周 |
dayofweek(date) | 返回周几,周日是1,周一是2,周六是7 |
weekday(date) | 返回周几,周一是0,周二是1,周日是6 |
dayname(date) | 返回星期,MONDAY,TUESDAY…SUNDAY |
monthname(date) | 返回月份January,February,March… |
datediff(date1,date2)/timediff(time1,time2) | 返回date1-date2的时间间隔(多少天)/返回time1-time2的时间间隔(HH:mm:ss,最大838:59:59) |
date_add(datetime,INTERVAL expr type) | 返回与给定日期时间增加exper(数值,可以为负数),type(类型)时间的日期。eg:date_add(now(),interval 3 year);增加3年 |
date_format(datetime,fmt) | 按照字符串fmt格式化日期datetime值 |
str_to_date(str,fmt) | 将字符串按照fmt格式化为日期 |
'%Y-%m-%d %H:%i:%s' #是这样的格式2019-3-24 13:02:01
格式符 | 说明 |
---|---|
%Y | 表示4位数字表示年份 |
%y | 表示两位数字表示年份 |
%M | 月名表示月份(January,…) |
%m | 两位数字表示月份(01,02,…) |
%b | 缩写的月份名(Jan,Feb,…) |
%c | 表示月份(1,2,3) |
%D | 英文后缀表示月中的天数(1st,2nd,3rd) |
%d | 两位数字表示月中的天数(01,02,…) |
%e | 数字形式表示月中天数(1,2,3,…) |
%H | 两位数字表示小时,24小时制(01,02,…) |
%h和%I(大写的i) | 两位数字表示小时,12小时制(01,02,…) |
%k | 数字形式的小时,24小时制(1,2,3) |
%l(小写的L) | 数字形式的小时,12小时制(1,2,3) |
%i | 两位数字表示分钟(00,01,02) |
%S,%s | 两位数字表示秒(00,01,02) |
%W | 一周中的星期名称(Monday,Tuesday,…) |
%a | 一周中的星期名称缩写(Mon,Tue,…) |
%w | 以数字表示周中的天数,(0=Sunday,1=Monday) |
函数 | 用法 |
---|---|
if(value, t, f) | 如果value是真,返回t,否则返回f |
ifnull(value1, value2) | 如果value1不为NULL,返回value1,否则返回value2. |
CASE WHEN 条件1 THEN result1 WHEN 条件2 THEN result2… [ELSE resultn] END |
相当于java的if… else if… else… 。 |
CASE expr WHEN 常量值1 THEN result1 WHEN 常量值2 THEN result2… [ELSE resultn] END |
相当于java中的switch(expr) case |
函数 | 用法 |
---|---|
database() | 返回当前数据库名 |
version() | 返回当前数据库版本 |
user() | 返回当前登录用户名 |
password(str) | 返回字符串str的加密版本,41位长的字符串。(mysql8中移出了该函数) |
md5(str) | 返回字符串的md5值,也是加密 |
如何实现这些结果
如果少了关联条件会出现笛卡尔积,(全排列)
select 字段列表
from A表名 inner join B表名
on 1个关联条件
where 其他条件等
select 字段列表
from A表名 inner join B表名 inner join C表名
on 2个关联条件
where 其他条件
select 字段列表
from A表名 , B表名 , C表名
where 2个关联条件 and 其他条件
A :其中A表中所有列都会显示(即使,该关联的字段为null,另一个表中没有)
select 字段列表
from A表名 left join B表名
on 关联条件
where 其他条件等
A-A∩B:只会显示没有关联的列(即关联字段为null)
select 字段列表
from A表名 left join B表名
on 关联条件
where 关联字段(从表) is null and 其他条件等
和左连接对应,正好相反。
A∪B:A union B
select 字段列表
from A表名 left join B表名
on 关联条件
where 其他条件等
UNION
select 字段列表
from A表名 right join B表名
on 关联条件
where 其他条件等
A∪B - A ∩ B :A - A ∩ B union B - A ∩ B
select 字段列表
from A表名 left join B表名
on 关联条件
where 关联字段(从表) is null and 其他条件等
UNION
select 字段列表
from A表名 right join B表名
on 关联条件
where 关联字段(从表) is null and 其他条件等
一种特殊的联合查询,因为现在联合查询的两种表本质是一个表。通过取别名,模拟两张表
select 字段列表
from 表名 别名1 inner/left/right join 表名 别名2
on 别名1.关联字段 = 别名2.关联字段
where 其他条件
PS:书写顺序是1-6;
在一个查询中嵌套了另一个查询,那么这个嵌套在里面的查询称为子查询。子查询的结果作为外部查询的条件或者数据的筛选范围来使用。
where型:子查询的结果作为外部查询的条件使用的。
#比这几个人都高的薪资
select *
from t_employee
where salary > ALL(xxx,xxx,xx)
#查找这几个人的薪资
select *
from t_employee
where name in(xxx,xxx,xx)
select *
from t_employee
where name = ANY(xxx,xxx,xx)
from型:子查询的结果是作为外部查询的筛选范围来使用的。
#对子查询的多行多列的二维表结构的临时表取别名。给分组函数取别名。
select 部门.id , 部门.name, temp.countOfDep
from 部门 inner join (select id,count(*) as countOfDep from 部门 group by id) temp
on 部门.id = temp.id
exists型:子查询的结果是作为外部查询的条件使用的。
#查询部门信息,要求这些部门必须有员工
select * from 部门
where exists(
select * from 员工
where 部门.id =员工.部门id
)
#将部门中的信息带入子查询去匹配,如果能查询出记录就保留,否则去掉
事务处理:保证所有事物都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有操作都被提交(commit),修改永久保存下来了;要么数据库管理系统将放弃所有的修改,整个事务回滚(rollback)到最初状态。
方式一
set autoCommit=false;
…都是需要手动提交的。
set autoCommit=true;
方式二
start transaction;
一个事务
commit;或rollback;
同一个库的同一个表同一个记录,对于多个事务来说,就是共享数据。多个事务被多个线程同时执行时,那么共享数据就会线程安全问题。
几种问题:
脏读现象:事务1对某个记录进行修改,还未提交。事务2就看到了。那么这个被事务1修改还未提交的数据就是脏数据。
不可重复的:事务1对某个表进行修改,已经提交。但是事务2在事务1提交之前,查询了这个记录,在事务1提交后,又查询了这个记录,对于事务2出现了不可重复读的现象。在同一个事务中,前后两次对同一个记录的读取结果不一样。
幻读:事务1给某个表添加了新的记录,或者删除了某个记录。记录数有变化。并且提交了。
事务2,在事务1提交之前,查询了这个表,在事务1提交之后,查询了这个表。
对于事务2来说前后两次的记录数不一样。
但是MySQL在升级了隔离级别3,也可以避免幻读。
-- mysql 5版本
select @@tx_isolation;
set tx_isolation = 'read-uncommitted';
-- mysql 8版本 改名了
select @@transaction_isolation;
set transaction_isolation = '';
事务回滚和提交只对insert、update、delete有效。
对create、drop等DDL语句无效。
如果前面的通过了,后面就不校验了。
show grants for user@host
user:用户名 (root)
host:主机ip (localhost)
注意:要用管理员权限打开cmd命令行。
停止你的mysql服务
一般使用net stop mysql(如果你没有修改过服务名默认mysql)
在随便一个地方新建一个txt文档,名字随意。
比如我在c盘output目录下新建了个reset.txt,输入以下内容,设置密码为123456(修改成你的)。
alter user 'root'@'localhost' identified by '123456';
在命令行中输入以下内容,文件路径是你的txt文档路径,显示几行东西后后关闭窗口即可。
mysqld --init-file=c:\output\reset.txt --console
重新启动mysql服务,用你的新密码登录即可。
net start mysql
如果你没有忘记密码,只是想修改密码。
直接登录进去,然后使用该命令即可修改密码
alter user 'root'@'localhost' identified by '123456';