mysql随笔
Posted 苏克俊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql随笔相关的知识,希望对你有一定的参考价值。
SQL: Structured Query Language, 结构化查询语言(数据以查询为主: 99%是在进行查询操作)
数据结构: 二维表(没有数据也要占用空间,比较浪费空间)
1.SQL分为三个部分
-DDL: Data Definition Language, 数据定义语言, 用来维护存储数据的结构(数据库,表), 代表指令: create, drop, alter等
-DML: Data Manipulation Language, 数据操作语言, 用来对数据进行操作(数据表中的内容), 代表指令: insert, delete,update等: 其中DML内部又单独进行了一个分类: DQL(Data Query Language: 数据查询语言, 如select)
-DCL: Data Control Language, 数据控制语言, 主要是负责权限管理(用户), 代表指令: grant,revoke等
2.mysql服务器内部对象分成了四层: 系统(DBMS) -> 数据库(DB) -> 数据表(Table) -> 字段(field)
3.用show查看MySQL数据库、表和内部信息
status; 查看mysql信息
select version(); 查看mysql版本
exit;/quit;\q; 退出mysql
show databases; 返回可用数据库的列表
show tables; 获取当前选择的数据库内可用表的列表
show columns from tests;和describe tests; 获取当前数据库中的某个表tests的数据结构
show status; 显示广泛的服务器状态信息
show grants; 用来显示授权用户的安全权限
show errors;和show warnings; 显示服务器错误和警告消息
show plugins; 显示MySQL支持的所有数据库引擎
show table status; 显示数据表的默认状态信息
show open tables; 查看被打开过的数据库和数据表
show create database test; 查看创建数据库test的SQL语句
show create table test; 查看创建数据表test的SQL语句
show privileges; 查看一些常用的SQL操作语句的作用和说明描述;
show character set; 查看所有字符集
show variables like ‘%char%‘; 查看默认字符集
-------------------------------------------------------------------------------------------------------------------------------------------------------------
4.新增数据库
-Create database 数据库名字 [库选项];
create database mydatabase charset utf8;
--库选项: 用来约束数据库, 分为两个选项:
字符集设定: charset/character set 具体字符集(数据存储的编码格式): 常用字符集: GBK和UTF8
校对集设定: collate 具体校对集(数据比较的规则)
注意:校对集依赖字符集,只需改字符集即可
--数据库名字不能用关键字(已经被使用的字符)或者保留字(将来可能会用到的),如果非要使用关键字或者保留字,那么必须使用反引号(esc键下面的键在英文状态下的输出:`)
create database `database` character set utf8;
--中文数据库是可以的,但是有前提条件: 保证服务器能够识别(建议不用)
解决办法:告诉服务器当前中文的字符集是什么:set names utf8;(cmd下只识别gbk字符编码)
5.查看数据库:
-查看所有数据库:show databases;
-查看指定部分的数据库: 模糊查询
Show databases like ‘pattern’; //pattern是匹配模式(%: 表示匹配多个字符,_: 表示匹配单个字符
-查看数据库的创建语句: show create database 数据库名字;
注意:数据库在执行sql语句之前会优化sql,系统保留的结果是优化后的结果
6.更新数据库
-数据库名字不可以修改.
-数据库的修改仅限库选项: 字符集和校对集(校对集依赖字符集)
Alter database 数据库名字 [库选项];
7.删除数据库(级联删除:里面的数据表全部删除)
Drop database 数据库名字;
注意:不要随意删除,应该先进行备份后操作.(删除不可逆)
-------------------------------------------------------------------------------------------------------------------------------------------------------------
8.新增数据表
Create table [if not exists] 表名( //此处数据库名.表名或者使用:use 数据库名字;先进入数据库环境
字段名字 数据类型,
字段名字 数据类型 //最后一行不需要逗号
)[表选项];
-If not exists: 如果表名不存在,那么就创建,否则不执行创建代码: 检查功能
-表选项: 控制表的表现
字符集: charset/character set 具体字符集; //保证表中数据存储的字符集
校对集: collate 具体校对集;
存储引擎: engine 具体的存储引擎(innodb和myisam)
9.查看数据表
-查看所有表: show tables;
-查看部分表: 模糊匹配: show tables like ‘pattern’; //注意:%不要放前面,效率低
-查看表的创建语句: show create table 表名; //其中语句后分号和\g效果相同,\G竖向查看
-查看表结构:Desc/describe/show columns from 表名;
Field:字符名称;Type:字段类型;NULL:是否允许为空;Key:索引类型(主键/唯一等);Default:默认值;Extra:扩充(自增长等)
10.修改表
-修改表名:rename table 老表名 to 新表名; //表的命名一般取数据库名字前两个字母,例如my_student;
-修改表选项: alter table 表名 表选项 [=] 值;
11.修改字段
-新增字段:alter table 表名 add [column] 字段名 数据类型 [列属性] [位置];
位置:first: 第一个位置;after 字段名; 默认的是在最后一个字段之后
alter table student add column id int first;
-修改字段:alter table 表名 modify 字段名 数据类型 [属性] [位置];
alter table student modify name char(10) first;
-重命名字段:alter table 表名 change 旧字段 新字段名 数据类型 [属性] [位置];
-删除字段:alter table 表名 drop 字段名; //删除字段会清空该字段的所有数据(不可逆)
12.删除数据表
Drop table 表名1,表名2...; //可以一次性删除多张表
-------------------------------------------------------------------------------------------------------------------------------------------------------------
13.新增数据
方案1: 给全表字段插入数据,与表中设计的字段出现的顺序一致
insert into 表名 values(值列表)[,(值列表)]; //可以一次性插入多条记录
方案2: 给部分字段插入数据
insert into 表名 (字段列表) values (值列表)[,(值列表)];
14.查看数据
Select */字段列表 from 表名 [where条件];
15.更新数据
Update 表名 set 字段 = 值 [where条件]; //建议都有where: 要不是更新全部
16.删除数据
Delete from 表名 [where条件];
-------------------------------------------------------------------------------------------------------------------------------------------------------------
17.中文数据问题
-查看服务器到底识别哪些字符集: show character set;
-查看服务器默认的跟客户端打交道的字符集: show variables like ‘character_set%‘;
服务器默认的客户端来的数据的字符集: _client
连接层字符集: _connection
当前所在数据库字符集: _database
服务器默认的给外部数据的字符集: _results
-改变服务器, 默认的接收字符集: set character_set_client和_results = gbk;
-快捷方式: set names 字符集;或者charset 字符集;
注意:修改只是会话级别(当前客户端,当次连接有效: 关闭失效)
根据客户端编码先设置当前控制台字符集
-------------------------------------------------------------------------------------------------------------------------------------------------------------
18.校对集
-校对集有三种格式
_bin: binary,二进制比较, 取出二进制位,一位一位的比较, 区分大小写
_cs: case sensitive,大小写敏感, 区分大小写
_ci: case insensitice,大小写不敏感,不区分大小写
-查看数据库所支持的校对集: show collation;
-创建不同校对集对应的表
create table my_collate_bin(name char(1))charset utf8 collate utf8_bin或utf8_ci;
-并排序: order by 字段名 [asc|desc]; asc升序,desc降序,默认是升序
select * from my_collate_bin order by name;
注意: 只有当数据产生比较的时候,校对集才会生效;
必须在没有数据之前生命好,如果有了数据,那么再进行校对集修改: 那么修改无效.
-------------------------------------------------------------------------------------------------------------------------------------------------------------
19.数据类型(列类型)
-数值类型(数字类型后面的显示宽度,其中负号算一位)
--整数型:在SQL中因为更多要考虑如何节省磁盘空间, 所以系统将整型又细分成了5类:
Tinyint: 迷你整型,使用一个字节存储, 表示的状态最多为256种(常用)
Smallint: 小整型,使用2个字节存储,表示的状态最多为65536种
Mediumint: 中整型, 使用3个字节存储
Int: 标准整型, 使用4个字节存储(常用)
Bigint: 大整型,使用8个字节存储
例如:insert在tinyint中255会报超出范围或者只插入127(新版本),范围-128~127可通过
alter table my_int add int_5 tintyint unsigned来添加一个无符号tinyint类型,范围0~255
显示宽度的意义: 显示宽度不足,0来补齐, 不改变值大小: zerofill(零填充): 零填充会导致数值自动变成无符号
--小数型:SQL中: 将小数型细分成两种: 浮点型和定点型
---浮点型:因为超出指定范围之后, 会丢失精度(自动四舍五入)
Float: 单精度, 占用4个字节存储数据, 精度范围大概为7位左右
Double: 双精度,占用8个字节存储数据, 精度方位大概为15位左右
注意: 1.float表示没有小数部分; float(M,D): M代表总长度,D代表小数部分长度
2.浮点型数据的插入: 整型部分是不能超出长度的,小数部分超出会自动四舍五入
3.浮点数超出精度范围一定会四舍五入: 浮点数如果是因为系统进位导致整数部分超出指定的长度,那么系统也允许成立.
---定点型:Decimal不会丢失精度,自动扩充精度
注意:整数部分一定不能超出长度(进位不可以),小数部分超出自动四舍五入
-时间日期类型
Datetime: 时间日期, 格式是YYYY-mm-dd HH:ii:ss
Date: 日期,就是datetime中的date部分
Time: 时间(段),可以是负数(过去)
Timestamp: 时间戳,从1970年开始的YYYY-mm-dd HH:ii:ss
注意:只要当前所在的记录被更新, 该字段一定会自动更新成当前时间
Year: 年份,两种形式:
year(2):范围1970~2069
year(4):范围1901~2155
-字符串类型
定长字符串:char
变长字符串: varchar,多处1到2个字节来确定存储的实际长度
例如:Varchar(10):存储了3个汉字: 3 * 3 + 1 = 10(bytes)
注意:如何选择?
定长浪费磁盘空间、效率高,如身份证, 电话号码, 手机号码等
变长节省磁盘空间、效率低,如姓名, 地址等
-文本字符串(如果数据量非常大, 通常说超过255个字符就会使用文本字符串)
Text: 存储文字(二进制数据实际上都是存储路径)
Blob: 存储二进制数据(通常不用)
-枚举字符串:enum
枚举原理: 枚举在进行数据规范的时候(定义的时候),系统会自动建立一个数字与枚举元素的对应关系(关系放到日志中): 然后在进行数据插入的时候,系统自动将字符转换成对应的数字存储, 然后在进行数据提取的时候, 系统自动将数值转换成对应的字符串显示.
create table my_enum(gender enum(‘男‘,‘女‘,‘保密‘))charset utf8;
insert intomy_enum values(‘男‘,‘女‘);
>枚举实际存储的是数值,所以可以直接插入数值:insert into my_enum values(1);效果同insert一个‘男‘
>证明字段存储的数据是数值: 将数据取出来 + 0 就可以判断出原来的数据存的到底是字符串还是数值: 如果是字符串最终结果永远为0, 否则就是其他值.
select gender+0,gender from mu_enum;
枚举作用: 作用之一: 规范数据格式: 数据只能是规定的数据中的其中一个
作用之二: 节省存储空间(枚举通常有一个别名: 单选框): 枚举实际存储的是数值而不是字符串本身.
缺点:需要事先定义,操作时会内部转换,效率比较低
-集合字符串:Set(元素列表)
create table my_set(hobby set(‘篮球‘,‘足球‘,‘网球‘))charset utf8;
insert into my_set values(‘篮球,足球‘); //注意此处是字符串
>集合跟枚举很类似: 实际存储的是数值,而不是字符串(集合是多选)
>集合中没一个元素都是对应一个对应二进制位,所以insert into my_set values(3);是插入‘篮球‘和‘足球‘
>集合中元素的顺序没有关系: 最终系统都会根据插入位去匹配顺序
>集合的强大在于能够规范数据和节省空间
-------------------------------------------------------------------------------------------------------------------------------------------------------------
20.Mysql记录长度
-Mysql中规定: 任何一条记录最长不能超过65535个字节.(varchar永远达不到理论值)
Utf8 下varchar的实际顶配: 21844字符
GBK下的varchar的实际顶配: 32766字符
想用完整个65535个字节长度: 增加一个tinyint字段即可
如果有任何一个字段允许为空,那么系统会自动从整个记录中保留一个字节来存储NULL(若想释放NULL所占用的字节: 必须保证所有的字段都不允许为空)
create table my_utf8(age tinyint not null,name varchar(21844) not null) charset utf8;
-Mysql中text文本字符串,不占用记录长度: 额外存储. 但是text文本字符串也是属于记录的一部分: 一定需要占据记录中的部分长度: 10个字节(保存数据的地址以及长度).
create table my_text(name varchar(21841) not null,content text not null)charset utf8;
-------------------------------------------------------------------------------------------------------------------------------------------------------------
21.列属性
-空属性:NULL(默认的)和NOT NULL(不为空)
-列描述: comment。
create table my_teacher(name varchar(20) not null comment ‘姓名‘) charset utf8;
可通过查看表创建语句查看列描述:show create table my_teacher;
-默认值: default
不想写值可以使用default关键字代替值
-主键: primary key。一张表只能有最多一个主键
--增加主键
方案1: 在字段之后加primary key关键字(主键本身不允许为空):
方案2: 在所有的字段之后使用primary key创建主键(如果有多个字段作为主键,可以是复合主键)
create table my_pri(number char(10) comment ‘学号‘,course char(10) comment ‘课程‘,score tinyint unsigned default 60 comment ‘成绩‘,primary key(number,course))charset utf8;
方案3: 当表已经创建好之后, 额外追加主键: 可以通过修改表字段属性, 也可以直接追加。但是表中字段对应的数据本身是独立的(不重复)
Alter table 表名 add primary key(字段列表);
alter table student add primary key (name);
--更新主键 & 删除主键
主键必须先删除,才能增加:alter table 表名 drop primary key;
--主键分类
业务主键:实际创建表的过程中, 很少使用真实业务数据作为主键字段,如学号,课程号
逻辑主键:大部分的时候是使用逻辑性的字段(字段没有业务含义,值是什么都没有关系)
--自增长: auto_increment。通常是跟主键搭配
>任何一个字段要做自增长必须前提是本身是一个索引(key一栏有值)
>自增长字段必须是数字(整型)
>一张表最多只能有一个自增长
--自增长使用
>NULL或者默认值的时候会触发自动增长.
>字段输入了值,那么自增长失效: 下一次从最大值开始自增长
>下一次是从多少开始自增长,通过查看表创建语句看到:show create table my_auto;
--修改自增长
>字段改变: 先删除自增长,后增加(一张表只能有一个自增长)
>修改当前自增长的值: 只能比当前已有的自增长的最大值大,不能小(小不生效)
Alter table 表名 auto_increment = 值;
>修改自增长起始值和步长(一般不会去做)
查看自增长对应的变量: show variables like ‘auto_increment%’;
修改是对整个数据修改,而不是单张表: (修改是会话级)Set auto_increment_increment = 5;
--删除自增长
Alter table 表名 modify 字段 类型; --去掉自增长即可
-唯一键(唯一键默认的允许自动为空,而且可以多个为空)
--增加唯一键
>方案1: 在创建表的时候,字段之后直接跟unique/ unique key
>方案2: 在所有的字段之后增加unique key(字段列表); -- 复合唯一键
create table my_unique(number char(10) not null comment ‘学号‘,name varchar(10) not null,unique key(number))charset utf8;
//注意:此处number显示为PRI原因:列属性为不为空的唯一键,并且该表没有主键,但他的性质并不是主键,可通过查看创建表语句查看
>方案3: 在创建表之后增加唯一键
alter table my_unique add unique key(name);
--唯一键约束
唯一键与主键本质相同: 唯一的区别就是唯一键默认允许为空,而且是多个为空。如果唯一键也不允许为空: 与主键的约束作用是一致的.
--更新唯一键 & 删除唯一键
先删除后新增(唯一键可以有多个: 可以不删除).
---删除唯一键
Alter table 表名 drop unique key; -- 错误: 唯一键有多个
Alter table 表名 drop index 索引名字; -- 唯一键默认的使用字段名作为索引名字
alter table my_unique drop index name;
-索引(几乎所有的索引都是建立在字段之上)
来处:系统根据某种算法, 将已有的数据(未来可能新增的数据),单独建立一个文件: 文件能够实现快速的匹配数据, 并且能够快速的找到对应表中的记录.
好处:提升查询数据的效率,约束数据的有效性(唯一性等)
坏处:索引本身会产生索引文件(有时候有可能比数据文件还大) ,会非常耗费磁盘空间.
应用场景:字段作为查询条件, 查询效率很低(一条一条记录去匹配),想办法增加索引,会去索引文件查询出索引,效率大大提高;
字段需要有效性约束, 也可能使用索引(主键,唯一键)
Mysql中提供了多种索引
>主键索引: primary key
>唯一索引: unique key
>全文索引: fulltext index //有待学习(中文分词sphinx)
>普通索引: index
-------------------------------------------------------------------------------------------------------------------------------------------------------------
22.关系
一对一,一对多,多对多(添加多对多)
-------------------------------------------------------------------------------------------------------------------------------------------------------------
23.范式(Normal Format):
是一种离散数学中的知识, 解决一种数据的存储与优化的问题: 保存数据的存储之后, 凡是能够通过关系寻找出来的数据,坚决不再重复存储: 终极目标是为了减少数据的冗余.
一种分层结构的规范,分为六层,1NF,2NF,3NF...6NF, 1NF是最底层,要求最低;6NF最高层,最严格,若要满足下一层范式,前提是满足上一层范式.
Mysql属于关系型数据库: 有空间浪费: 也是致力于节省存储空间: 与范式所有解决的问题不谋而合: 在设计数据库的时候, 会利用到范式来指导设计.
但是数据库不单是要解决空间问题,要保证效率问题: 范式只为解决空间问题, 所以数据库的设计又不可能完全按照范式的要求实现: 一般情况下,只有前三种范式需要满足.
-第一范式: 字段具有原子性,不可再分
-第二范式:如果有复合主键,且字段存在依赖部分主键的问题,称之为部分依赖。第二范式就是要解决表设计不允许出现部分依赖.
>解决方案1: 可以将依赖字段和被依赖主键单独成表
>解决方案2: 取消复合主键, 使用逻辑主键,及加一个逻辑ID
-第三范式:莫些字段不是直接依赖主键,而是依赖非主键字段的依赖关系称之为传递依赖.第三范式就是要解决传递依赖的问题.
解决方案: 将存在传递依赖的字段以及被依赖的字段单独取出,形成一个单独的表, 然后在需要对应的信息的时候, 使用对应的实体表的主键加进来.
24.逆规范化
如果一张表中经常有几个字段是需要从另外的表中去获取信息,但是多表查询效率低,有时为了提高查询效率,会刻意的在某些表中不去保存另外表的主键(逻辑主键), 而是直接保存想要的数据信息,但是会导致数据冗余增加.
及磁盘利用率与效率的对抗。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
25.数据操作
-新增数据
Insert into 表名 [(字段列表)] values (值列表);
主键冲突(假设主键对应的值已经存在: 插入一定会失败!)
>更新操作:Insert into 表名[(字段列表:包含主键)] values(值列表) on duplicate key update 字段 = 新值;
>替换:Replace into 表名 [(字段列表:包含主键)] values(值列表);
蠕虫复制
从已有的数据中去获取数据,然后将数据又进行新增操作: 数据成倍的增加.
先从已有表创建新表(复制表结构):Create table 表名 like 数据库.表名;
蠕虫复制: 先查出数据, 然后将查出的数据新增一遍:Insert into 表名[(字段列表)] select 字段列表/* from 数据表名;
应用: >从已有表拷贝数据到新表中
>可以迅速的让表中的数据膨胀到一定的数量级: 测试表的压力以及效率
-更新数据
基本语法:Update 表名 set 字段 = 值 [where条件];
update my_copy set name=‘c‘ where name=‘a‘ limit 3; --更新前3条匹配记录
高级新增语法:Update 表名 set 字段 = 值 [where条件] [limit 更新数量];
-删除数据:Delete from 表名 [where条件] [limit 数量];
Truncate 表名; -- 先删除改变,后新增改变,及清空数据并重建表,
-查询数据
--Select [select选项] 字段列表[字段别名]/* from 数据源 [where条件子句] [group by子句] [having子句] [order by子句] [limit 子句];
--Select选项: select对查出来的结果的处理方式
All: 默认的,保留所有的结果
Distinct: 去重, 当所有字段都相同时才可用
--字段别名:字段名 [as] 别名;
--数据源(关系型数据库的来源都是数据表: 本质上只要保证数据类似二维表):
---单表数据源: select * from 表名;
---多表数据源: select* from 表名1,表名2...; --小心笛卡尔积
---子查询: 数据的来源是一条查询语句(查询语句的结果是二维表):Select * from (select 语句) as 表名;
--where子句
用来判断数据,筛选数据。子句返回结果: 0或者1, 0代表false,1代表true.
判断条件: 比较运算符: >, <, >=, <= ,!= ,<>, =, like, between and, in/not in ;逻辑运算符: &&(and), ||(or), !(not)
>Where原理: where是唯一一个直接从磁盘获取数据的时候就开始判断的条件,判断的结果如果成立保存到内存,如果失败直接放弃
--Group by子句: group by 字段名1,字段名2;
分组统计数据,统计函数:Count(): 记录数;Max():最大的值;Min(): 最小值Avg():平均值;Sum(): 和
注意:Count函数: 里面可以使用两种参数: *代表统计记录,字段名代表统计对应的字段(NULL不统计)
分组会自动排序: 根据分组字段:默认升序。Group by 字段 [asc|desc];--合并之后的整个结果进行排序
某个字段进行字符串连接(保留该组所有的某个字段): group_concat(字段);
--Having子句
与where子句一样都可以进行条件判断,Having能做where能做的几乎所有事情, 但是where却不能做having能做的很多事情
>分组统计的结果或者说统计函数都只有having能够使用:select id,count(*) from student group by id having count(*)>=2;
>Having能够使用字段别名: where不能: where是从磁盘取数据,而名字只可能是字段名: 别名是在字段进入到内存后才会产生.
--Order by子句(依赖校对集)
Order by 字段名 [asc|desc]; -- asc是升序(默认的),desc是降序,可以进行多字段排序
-Limit子句
限制结果的语句: 限制数量
>限制长度:查询前两个;select * from student limit 2;
>限制起始位置:limit 起始位置,长度;常用于分页
-连接查询
--内连接:左表 [inner] join 右表 on 左表.字段 = 右表.字段;
左表中取出每一条记录,去右表中与所有的记录进行匹配。
注意:1.字段别名以及表别名的使用:不同表有同名字段,这个时候需要加上表名才能区分, 而表名太长, 通常可以使用别名.
select s.*,c.name as c_name,c.room from -- 字段别名
my_student as s inner join my_class as c -- 表别名
on s.c_id = c.id;
2.on之后没有内容,这个时候系统会保留所有结果(笛卡尔积)
3.内连接还可以使用where代替on关键字(where没有on效率高)
--外连接:左表 left/right join 右表 on 左表.字段 = 右表.字段;
outer join, 以某张表为主,不管能不能匹配上条件,最终都会保留: 能比配,正确保留; 不能匹配,其他表的字段都置空NULL.
Left join: 左外连接(左连接), 以左表为主表
Right join: 右外连接(右连接), 以右表为主表:
例如:select s.*,c.name as c_name,c.room from
my_student as s left join my_class as c -- 左表为主表: 最终记录数至少不少于左表已有的记录数
on s.c_id = c.id;
--自然连接:左表 natural join 右表; --注意:最好不要用
自动匹配连接条件:系统以同名字段就作为条件, 多个同名字段都作为条件
--自然内连接: 左表 natural join 右表;
select * from my_student natural join my_class; --注意:连接之后会自动合并同名字段
--自然外连接: 左表 natural left/right join 右表;
--交叉连接:左表 cross join 右表; ===== from 左表,右表; 笛卡尔积,产生n*n个匹配数据 --不要用
交叉连接存在的价值: 保证连接这种结构的完整性。但没有实际应用。
--多表连接: A表 inner join B表 on 条件 left join C表 on条件 ...
执行顺序: A表内连接B表,得到一个二维表, 左连接C表形成二维表...
-外键:foreign key
键不在自己表中,如果一张表中有一个字段(非主键)指向另外一张表的主键,那么将该字段称之为外键.
--增加外键
--创建表的时候增加外键: foreign key(外键字段) references 外部表(主键字段)
--在新增表之后增加外键: 修改表结构:Alter table 表名 add [constraint 外键名字] foreign key(外键字段) references 父表(主键字段);
alter table my_foreign2 add constraint student_class_1 foreign key(c_id) references my_class(id);
--修改外键&删除外键
外键不可修改: 只能先删除后新增.
Alter table 表名 drop foreign key 外键名; -- 一张表中可以有多个外键,但是名字不能相同
注意:外键删除不能通过查看表结构体现,可通过查看创建表语句查看
--外键作用
--对子表约束:子表数据进行写操作(增和改),外键字段在父表找不到,那么操作会失败
--对父表约束: 父表数据进行写操作(删和改: 都必须涉及到主键本身), 如果对应的主键在子表中已经被数据所引用, 那么就不允许操作
--外键条件
>外键要存在: 首先必须保证表的存储引擎是innodb(默认的存储引擎): 如果不是innodb存储引擎,那么外键可以创建成功,但是没有约束效果.
>外键字段的字段类型(列类型)必须与父表的主键类型完全一致.
>一张表中的外键名字不能重复.
>增加外键的字段(数据已经存在),必须保证数据与父表主键要求对应.
--外键约束模式(针对父表的约束)
District: 严格模式(默认的), 父表不能删除或者更新一个已经被子表数据引用的记录
Cascade: 级联模式: 父表的操作, 对应子表关联的数据也跟着被删除
Set null: 置空模式: 父表的操作之后,子表对应的数据(外键字段)被置空
推荐: 通常的一个合理的做法(约束模式)是删除的时候子表置空, 更新的时候子表级联操作
Foreign key(外键字段) references 父表(主键字段) on delete set null on update cascade;
注意: 删除置空的前提条件: 外键字段允许为空(如果不满足条件,外键无法创建)
-联合查询(将多次查询(多条select语句), 在记录上进行拼接(字段不会增加))
--Select 语句1 Union [union选项] Select语句2... --注意:每一条select语句获取的字段数必须严格一致(但是字段类型无关)
Union选项: All: 保留所有(不管重复) select * from emp union al select * from emp;
Distinct: 去重(整个重复): 默认的
--意义: >查询同一张表,但是需求不同: 如查询学生信息, 男生身高升序, 女生身高降序.
>多表查询: 多张表的结构是完全一样的,保存的数据(结构)也是一样的.
--Order by的使用
需求:男生升序,女生降序
(select * from student where sex=‘男‘ order by age asc limit 9999999) union (select * from student where sex=‘女‘ order by age desc limit 9999999);
注意: >order by不能直接使用,需要对查询语句使用括号才行
>若要orderby生效: 必须搭配limit: limit使用限定的最大数即可.
-子查询(在某个查询结果之上进行的查询)
--标量子查询(子查询得到的结果是一行一列)
班级名字为‘php0710d‘的班级的所有学生:Select * from my_student where c_id =(Select id from my_class where c_name = ‘PHP0710‘);
--列子查询(子查询得到的结果是一列多行)
查询所有存在班级的所有学生:Select * from my_student where c_id in (Select id from my_class);
=any ==== in; -- 一个满足即可 !=any --所有结果(null不参与比较,除外)
any ====== some; -- 同上 !=some --同上
=all ==== 为全部 --全部满足才行 !=all --全部不满足(null除外)
-行子查询(返回的结果可以是多行多列(一行多列),需要构建行元素)
年龄最大且身高是最高的学生:select * from my_student where (age,height)=(select max(age),max(height) from my_student);
也可用标量子查询:select * from my_student where age=(select max(age) from my_student) and height=(select max(height) from my_student);
-表子查询(子查询返回的结果是当做二维表来使用)
每一个班最高的一个学生:select * from (select * from my_student order by height desc) as student group by c_id;
注意: >from后只能放表,自查询结果取个表别名;
>from后面放的是数据源,只有数据源确定才能往下走,where是在数据源确定之后才能继续走
>这个思维是错的:select * from my_student group by c_id order by height;group by后只留第一条数据,并不是想要到,再去排序没意义
-Exists子查询(exists子查询就是用来判断某些条件是否满足(跨表), exists是接在where之后: exists返回的结果只有0和1)
查询所有的学生: 前提条件是班级存在: Select * from my_student where exists(Select * from my_class where id=1);
-------------------------------------------------------------------------------------------------------------------------------------------------------------
26.视图
view, 是一种有结构(有行有列)但是没结果(结构中不真实存放数据)的虚拟表, 虚拟表的结构来源不是自己定义, 而是从对应的基表中产生(视图的数据来源),类似代理商.
-创建视图
Create view 视图名字 as select语句;
--单表视图: 基表只有一个 create view my_view as select * from emp;
--多表视图: 基表来源至少两个 create view my_view as select e.*,d.dname,d.loc from emp e left join dept d on e.deptno=d.deptno;
注意:视图基表有多张情况下,注意字段名不能重复
-查看视图
表的所有查看方式都适用于视图,多一个show create view my_view;
视图一旦创建: 系统会在视图对应的数据库文件夹下创建一个对应的结构文件: frm文件
-使用视图
主要是为了查询: 将视图当做表一样查询即可.
select * from my_veiw;
视图的执行,其实本质就是执行封装的select语句.简化sql语句
-修改视图
视图本身不可修改, 但是视图的来源是可以修改的.
Alter view 视图名字 as 新的select语句;
-删除视图
Drop view 视图名字;
-视图意义
>节省SQL语句: 将一条复杂的查询语句使用视图进行保存: 以后可以直接对视图进行操作
>数据安全: 视图操作是主要针对查询的, 如果对视图结构进行处理(删除), 不会影响基表数据(相对安全).
>视图往往是在大项目中使用, 而且是多系统使用: 可以对外提供有用的数据, 但是隐藏关键(无用)的数据: 数据安全
>视图可以对外提供友好型: 不同的视图提供不同的数据, 对外好像专门设计
>视图可以更好(容易)的进行权限控制
-视图数据操作
--新增数据:
>多表视图不能新增数据
>单表视图可以插入数据,但是视图中包含的字段必须有基表中所有不能为空(或者没有默认值)字段
>视图是可以向基表插入数据的(直接作用到基表,但是一般用户不会给权限)
--删除数据
多表视图不能删除数据,单表视图可以删除数据
--更新数据
单表视图还是多表示视图都可以更新数据
注意:更新限制: with check option, 如果对视图在新增的时候,限定了某个字段有限制: 那么在对视图进行数据更新操作时,系统会进行验证: 要保证更新之后,数据依然可以被实体查询出来,否则不让更新.
create view my_view2 as select * from emp where sal>1500 with check option;
注意:with check option起限制作用,不能将数据sal改成小于1500
-------------------------------------------------------------------------------------------------------------------------------------------------------------
27. 视图算法?
系统对视图以及外部查询视图的Select语句的一种解析方式.
-Undefined: 未定义(默认的), 这不是一种实际使用算法, 是一种推卸责任的算法: 告诉系统,视图没有定义算法, 系统自己看着办
-Temptable: 临时表算法: 系统应该先执行视图的select语句,后执行外部查询语句
-Merge: 合并算法: 系统应该先将视图对应的select语句与外部查询视图的select语句进行合并,然后执行(效率高: 常态)
在创建视图的时候:Create algorithm = 指定算法 view 视图名字 as select语句;
-视图算法选择: 如果视图的select语句中会包含一个查询子句(五子句), 而且很有可能顺序比外部的查询语句要靠后, 一定要使用算法temptable,其他情况可以不用指定(默认即可).
-------------------------------------------------------------------------------------------------------------------------------------------------------------
28.数据备份与还原
备份: 将当前已有的数据或者记录保留
还原: 将已经保留的数据恢复到对应的表中
-数据表备份:直接进入到数据库文件夹复制对应的表结构以及数据文件, 以后还原的时候,直接将备份的内容放进去即可(通常适用于myisam存储引擎)
注意:根据不同的存储引擎有不同的区别.
>存储引擎: mysql进行数据存储的方式,主要是两种(免费): innodb和myisam
innodb:批量插入速度低,支持事物安全,5.5以上支持全文索引,行锁机制,64TB存储限制,空间及内存使用高,支持外键
myisam:批量插入速度高,不支持事物安全,支持全文索引,表锁机制,没有存储限制,空间及内存使用低,不支持外键
>Innodb: 只有表结构,数据全部存储到ibdata1文件中,不可直接复制文件
>Myisam: 表,数据和索引全部单独分开存储,可以直接复制三个文件(.frm结构,.MYD数据,MYI索引)到相应数据库下,有迁移的优势
-单表数据备份:每次只能备份一张表; 只能备份数据(表结构不能备份),通常是将表中的数据进行导出到文件
--备份: 从表中选出一部分数据保存到外部的文件中(outfile)
Select */字段列表 into outfile 文件所在路径 from 数据源; -- 前提: 外部文件不存在
select * into outfile ‘F:/server/aa.txt‘ from dept;
报错:the mysql server is running with the --secure-file-priv option so it cannot excute this statement
-SQL备份
-增量备份
-------------------------------------------------------------------------------------------------------------------------------------------------------------
29.事务
事务开启之后, 所有的操作都会临时保存到事务日志, 事务日志只有在得到commit命令才会同步到数据表,其他任何情况都会清空(rollback, 断电, 断开连接)
-自动事务(默认的)
系统通过autocommit变量控制,查看:Show variables like ‘autocommit’;
关闭自动提交: set autocommit = off/0;
手动来选择处理: commit提交/rollback回滚
-手动事务
>开启事务:Start transaction;
>事务操作
>关闭事务:提交(commit;)/回滚(rollback;)
-回滚点:savepoint 回滚点名字;rollback to 回滚点名字;
-事务有四大特性: ACID
>A: Atomic原子性, 事务的整个操作是一个整体, 不可分割,要么全部成功,要么全部失败;
>C: Consistency, 一致性, 事务操作的前后, 数据表中的数据没有变化
>I: Isolation, 隔离性, 事务操作是相互隔离不受影响的.
>D: Durability, 持久性, 数据一旦提交, 不可改变,永久的改变数据表数据
-锁机制: innodb默认是行锁, 但是如果在事务操作的过程中, 没有使用到索引,那么系统会自动全表检索数据, 自动升级为表锁,等待解锁(commit或rollback)
行锁: 只有当前行被锁住, 别的用户不能操作
表锁: 整张表被锁住, 别的用户都不能操作
-------------------------------------------------------------------------------------------------------------------------------------------------------------
30.变量
-系统变量
>查看系统变量:Show variables;
>查看具体变量值:Select @@变量名;
>修改系统变量:
会话级别(当前客户端当次连接有效):Set 变量名 = 值;/Set @@变量名 = 值;
全局级别(对所有客户端都生效):Set global 变量名 = 值;
-自定义变量:Set @变量名 = 值;(注意:在mysql中, “=”会默认的当做比较符号处理(很多地方), mysql为了区分比较和赋值的概念: 重新定义了一个新的的赋值符号: :=,推荐使用)
>查看自定义变量:Select @变量名;
>Mysql允许从数据表中获取数据,然后赋值给变量
方案1:Select @变量名 := 字段名 from 数据源; -- 从字段中取值赋值给变量名, 如果使用=会变成比较
方案2: Select 字段列表 from 表名 into 变量列表;--只有赋值不看结果,数据记录最多只允许获取一条,mysql不支持数组
所有自定义的变量都是会话级别: 当前客户端当次连接有效
所有自定义变量不区分数据库(用户级别)
-------------------------------------------------------------------------------------------------------------------------------------------------------------
31.触发器(张表中只能拥有一种触发时间的一种类型的触发器: 最多一张表能有6个触发器)
事件类型: 增删改, 三种类型insert,delete和update
触发时间: 前后: before和after
触发对象: 表中的每一条记录(行)
-创建触发器:
-- 临时修改语句结束符
Delimiter 自定义符号: 后续代码中只有碰到自定义符号才算结束
Create trigger 触发器名字 触发时间 事件类型 on 表名 for each row
Begin -- 代表左大括号: 开始
-- 里面就是触发器的内容: 每行内容都必须使用语句结束符: 分号
End -- 代表右带括号: 结束
-- 语句结束符
自定义符号
-- 将临时修改修正过来
Delimiter ;
。。。。。。。。。。。。。。。。。。。。
Mysql应用:
1.随机数:update my_student set id=ceil(rand()*10);
2.分组自能保留每组一条记录
3.查看存储引擎版本:select @@version;
4.数据库创建提示访问权限不足:Access denied for user ‘‘@‘localhost‘ to database
解决办法:使用正确用户名及密码登录mysql --user=root -p 输入root用户的密码即可进入mysql控制台
5.执行mysql脚本:source d:\book.sql 或者 \. d:\book.sql 回车即可。
6.数据库查出来的数量在不同的驱动结果不同,在DAO中应用是要转换成Number类型
以上是关于mysql随笔的主要内容,如果未能解决你的问题,请参考以下文章