MySQL全套(究极速成)
作者:互联网
库操作----------------------------------------------------------------- --创建数据库 create database mydatabase; create database mydatabase2 charset utf8; --显示数据库 --显示全部 show databases; --显示部分 show databases like '匹配模式' 匹配模式 _:匹配当前位置单个字符 %:匹配指定位置多个字符 --查看以my开头的数据库 show databases like 'my%'; --显示数据库创建语句 show create database mydatabase; --选择数据库 use mydatabase2; --修改数据库字符集(库选项:字符集和校对集) alter database 数据库名字 charset = 字符集 alter database mydatabase charset = utf8; --删除数据库 drop database mydatabase2; 表操作----------------------------------------------------------- --创建表 create table nclass( name varchar2(10), num int(10) )charset=utf8; --查看所有表 show tables; --匹配显示表 show tables like '匹配模式'; --显示表结构:显示表中所包含的字段信息 describe 表名 desc 表名 show columns from 表名 --显示表创建语句 show create table mytest; 表属性指的就是表选项:engine,charset和collate 基本语法:alter table 表名 表选项 [=] 值; 修改表名:rename table 旧表名 to 新表名 新增字段:alter table 表名 add [column] 新字段名 列类型 [列属性] [位置first/after 字段名] 字段位置:字段想要存放的位置 First:在某某之前(最前面),第一个字段 After 字段名:放在某个具体的字段之后(默认的) 修改字段名:alter table 表名 change 旧字段名 新字段名 字段类型 [列属性] [新位置] 修改字段类型(属性):alter table 表名 modify 字段名 新类型 [新属性] [新位置] 删除字段:alter table 表名 drop 字段名 删除表结构:drop table 表名[,表名2…],可以同时删除多个数据表 插入指定字段数据:insert into 表名[(字段列表)] values(对应字段列表) 表中所有字段插入数据:Insert into 表名 values(对应表结构)//值列表必须与字段列表一致 查询表中全部数据:select * from 表名; 查询表中部分字段:select 字段列表 from 表名; 简单条件查询数据:select 字段列表或* from 表名 where 字段名 = 值; 删除:delete from 表名 [where 条件]; //如果没有where条件:意味着系统会自动删除该表所有数据(慎用) 修改:update 表名 set 字段名 = 新值 [where 条件]; //如果没有where条件,那么所有的表中对应的那个字段都会被修改成统一值。 Set names 字符集的本质:就是一次性打通三层关系的字符集,变得一致。 在系统中有三个变量来记录着这三个关系对应的字符集:show variables like ‘character_set_%’; mysql默认编码配置---------------------------------------------- /* 配置mysql默认编码为utf8: 在配置文件my.ini中的[client]和[mysqld]下添加如下代码,然后重启mysql服务 [client] default-character-set=utf8 ... [mysqld] character_set_server=utf8 collation-server=utf8_general_ci */ 字段类型---------------------------------------------------------- 整数类型: tinyint:迷你整形,系统采用一个字节来保存的整形:一个字节 = 8位,最大能表示的数值是0-255,mysql默认的为整形增加负数。实际表示的区间为-128,127 无符号:表示存储的数据在当前字段中,没有负数(只有正数,区间为0-255) 基本语法:在类型之后加上一个 unsigned --例如: alter table my_int add int_6 tinyint unsigned first; 新增字段int_6的范围为0-255,此时就无法在该字段上插入负数 smallint:小整形,系统采用两个字节来保存的整形:能表示0-65535之间 mediumint:中整形,采用三个字节来保存数据 int:整形(标准整形),采用四个字节来保存数据 显示长度--------------------------------------------------------------- /* 显示长度:指数据(整型)在数据显示的时候,到底可以显示多长位。 Tinyint(3): 表示最长可以显示3位,unsigned说明只能是正数,0-255永远不会超过三个长度 Tinyint(4):表示最长可以显示4位,-128~127 显示长度只是代表了数据是否可以达到指定的长度,但是不会自动满足到指定长度:如果想要数据显示的时候,保持最高位(显示长度),那么还需要给字段增加一个zerofill属性才可以。 Zerofill:从左侧开始填充0(左侧不会改变数值大小),所以负数的时候就不能使用zerofill,一旦使用zerofill就相当于确定该字段为unsigned 数据显示的时候,zerofill会在左侧填充0到指定位:如果不足3位,那么填充到3位,如果本身已经够了或者超出,那么就不在填充。 显示长度可以自己设定:超出长度(但是不超出范围)不会影响,只会对不够长度的进行补充(显示长度) */ 小数类型:专门用于存储小数的 在Mysql中将小数类型又分为两类:浮点型和定点型 浮点型又称之为精度类型:是一种有可能丢失精度的数据类型,数据有可能不那么准确(由其是在超出范围的时候) /*浮点数 Float又称之为单精度类型:系统提供4个字节用来存储数据,但是能表示的数据范围比整型大的多,大概是10^38; 只能保证大概7个左右的精度(如果数据在7位数以内,那么基本是准确的,但是如果超过7位数,那么就是不准确的) 基本语法 Float:表示不指定小数位的浮点数 Float(M,D):表示一共存储M个有效数字,其中小数部分占D位 Float(10,2):整数部分为8位,小数部分为2位 浮点数可以采用科学计数法来存储数据 浮点数的应用:通常是用来保存一些数量特别大,大到可以不用那么精确的数据 Double又称之为双精度:系统用8个字节来存储数据,表示的范围更大,10^308次方,但是精度也只有15位左右。 */ /*定点数 定点数:能够保证数据精确的小数(小数部分可能不精确,超出长度会四舍五入),整数部分一定精确 Decimal定点数:系统自动根据存储的数据来分配存储空间,每大概9个数就会分配四个字节来进行存储,同时小数和整数部分是分开的 Decimal(M,D):M表示总长度,最大值不能超过65,D代表小数部分长度,最长不能超过30。 定点数的应用:如果涉及到钱的时候有可能使用定点数 */ date 日期类型:系统使用三个字节来存储数据,对应的格式为:YYYY-mm-dd,能表示的范围是从1000-01-01 到9999-12-12,初始值为0000-00-00 time 时间类型:能够表示某个指定的时间,但是系统同样是提供3个字节来存储,对应的格式为:HH:ii:ss, 但是mysql中的time类型能够表示时间范围要大的多,能表示从-838:59:59~838:59:59,在mysql中具体的用处是用来描述时间段。 time类型特殊性:本质是用来表示时间区间(当前时间之后的多少个小时),能表示的范围比较大 datetime 日期时间类型:就是将前面的date和time合并起来,表示的时间,使用8个字节存储数据,格式为YYYY-mm-dd HH:ii:ss, 能表示的区间1000-01-01 00:00:00 到9999-12-12 23:59:59,其可以为0值:0000-00-00 00:00:00 timestamp 时间戳类型:mysql中的时间戳只是表示从格林威治时间开始,但是其格式依然是:YYYY-mm-dd HH:ii:ss timestamp当对应的数据被修改的时候,会自动更新(这个被修改的数据不是自己) year 年类型:占用一个字节来保存,能表示1900~2155年,但是year有两种数据插入方式:0~99和四位数的具体年 year的特殊性:可以采用两位数的数据插入,也可以采用四位数的年份插入 year进行两位数插入的时候,有一个区间划分,零界点为69和70:当输入69以下,那么系统时间为20+数字,如果是70以上,那配系统时间为19+数字 char 定长字符:指定长度之后,系统一定会分配指定的空间用于存储数据 基本语法:char(L),L代表字符数(中文与英文字母一样),L长度为0到255 varchar 变长字符:指定长度之后,系统会根据实际存储的数据来计算长度,分配合适的长度(数据没有超出长度)。 基本语法:Varchar(L),L代表字符数,L的长度理论值位0到65535。 因为varchar要记录数据长度(系统根据数据长度自动分配空间),所以每个varchar数据产生后,系统都会在数据后面增加1-2个字节的额外开销:是用来保存数据所占用的空间长度 如果数据本身小于127个字符:额外开销一个字节;如果大于127个,就开销两个字节。 Char和varchar的区别 1、 char一定会使用指定的空间,varchar是根据数据来定空间 2、 char的数据查询效率比varchar高:varchar是需要通过后面的记录数来计算 如果确定数据一定是占指定长度,那么使用char类型; 如果不确定数据到底有多少,那么使用varchar类型; 如果数据长度超过255个字符,不论是否固定长度,都会使用text,不再使用char和varchar text 文本类型:本质上mysql提供了两种文本类型 Text:存储普通的字符文本 Blob:存储二进制文本(图片,文件),一般都不会使用blob来存储文件本身,通常是使用一个链接来指向对应的文件本身。 Text:系统中提供的四种text Tinytext:系统使用一个字节来保存,实际能够存储的数据为:2 ^ 8 + 1 Text:使用两个字节保存,实际存储为:2 ^ 16 + 2 Mediumtext:使用三个字节保存,实际存储为:2 ^ 24 + 3 Longtext:使用四个字节保存,实际存储为:2 ^ 32 + 4 注意: 1、 在选择对应的存储文本的时候,不用刻意去选择text类型,系统会自动根据存储的数据长度来选择合适的文本类型。 2、 在选择字符存储的时候,如果数据超过255个字符,那么一定选择text存储 /*enum 枚举类型:在数据插入之前,先设定几个项,这几个项就是可能最终出现的数据结果。 如果确定某个字段的数据只有那么几个值:如性别,男、女、保密,系统就可以在设定字段的时候规定当前字段只能存放固定的几个值:使用枚举 基本语法:enum(数据值1,数据值2…) 系统提供了1到2个字节来存储枚举数据:通过计算enum列举的具体值来选择实际的存储空间:如果数据值列表在255个以内, 那么一个字节就够,如果超过255但是小于65535,那么系统采用两个字节保存。 enum有规范数据的功能,能够保证插入的数据必须是设定的范围,其他类型都不可以 枚举enum的存储原理:实际上字段上所存储的值并不是真正的字符串,而是字符串对应的下标:当系统设定枚举类型的时候,会给枚举中每个元素定义一个下标,这个下标规则从1开始 Enum(1=>‘男’,2=>’女’,3=>’保密’) 特性:在mysql中系统是自动进行类型转换的:如果数据碰到“+、-、*、/”系统就会自动将数据转换成数值:而普通字符串转换成数值为0 既然实际enum字段存储的结果是数值:那么在进行数据插入的时候,就可以使用对应的数值来进行。 枚举的意义: 1、 规范数据本身,限定只能插入规定的数据项 2、 节省存储空间 */ /* set集合:是一种将多个数据选项可以同时保存的数据类型,本质是将指定的项按照对应的二进制位来进行控制:1表示该选项被选中,0表示该选项没有被选中。 基本语法:set(‘值1’,’值2’,’值3’…) 系统为set提供了多个字节进行保存,但是系统会自动计算来选择具体的存储单元 1个字节:set只能有8个选项 2个字节:set只能有16个选项 3个字节:set只能表示24个选项 8个字节:set可以表示64个选项 Set和enum一样,最终存储到数据字段中的依然是数字而不是真实的字符串 插入数据:可以插入多个数据,就是在数据插入的字符串中,使用对应的逗号“,”将选项进行隔开 数据选项所在的数据与数据插入的顺序无关:最终都会变成选项对应的顺序 数据在存储的时候,如果被选中,那么对应的位的值就为1,否则为0 系统在进行存储的时候会自动将得到的最终的二进制颠倒过来,然后再进行转换成十进制存储 既然是数值,那么就可以插入数值来代替实际插入数据 注意:数字插入的前提是对应的二进制位上都有对应的数据项 Set集合的意义: 1、 规范数据 2、 节省存储空间 Enum:单选框 Set:复选框 */ 列属性-------------------------------------------------------------------------------- 列属性又称之为字段属性,在mysql中一共有6个属性:null,默认值,列描述,主键,唯一键和自动增长 NULL属性:代表字段为空 Default:默认值,当字段被设计的时候,如果允许默认条件下,用户不进行数据的插入,那么就可以使用事先准备好的数据来填充:通常填充的是NULL 列描述:comment,是专门用于给开发人员进行维护的一个注释说明 基本语法:comment ‘字段描述’; 查看Comment:必须通过查看表创建语句:show create table 表名 主键:primary key,在一张表中,有且只有一个字段,里面的值具有唯一性 主键创建方式: 随表创建 1、 方案1:直接在需要当做主键的字段之后,增加primary key属性来确定主键 2、 方案2:在所有字段之后增加primary key选项:primary key(字段信息) 表后创建 alter table 表名 add primary key(字段); 删除主键:alter table 表名 drop primary key; 案例:有一张学生选修课表:一个学生可以选修多个选修课,一个选修课也可以由多个学生来选:但是一个学生在一个选修课中只有一个成绩。 此时应该使用复合主键(一般中间表使用复合主键) create table score( stu_no char(10), corse_no char(10), primary key(stu_no,corse_no) )charset utf8; 主键一旦增加,那么对对应的字段有数据要求 1、 当前字段对应的数据不能为空; 2、 当前字段对应的数据不能有任何重复 主键分类采用的是主键所对应的字段的业务意义分类 业务主键:主键所在的字段,具有业务意义(学生ID,课程ID) 逻辑主键:自然增长的整型(应用广泛) 自动增长:auto_increment,当给定某个字段该属性之后,该列的数据在没有提供确定数据的时候,系统会根据之前已经存在的数据进行自动增加后,填充数据。 通常自动增长用于逻辑主键。 自动增长的原理: 1、 在系统中有维护一组数据,用来保存当前使用了自动增长属性的字段,记住当前对应的数据值,再给定一个指定的步长 2、 当用户进行数据插入的时候,如果没有给定值,系统在原始值上再加上步长变成新的数据 3、 自动增长的触发:给定属性的字段没有提供值 4、 自动增长只适用于数值 语法:在字段之后增加一个属性auto_increment 查看自增长:show create table 表名 自增长一旦触发使用之后,会自动的在表选项中增加一个选项(一张表最多只能拥有一个自增长) 修改自增长 alter table my_auto auto_increment = 10; 自增长修改的时候,值可以较大,但是不能比当前已有的自增长字段的值小 删除自增长:就是在字段属性之后不再保留auto_increment,当用户修改自增长所在字段时,如果没有看到auto_increment属性,系统会自动清除该自增长 alter table my_auto modify id int; 增加自增长 alter table my_auto modify id int auto_increment; 查看自增长初始变量 在系统中,有一组变量用来维护自增长的初始值和步长Show variables like ‘auto_increment%’; 1、 一张表只有一个自增长:自增长会上升到表选项中 2、 如果数据插入中没有触发自增长(给定了数据),那么自增长不会表现 唯一键:unique key,用来保证对应的字段中的数据唯一的。 主键也可以用来保证字段数据唯一性,但是一张表只有一个主键。 1、 唯一键在一张表中可以有多个。 2、 唯一键允许字段数据为NULL,NULL可以有多个(NULL不参与比较) 创建唯一键与创建主键非常类似 1、 直接在表字段之后增加唯一键标识符:unique[ key] 2、 在所有的字段之后使用unique key(字段列表); 3、 在创建完表之后也可以增加唯一键:alter table 表名 add unique key(字段列表); 查看唯一键:desc 表名 删除唯一键:alter table 表名 drop index 唯一键名字; 修改唯一键:先删除后增加 复合唯一键 唯一键与主键一样可以使用多个字段来共同保证唯一性; 一般主键都是单一字段(逻辑主键),而其他需要唯一性的内容都是由唯一键来处理。 表关系-------------------------------------------------------------------------------------------------------- 表关系:表与表之间(实体)有什么样的关系,每种关系应该如何设计表结构。 一对一:一张表中的一条记录与另外一张表中最多有一条明确的关系:通常,此设计方案保证两张表中使用同样的主键即可 一对多:通常也叫作多对一的关系。通常一对多的关系设计的方案,在“多”关系的表中去维护一个字段,这个字段是“一”关系的主键。 多对多:一张表中的一条记录在另外一张表中可以匹配到多条记录,反过来也一样。 多对多的关系如果按照多对一的关系维护:就会出现一个字段中有多个其他表的主键,在访问的时候就会带来不便。 既然通过两张表自己增加字段解决不了问题,那么就通过第三张表来解决。 多对多解决方案;增加一个中间表,让中间表与对应的其他表形成两个多对一的关系:多对一的解决方案是在“多”表中增加“一”表对应的主键字段。 高级数据操作-------------------------------------------------------------------------------------------------- 新增数据 1、主键冲突更新:类似插入数据语法,如果插入的过程中主键冲突,那么采用更新方法。 Insert into 表名 [(字段列表)] values(值列表) on duplicate key update 字段 = 新值; 2、 主键冲突替换:当主键冲突之后,干掉原来的数据,重新插入进去。 Replace into [(字段列表)] values(值列表); 蠕虫复制:一分为二,成倍的增加。从已有的数据中获取数据,并且将获取到的数据插入到数据表中。 基本语法: Insert into 表名 [(字段列表)] select */字段列表 from 表; insert into my_simple(name) select name from my_simple; 注意: 1、 蠕虫复制的确通常是重复数据,没有太大业务意义:可以在短期内快速增加表的数据量,从而可以测试表的压力,还可以通过大量数据来测试表的效率(索引) 2、 蠕虫复制虽好,但是要注意主键冲突。 更新数据 1、 在更新数据的时候,特别要注意:通常一定是跟随条件更新 Update 表名 set 字段名 = 新值 where 判断条件; 2、 如果没有条件,是全表更新数据。但是可以使用limit 来限制更新的数量; Update 表名 set 字段名 = 新值 [where 判断条件] limit 数量; 例如改变4个a变成e: Update my_simple set name = ‘e’ where name = ‘a’ limit 4; 删除数据 1、 删除数据的时候尽量不要全部删除,应该使用where进行 判定; 2、 删除数据的时候可以使用limit来限制要删除的具体数量 Delete删除数据的时候无法重置auto_increment Mysql有一个能够重置表选项中的自增长的语法:truncate 表名,相当于先drop再create Where字句:用来从数据表获取数据的时候,然后进行条件筛选。 数据获取原理:针对表去对应的磁盘处获取所有的记录(一条条),where的作用就是在拿到一条结果就开始进行判断,判断是否符合条件:如果符合就保存下来,如果不符合直接舍弃(不放到内存中) Where是通过运算符进行结果比较来判断数据。 Group by表示分组的含义:根据指定的字段,将数据进行分组:分组的目标是为了统计 基本语法: group by 字段名; Group by是为了分组后进行数据统计的,如果只是想看数据显示,那么group by没什么含义:group by将数据按照指定的字段分组之后,只会保留每组的第一条记录。 利用一些统计函数:(聚合函数) count():统计每组中的数量,如果统计目标是字段,那么不统计为空NULL字段,如果为*那么代表统计记录 avg():求平均值 sum():求和 max():求最大值 min():求最小值 Group_concat():为了将分组中指定的字段进行合并(字符串拼接) 多分组:将数据按照某个字段进行分组之后,对已经分组的数据进行再次分组 基本语法:group by 字段1,字段2; //先按照字段1进行排序,之后将结果再按照字段2进行排序,以此类推。 Mysql中,分组默认有排序的功能:按照分组字段进行排序,默认是升序 基本语法:group by 字段 [asc|desc],字段 [asc|desc] 回溯统计 当分组进行多分组之后,往上统计的过程中,需要进行层层上报,将这种层层上报统计的过程称之为回溯统计:每一次分组向上统计的过程都会产生一次新的统计数据,而且当前数据对应的分组字段为NULL。 基本语法:group by 字段 [asc|desc] with rollup; Having的本质和where一样,是用来进行数据条件筛选。 Having在group by分组之后,可以使用聚合函数或者字段别名(where是从表中取出数据,别名是在数据进入到内存之后才有的) 强调:having是在group by之后,group by是在where之后:where的时候表示将数据从磁盘拿到内存,where之后的所有操作都是内存操作。 Order by排序:根据校对规则对数据进行排序 基本语法:order by 字段 [asc|desc]; //asc升序,默认的 Order by也可以像group by一样进行多字段排序:先按照第一个字段进行排序,然后再按照第二个字段进行排序。 Order by 字段1 规则,字段2 规则; Limit限制子句:主要是用来限制记录数量获取 纯粹的限制获取的数量:从第一条到指定的数量 基本语法: limt 数量; Limit通常在查询的时候如果限定为一条记录的时候,使用的比较多:有时候获取多条记录并不能解决业务问题,但是会增加服务器的压力。 分页 利用limit来限制获取指定区间的数据。 基本语法:limit offset,length; //offset偏移量:从哪开始,length就是具体的获取多少条记录 Mysql中记录的数量从0开始 Limit 0,2; 表示获取前两条记录 注意:limit后面的length表示最多获取对应数量,但是如果数量不够,系统不会强求 运算符------------------------------------------------------------------------------- 算术运算符 +、-、*、/、% 基本算术运算:通常不在条件中使用,而是用于结果运算(select 字段中) 比较运算符 >、>=、<、<=、=、<> 通常是用来在条件中进行限定结果 =:在mysql中,没有对应的 ==比较符号,就是使用=来进行相等判断 <=>:相等比较 特殊应用:就是在字段结果中进行比较运算 在mysql中没有布尔值,1代表true,2代表false 在条件判断的时候,还有有对应的比较运算符:计算区间 Between 条件1 and 条件2; Between中条件1必须小于条件2,反过来不可以 逻辑运算符 and、or、not and:逻辑与 or:逻辑或 not:逻辑非 In运算符 In:在什么里面,是用来替代=,当结果不是一个值,而是一个结果集的时候 基本语法: in (结果1,结果2,结果3…),只要当前条件在结果集中出现过,那么就成立 Is运算符 Is是专门用来判断字段是否为NULL的运算符 基本语法:is null / is not null Like运算符 Like运算符:是用来进行模糊匹配(匹配字符串) 基本语法:like ‘匹配模式’; 匹配模式中,有两种占位符: _:匹配对应的单个字符 %:匹配多个字符 联合查询--------------------------------------------------- 联合查询是可合并多个相似的选择查询的结果集。等同于将一个表追加到另一个表,从而实现将两个表的查询组合到一起,使用谓词为UNION或UNION ALL。 联合查询:将多个查询的结果合并到一起(纵向合并):字段数不变,多个查询的记录数合并。 基本语法: Select 语句 Union [union 选项] Select 语句; Union选项:与select选项基本一样 Distinct:去重,去掉完全重复的数据(默认的) All:保存所有的结果 注意细节:union理论上只要保证字段数一样,不需要每次拿到的数据对应的字段类型一致。永远只保留第一个select语句对应的字段名字。 1、 在联合查询中,如果要使用order by,那么对应的select语句必须使用括号括起来 2、 orderby在联合查询中若要生效,必须配合使用limit:而limit后面必须跟对应的限制数量(通常可以使用一个较大的值:大于对应表的记录数) 连接查询------------------------------------------------------------------ 连接查询:将多张表连到一起进行查询(会导致记录数行和字段数列发生改变) 连接查询的意义: 在关系型数据库设计过程中,实体(表)与实体之间是存在很多联系的。在关系型数据库表的设计过程中, 遵循着关系来设计:一对一,一对多和多对多,通常在实际操作的过程中,需要利用这层关系来保证数据的完整性。 连接查询一共有以下几类: 交叉连接 内连接 外连接:左外连接(左连接)和右外连接(右连接) 自然连接 交叉连接:将两张表的数据与另外一张表彼此交叉 原理: 1、 从第一张表依次取出每一条记录 2、 取出每一条记录之后,与另外一张表的全部记录挨个匹配 3、 没有任何匹配条件,所有的结果都会进行保留 4、 记录数 = 第一张表记录数 * 第二张表记录数;字段数 = 第一张表字段数 + 第二张表字段数(笛卡尔积) 基本语法:表1 cross join 表2; select * from mytest cross join mystu; 应用 交叉连接产生的结果是笛卡尔积,没有实际应用。 本质:from 表1,表2; 内连接:inner join,从一张表中取出所有的记录去另外一张表中匹配:利用匹配条件进行匹配,成功了则保留,失败了放弃。 原理 1、 从第一张表中取出一条记录,然后去另外一张表中进行匹配 2、 利用匹配条件进行匹配: 2.1 匹配到:保留,继续向下匹配 2.2 匹配失败:向下继续,如果全表匹配失败,结束 基本语法:表1 [inner] join 表2 on 匹配条件; 1、 如果内连接没有条件(允许),那么其实就是交叉连接(避免) 2、 使用匹配条件进行匹配:select * from mystu inner join myclass on mystu.class_id = myclass.id; 3、 因为表的设计通常容易产生同名字段,尤其是ID,所以为了避免重名出现错误,通常使用表名.字段名,来确保唯一性 4、 通常,如果条件中使用到对应的表名,而表名通常比较长,所以可以通过表别名来简化 5、 内连接匹配的时候,必须保证匹配到才会保存 6、 内连接因为不强制必须使用匹配条件(on)因此可以在数据匹配完成之后,使用where条件来限制,效果与on一样(建议使用on) 应用 内连接通常是在对数据有精确要求的地方使用:必须保证两种表中都能进行数据匹配。 外连接 外链接:outer join,按照某一张表作为主表(表中所有记录在最后都会保留),根据条件去连接另外一张表,从而得到目标数据。 外连接分为两种:左外连接(left join),右外连接(right join) 左连接:左表是主表 右连接:右表是主表 原理 1、 确定连接主表:左连接就是left join左边的表为主表;right join就是右边为主表 2、 拿主表的每一条记录,去匹配另外一张表(从表)的每一条记录 3、 如果满足匹配条件:保留;不满足即不保留 4、 如果主表记录在从表中一条都没有匹配成功,那么也要保留该记录:从表对应的字段值都未NULL 基本语法: 左连接:主表 left join 从表 on 连接条件; 右连接:从表 right join 主表 on连接条件; 特点: 1、只要sql查询时表在左边,表的字段就在左边;只要表在右边,表的字段就在右边————(左右:以join为界,join左边为左表,右边为右表) 2、外连接中主表数据记录一定会保存:连接之后不会出现记录数少于主表(内连接可能) 3、左连接和右连接其实可以互相转换,但是数据对应的位置(表顺序)会改变 应用 非常常用的一种获取的数据方式:作为数据获取对应主表以及其他数据(关联) Using关键字 是在连接查询中用来代替对应的on关键字的,进行条件匹配。 原理 1、 在连接查询时,使用on的地方用using代替 2、 使用using的前提是对应的两张表连接的字段是同名(类似自然连接自动匹配) 3、 如果使用using关键字,那么对应的同名字段,最终在结果中只会保留一个。 例如:select * from mystu inner join myclass using(class_id);//此处class_id在mystu和myclass中为同名字段 子查询----------------------------------------------------------------- 子查询:sub query 子查询是一种常用计算机语言SELECT-SQL语言中嵌套查询下层的程序模块。当一个查询是另一个查询的条件时,称之为子查询。 子查询:指在一条select语句中,嵌入了另外一条select语句,那么被嵌入的select语句称之为子查询语句。 主查询:主要的查询对象,第一条select语句,确定的用户所有获取的数据目标(数据源),以及要具体得到的字段信息。 子查询和主查询的关系 1、 子查询是嵌入到主查询中的; 2、 子查询的辅助主查询的:要么作为条件,要么作为数据源 3、 子查询其实可以独立存在:是一条完整的select语句 子查询分类 按功能分 标量子查询:子查询返回的结果是一个数据(一行一列) 列子查询:返回的结果是一列(一列多行) 行子查询:返回的结果是一行(一行多列) 表子查询:返回的结果是多行多列(多行多列) Exists子查询:返回的结果1或者0(类似布尔操作) 按位置分 Where子查询:子查询出现的位置在where条件中 From子查询:子查询出现的位置在from数据源中(做数据源) 标量子查询:子查询得到结果是一个数据(一行一列) 基本语法:select * from 数据源 where 条件判断 =/<> (select 字段名 from 数据源 where 条件判断); //子查询得到的结果只有一个值 列子查询:子查询得到的结果是一列数据(一列多行) 基本语法:主查询 where 条件 in (列子查询); 行子查询:子查询返回的结果是一行多列 行元素:字段元素是指一个字段对应的值,行元素对应的就是多个字段:多个字段合起来作为一个元素参与运算,把这种情况称之为行元素。 基本语法: 主查询 where 条件[(构造一个行元素)] = (行子查询); 例如:获取班级上年龄最大,且身高最高的学生 1、求出班级年龄最大值 2、求出班级身高最大值 3、求出对应的学生 select * from my_student where stu_age = max(stu_age) and stu_height = max(stu_height)--错误:where后不能使用聚合函数 select * from my_student where (stu_age,stu_height) = (select max(stu_age),max(stu_height) from my_student); 常见的三个子查询 标量子查询、列子查询和行子查询:都属于where子查询 表子查询:子查询返回的结果是多行多列,表子查询与行子查询非常相似,只是行子查询需要产生行元素,而表子查询没有。 行子查询是用于where条件判断:where子查询 表子查询是用于from数据源:from子查询 基本语法: Select 字段表 from (表子查询) as 别名 [where] [group by] [having] [order by] [limit]; 案例:获取每个班上最高身高的学生(一个) 1、将每个班最高的学生排在最前面:order by 2、再针对结果进行group by:保留每组第一个 select * from (select * from my_student order by stu_height desc) as temp group by class_id; Exists子查询:查询返回的结果只有0或者1,1代表成立,0代表不成立 基本语法:where exists(查询语句); //exists就是根据查询得到的结果进行判断:如果结果存在,那么返回1,否则返回0 Where 1:永远为真 案例:有学生的所有班级 表:mystu和myclass select * from myclass as c where exists(select stu_id from mystu as s where c.class_id=s.class_id); /*建表语句: DROP TABLE IF EXISTS `myclass`; CREATE TABLE `myclass` ( `class_id` int(10) DEFAULT NULL, `class_name` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of myclass -- ---------------------------- INSERT INTO `myclass` VALUES ('1', '一班'); INSERT INTO `myclass` VALUES ('2', '二班'); INSERT INTO `myclass` VALUES ('3', '三班'); DROP TABLE IF EXISTS `mystu`; CREATE TABLE `mystu` ( `stu_id` int(11) NOT NULL, `stu_name` varchar(10) DEFAULT NULL, `stu_no` varchar(10) DEFAULT NULL, `class_id` int(10) DEFAULT NULL, PRIMARY KEY (`stu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of mystu -- ---------------------------- INSERT INTO `mystu` VALUES ('1', '刘飞', '2016081038', '1'); INSERT INTO `mystu` VALUES ('2', '张飞', '2016081036', '1'); INSERT INTO `mystu` VALUES ('3', 'wolf', '2016081037', '2'); INSERT INTO `mystu` VALUES ('4', 'lf', '2016081035', '4'); */ 子查询中特定关键字的使用:如果对应的匹配字段有NULL,那么不参与匹配 in 主查询 where 条件 in (列子查询); any任意一个 = any(列子查询):条件在查询结果中有任意一个匹配即可,等价于in <>any(列子查询):条件在查询结果中不等于任意一个 1 =any(1,2,3) ===== true 1 <>any(1,2,3) ===== true some 与any完全一样:在国外,some与any的正面含义一致,但是否定就大不相同:not any与not some 开发者为了让对应的使用者不要在语法上纠结:重新设计了some all = all(列子查询):等于里面所有 <>all(列子查询):不等于其中所有 数据库备份--------------------------------- 整库数据备份也叫SQL数据备份:备份的结果都是SQL指令 在Mysql中提供了一个专门用于备份SQL的客户端:mysqldump.exe SQL备份是一种mysql非常常见的备份与还原方式,SQL备份不只是备份数据,还备份对应的SQL指令(表结构):即便是数据库遭到毁灭性的破坏(数据库被删),那么利用SQL备份依然可以实现数据还原。 SQL备份因为需要备份结构,因此产生的备份文件特别大,因此不适合特大型数据备份,也不适合数据变换频繁型数据库备份。 SQL备份用到的是专门的备份客户端,因此还没与数据库服务器进行连接。 基本语法:mysqldump/mysqldump.exe -hPup 数据库名字 [表1 [表2…]] > 备份文件地址 备份可以有三种形式: 1、 整库备份(只需要提供数据库名字) mysqldump.exe -hlocalhost -P3306 -utoot -p5445abcd mydatabase > c:/server/temp/mydatabase.sql 2、 单表备份:数据库后面跟一张表 3、 多表备份:数据库后跟多张表 mysqldump -hlocalhost -P3306 -utoot -p5445abcd mydatabase mystu myclass > c:/server/temp/stu_class.sql 数据还原 Mysql提供了多种方式来实现:两种 Mysqldump备份的数据中没有关于数据库本身的操作,都是针对表级别的操作:当进行数据(SQL还原),必须指定数据库 1、 利用mysql.exe客户端:没有登录之前,可以直接用该客户端进行数据还原 Mysql.exe –hPup 数据库 < 文件位置 2、 在SQL指令,提供了一种导入SQL指令的方式 Source SQL文件位置; //必须先进入到对应的数据库 如:source c:/server/temp/stu_class; 3、 人为操作:打开备份文件,复制所有SQL指令,然后到mysql.exe客户端中去粘贴执行。(不推荐) 用户管理--------------------------------------------- 创建用户:理论上讲可以采用两种方式创建用户: 1、 直接使用root用户在mysql.user表中插入记录(不推荐) 2、 专门创建用户的SQL指令 基本语法:create user 用户名 identified by ‘明文密码’; 用户:用户名@主机地址 主机地址:’’ / ‘%’ 简化版创建用户(谁都可以访问,不需要密码):create user 用户名; 删除用户 注意:mysql中user是带着host本身的(具有唯一性) 基本语法:drop user 用户名@host; 修改用户密码 Mysql中提供了多种修改的方式:基本上都必须使用对应提供的一个系统函数:password(),需要靠该函数对密码进行加密处理。 1、 使用专门的修改密码的指令 基本语法:set password for 用户 = password(‘新的明文密码’); 2、 使用更新语句update来修改表 基本语法:update mysql.user set password = password(‘新的明文密码’) where user = ‘’ and host= ‘’; 权限管理-------------------------------------------------------- 在mysql中将权限管理分为三类: 1、 数据权限:增删改查(select\update\delete\insert) 2、 结构权限:结构操作(create\drop) 3、 管理权限:权限管理(create user\grant\revoke):通常只给管理员如此权限 授予权限:grant 将权限分配给指定的用户 --基本语法:grant 权限列表 on 数据库/*.表名/* to 用户; 权限列表:使用逗号分隔,但是可以使用all privileges代表全部权限 数据库.表名:可以是单表(数据库名字.表名),可以是具体某个数据库(数据库.*),也可以整库(*.*) 用户被分配权限以后不需要退出就可以看到效果 具体权限查看:单表权限只能看到数据库中的一张表 取消权限:revoke 权限回收:将权限从用户手中收回 --基本语法:revoke 权限列表/all privileges on 数据库/*.表/* from 用户; 权限回收,同样不需要刷新,用户马上就会感受到 刷新权限:flush Flush:刷新,将当前对用户的权限操作,进行一个刷新,将操作的具体内容同步到对应的表中。 基本语法:flush privileges; ------------------------------------------------------------- 密码丢失的解决方案 如果忘记了root用户密码,就需要去找回或者重置root用户密码 1、 停止服务:net stop mysql 2、 重新启动服务:mysqld.exe --skip-grant-tables //启动服务器但是跳过权限 3、 当前启动的服务器没有权限概念:非常危险,任何客户端,不需要任何用户信息都可以直接登录,而且是root权限:新开客户端,使用mysql.exe登录即可 4、 修改root用户的密码:指定 用户名@host update mysql.user set password = password('5445abcd') where user = 'root' and host = 'localhost'; 5、 赶紧关闭服务器(直接结束进程),重启服务:net start mysql; 外键-------------------------------------------------------- 外键:foreign key 一张表(A)中有一个字段,保存的值指向另外一张表(B)的主键 B:主表 A:从表 增加外键 1、 方案1:在创建表的时候增加外键(类似主键) 基本语法:在字段之后增加一条语句 [constraint `外键名`] foreign key(外键字段) references 主表(主键); MUL:多索引,外键本身是一个索引,外键要求外键字段本身也是一种普通索引 2、 方案2:在创建表后增加外键 Alter table 从表 add [constraint `外键名`] foreign key(外键字段) references 主表(主键); 修改&删除外键 外键不允许修改,只能先删除后增加 基本语法:alter table 从表 drop foreign key 外键名字; 外键不能删除产生的普通索引,只会删除外键自己;如果想删除对应的索引:alter table 表名 drop index 索引名字; 外键基本要求 1、 外键字段需要保证与关联的主表的主键字段类型完全一致; 2、 基本属性也要相同 3、 如果是在表后增加外键,对数据还有一定的要求(从表数据与主表的关联关系) 4、 外键只能使用innodb存储引擎:myisam不支持 外键约束:通过建立外键关系之后,对主表和从表都会有一定的数据约束效率。 约束的基本概念 1、 当一个外键产生时:外键所在的表(从表)会受制于主表数据的存在从而导致数据不能进行某些不符合规范的操作(不能插入主表不存在的数据); 2、 如果一张表被其他表外键引入,那么该表的数据操作就不能随意:必须保证从表数据的有效性(不能随便删除一个被从表引入的记录) 外键约束的概念 可以在创建外键的时候,对外键约束进行选择性的操作。 基本语法: add foreign key(外键字段) references 主表(主键) on 约束模式; 约束模式有三种: 1、 district:严格模式,默认的,不允许操作 2、 cascade:级联模式,一起操作,主表变化,从表数据跟着变化 3、 set null:置空模式,主表变化(删除),从表对应记录设置为空:前提是从表中对应的外键字段允许为空 外键约束主要约束的对象是主表操作:从表就是不能插入主表不存在的数据 通常在进行约束时候的时候,需要指定操作:update和delete 常用的约束模式: on update cascade, on delete set null,更新级联,删除置空 约束作用 保证数据的完整性:主表与从表的数据要一致 正是因为外键有非常强大的数据约束作用,而且可能导致数据在后台变化的不可控。导致程序在进行设计开发逻辑的时候,没有办法去很好的把握数据(业务),所以外键比较少使用。 视图-------------------------------------------------------------------------- 创建视图 视图的本质是SQL指令(select语句) 基本语法:create view 视图名字 as select指令; //可以是单表数据,也可以是连接查询,联合查询或者子查询 查看视图结构:视图本身是虚拟表,所以关于表的一些操作都适用于视图 Show tables/show create table[view]/desc 视图名字; 视图是一张虚拟表:可以直接把视图当做“表”操作,但是视图本身没有数据,是临时执行select语句得到对应的结果。视图主要用户查询操作。 基本语法:select 字段列表 from 视图名字 [子句]; 修改视图 修改视图:本质是修改视图对应的查询语句 基本语法:alter view 视图名字 as 新select指令; 删除视图 基本语法:drop view 视图名字; 事务------------------------------------------- 事务概念:事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。 事务通常由高级数据库操纵语言或编程语言书写的用户程序的执行所引起。 事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。 事务基本原理 基本原理:Mysql允许将事务统一进行管理(存储引擎INNODB),将用户所做的操作,暂时保存起来,不直接放到数据表(更新),等到用于确认结果之后再进行操作。 事务在mysql中通常是自动提交的,但是也可以使用手动事务。 自动事务:autocommit,当客户端发送一条SQL指令(写操作:增删改)给服务器的时候,服务器在执行之后,不用等待用户反馈结果,会自动将结果同步到数据表。 证明:利用两个客户端,一个客户端执行SQL指令,另外一个客户端查看执行结果 自动事务:系统做了额外的步骤来帮助用户操作,系统是通过变量来控制的。Autocommit Show variables like ‘autocommit%’; 关闭自动事务:关闭之后系统就不在帮助用户提交结果了 Set autocommit = Off; 开启自动事务:set autocommit = on; 一旦自动事务关闭,那么需要用户提供是否同步的命令 Commit:提交(同步到数据表:事务也会被清空) Rollback:回滚 (commit和rollback只要执行一个,就会清空之前的操作,不要了) 通常,我们不会关闭自动事务:这样操作太麻烦。因此只会在需要使用事务处理的时候,才会进行操作(手动事务) 手动事务:不管是开始还是过程还是结束都需要用户(程序员),手动的发送事务操作指令来实现。 手动事务对应的命令: 1、 start transaction; //开启事务:从这条语句开始,后面的所有语句都不会直接写入到数据表(保存在事务日志中) 2、 事务处理:多个写指令构成 3、 事务提交:commit/rollback,到这个时候所有的事务才算结束 回滚点:savepoint,当有一系列事务操作时,而其中的步骤如果成功了,没有必要重新来过,可以在某个点(成功),设置一个记号(回滚点),然后如果后面有失败,那么可以回到这个记号位置。 增加回滚点:savepoint 回滚点名字; //字母数字和下划线构成 回到回滚点:rollback to 回滚点名字; //那个记号(回滚点)之后的所有操作没有了 注意:在一个事务处理中,如果有很多个步骤,那么可以设置多个回滚点。但是如果回到了前面的回滚点,后面的回滚点就失效; 事务特点 事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。 事务从start transaction起到提交事务(commit或者rollback),要么所有的操作都成功,要么就是所有的操作都失败; 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。 数据表中的数据修改,要么是所有操作一次性修改,要么是根本不懂 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。 如果一个客户端在使用事务操作一个数据(可能是一行/整表)的时候,另外一个客户端不能对该数据进行操作 什么时候是行被隔离?什么时候是整表被隔离? 说明:如果条件中使用了索引(主键),那么系统是根据主键直接找到某条记录,这个时候与其他记录无关,那么只隔离一条记录;反之,如果说系统是通过全表检索(每一条记录都去检查:没有索引),
被检索的所有数据都会被锁定(整表) 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。 变量------------------------------------------------------------ 变量:系统变量、会话变量、局部变量 Mysql本质是一种编程语言,需要很多变量来保存数据。Mysql中很多的属性控制都是通过mysql中固有的变量来实现的。 系统内部定义的变量,系统变量针对所有用户(MySQL客户端)有效。 查看系统所有变量:show variables [like ‘pattern’]; Mysql允许用户使用select查询变量的数据值(系统变量) 基本语法:select @@变量名; 修改系统变量:分为两种修改方式 1、 局部修改(会话级别):只针对当前自己客户端当次连接有效 基本语法:set 变量名 = 新值; 2、 全局修改:针对所有的客户端,“所有时刻”都有效 基本语法:set global 变量名 = 值; || set @@global.变量名 = 值; 全局修改之后:所有连接的客户端并没发现改变?全局修改只针对新客户端生效(正在连着的无效) 注意:如果想要本次连接对应的变量修改有效,那么不能使用全局修改,只能使用会话级别修改(set 变量名 = 值); 会话变量 会话变量也称之为用户变量,会话变量跟mysql客户端是绑定的,设置的变量,只对当前用户使用的客户端生效。 定义用户变量:set @变量名 = 值; 在mysql中因为没有比较符号==,所以是用=代替比较符号:有时候在赋值的时候,会报错:mysql为了避免系统分不清是赋值还是比较:特定增加一个变量的赋值符号: := Set @变量名 := 值; Mysql是专门存储数据的:允许将数据从表中取出存储到变量中:查询得到的数据必须只能是一行数据(一个变量对应一个字段值):Mysql没有数组。 1、 赋值且查看赋值过程:select @变量1 := 字段1,@变量2 := 字段2 from 数据表 where 条件; 2、 只赋值,不看过程:select 字段1,字段2… from 数据源 where条件 into @变量1,@变量2… 查看变量:select @变量名; 局部变量 作用范围在begin到end语句块之间。在该语句块里设置的变量,declare语句专门用于定义局部变量。 1、 局部变量是使用declare关键字声明 2、 局部变量declare语句出现的位置一定是在begin和end之间(beginend是在大型语句块中使用:函数/存储过程/触发器) 3、 声明语法:declare 变量名 数据类型 [属性]; 流程结构:代码的执行顺序-------------------------------------------------------------------------- If分支 基本语法 If在Mysql中有两种基本用法 1、 用在select查询当中,当做一种条件来进行判断 基本语法:if(条件,为真结果,为假结果) select *,if(stu_age > 20,'符合','不符合') as judge from my_student; 2、 用在复杂的语句块中(函数/存储过程/触发器) 基本语法 If 条件表达式 then 满足条件要执行的语句; End if; 复合语法:代码的判断存在两面性,两面都有对应的代码执行。 基本语法: If 条件表达式 then 满足条件要执行的语句; Else 不满足条件要执行的语句; //如果还有其他分支(细分),可以在里面再使用if If 条件表达式 then //满足要执行的语句 End if; End if; While循环 基本语法:循环体都是需要在大型代码块中使用 基本语法: While 条件 do 要循环执行的代码; End while; 结构标识符:为某些特定的结构进行命名,然后为的是在某些地方使用名字 基本语法 标识名字:While 条件 do 循环体 End while [标识名字]; 标识符的存在主要是为了循环体中使用循环控制。在mysql中没有continue和break,有自己的关键字替代: Iterate:迭代,就是以下的代码不执行,重新开始循环(continue) Leave:离开,整个循环终止(break) 语法: 标识名字:While 条件 do If 条件判断 then 循环控制; Iterate/leave 标识名字; End if; 循环体 End while [标识名字]; 函数---------------------------------------------------------------------------------------- 在mysql中,函数分为两类:系统函数(内置函数)和自定义函数 不管是内置函数还是用户自定义函数,都是使用select 函数名(参数列表); 内置函数 字符串函数 Char_length():判断字符串的字符数 Length():判断字符串的字节数(与字符集) select char_length('你好中国'),length('你好中国'); Concat():连接字符串 Instr():判断字符在目标字符串中是否存在,存在返回其位置,不存在返回0 Lcase():全部小写 Left():从左侧开始截取,直到指定位置(位置如果超过长度,截取所有) Ltrim():消除左边对应的空格 Mid():从中间指定位置开始截取,如果不指定截取长度,直接到最后 时间函数 Now():返回当前时间,日期 时间 Curdate():返回当前日期 Curtime():返回当前时间 Datediff():判断两个日期之间的天数差距,参数日期必须使用字符串格式(用引号) Date_add(日期,interval 时间数字 type):进行时间的增加 Type:day/hour/minute/second Unix_timestamp():获取时间戳 From_unixtime():将指定时间戳转换成对应的日期时间格式 数学函数 Abs():绝对值 Ceiling():向上取整 Floor():向下取整 Pow():求指数,谁的多少次方 Rand():获取一个随机数(0-1之间) Round():四舍五入函数 其他函数 Md5():对数据进行md5加密(mysql中的md5与其他任何地方的md5加密出来的内容是完全相同的) Version():获取版本号 Databse():显示当前所在数据库 UUID():生成一个唯一标识符(自增长):自增长是单表唯一,UUID是整库(数据唯一同时空间唯一) 自定义函数 自定义函数:用户自己定义的函数 函数:实现某种功能的语句块(由多条语句组成) 1、 函数内部的每条指令都是一个独立的个体:需要符合语句定义规范:需要语句结束符分号; 2、 函数是一个整体,而且函数是在调用的时候才会被执行,那么当设计函数的时候,意味着整体不能被中断; 3、 Mysql一旦见到语句结束符分号,就会自动开始执行 解决方案:在定义函数之前,尝试修改临时的语句结束符 基本语法:delimiter 修改临时语句结束符:delimiter 新符号[可以使用系统非内置即可$$] 中间为正常SQL指令:使用分号结束(系统不会执行:不认识分号) 使用新符号结束 修改回语句结束符:delimiter ; 创建函数 自定义函数包含几个要素:function关键字,函数名,参数(形参和实参[可选]),确认函数返回值类型,函数体,返回值 函数定义基本语法: 修改语句结束符 Create function 函数名(形参) returns 返回值类型 Begin //函数体 Return 返回值数据; //数据必须与结构中定义的返回值类型一致 End 语句结束符 修改语句结束符(改回来) --创建自定义函数 ① --修改语句结束符 delimiter $$ create function my_fun1() returns int begin return 10; end $$ --修改语句结束符(改回来) delimiter ; ② 并不是所有的函数都需要begin和end:如果函数体本身只有一条指令(return),那么可以省略begin和end 最简函数 create function my_fun2() returns int return 100; ③ 形参:在mysql中需要为函数的形参指定数据类型(形参本身可以有多个) 基本语法:变量名 字段类型 create function my_fun3(int_1 int,int_2 int) returns int return int_1 + int_2; 查看函数 1、 可以通过查看function状态,查看所有的函数 Show function status [like ‘pattern’]; 2、 查看函数的创建语句:show create function 函数名字; 调用函数 自定义函数的调用与内置函数的调用是一样的:select 函数名(实参列表); 删除函数:drop function 函数名; 注意事项 1、 自定义函数是属于用户级别的:只有当前客户端对应的数据库中可以使用 2、 可以在不同的数据库下看到对应的函数,但是不可以调用 3、 自定义函数:通常是为了将多行代码集合到一起解决一个重复性的问题 4、 函数因为必须规范返回值:那么在函数内部不能使用select指令:select一旦执行就会得到一个结果(result set):select 字段 into @变量;(唯一可用) create function my_sum(end_value int) returns int begin --声明变量():如果使用declare声明变量:必须在函数体其他语句之前 declare res int default 0; declare i int default 1; --循环处理 mywhile:while i <= end_value do --判断当前的数据是否合理 if i % 5 = 0 then --5的倍数不要 set i = i + 1; iterate mywhile; end if; --修改变量:累加结果 set res = res + i; --mysql中没有++ set i = i + 1; end while mywhile; return res; end; create function my_sum(end_value int) returns int begin declare res int default 0; declare i int default 1; mywhile:while i <= end_value do if i % 5 = 0 then set i = i + 1; iterate mywhile; end if; set res = res + i; set i = i + 1; end while mywhile; return res; end; 变量作用域---------------------------------------------------------------- 局部作用域 使用declare关键字声明(在结构体内:函数/存储过程/触发器),而且只能在结构体内部使用 1、 declare关键字声明的变量没有任何符号修饰,就是普通字符串,如果在外部访问该变量,系统会自动认为是字段 会话作用域 用户定义的,使用@符号定义的变量,使用set关键字 会话作用域:在当前用户当次连接有效,只要在本连接之中,任何地方都可以使用(可以在结构内部,也可以跨库) 会话变量可以在函数内部使用 会话变量可以跨库 全局作用域 所有的客户端所有的连接都有效:需要使用全局符号来定义 Set global 变量名 = 值; Set @@global.变量名 = 值; 通常,在SQL编程的时候,不会使用自定义变量来控制全局。一般都是定义会话变量或者在结构中使用局部变量来解决问题。 存储过程----------------------------------------------------------------------- 存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中, 经过第一次编译后再次调用不需要再次编译(效率比较高),用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。 存储过程是数据库中的一个重要对象(针对SQL编程而言)。 存储过程:简称过程 存储过程与函数的区别 相同点 1、 存储过程和函数目的都是为了可重复地执行操作数据库的sql语句的集合。 2、 存储过程函数都是一次编译,后续执行 不同点 1、标识符不同。函数的标识符为FUNCTION,过程为:PROCEDURE。 2、函数中有返回值,且必须返回,而过程没有返回值。 3、过程无返回值类型,不能将结果直接赋值给变量;函数有返回值类型,调用时,除在select中,必须将返回值赋给变量。 4、函数可以在select语句中直接使用,而过程不能:函数是使用select调用,过程不是。 创建过程 基本语法 Create procedure 过程名字([参数列表]) Begin 过程体 End 结束符 如果过程体中只有一条指令,那么可以省略begin和end create procedure my_pro1() select * from mystu; 过程基本上也可以完成函数对应的所有功能 --求1到100之间的和 create procedure my_pro2() begin --求1到100之间的和 declare i int default 1; --declare sum int default 0; --局部变量,可以解决 set @sum = 0; --会话变量 --开始循环获取结果 while i < 100 do --求和 set @sum = @sum + i; set i = i + 1; end while; --显示结果 select @sum; end; 查看过程 查看过程与查看函数完全一样:除了关键字 查看全部存储过程:show procedure status [like ‘pattern’]; 查看过程创建语句:show create procedure 过程名字; 调用过程 过程:没有返回值,select不可能调用 调用过程有专门的语法:call 过程名([实参列表]); 删除过程 基本语法:drop procedure 过程名字; 存储过程的形参类型 存储过程也允许提供参数(形参和实参):存储的参数也和函数一样,需要指定其类型。 但是存储过程对参数还有额外的要求:自己的参数分类in、out、inout In 表示参数从外部传入到里面使用(过程内部使用):可以是直接数据也可以是保存数据的变量 Out 表示参数是从过程里面把数据保存到变量中,交给外部使用:传入的必须是变量 如果说传入的out变量本身在外部有数据,那么在进入过程之后,第一件事就是被清空,设为NULL Inout 数据可以从外部传入到过程内部使用,同时内部操作之后,又会将数据返还给外部。 参数使用级别语法(形参) 过程类型 变量名 数据类型; //in int_1 int --创建三个外部变量 set @n1 = 1; set @n2 = 2; set @n3 = 3; --创建过程 --修改语句结束符 demiter $$ create procedure my_pro3(in int_1 int,out int_2 int,inout int_3 int) begin --查看三个传入进来的数据值 select int_1,int_2,int_3; --修改三个变量的值 set int_1 = 10; set int_2 = 100; set int_3 = 1000; select int_1,int_2,int_3; --查看会话变量 select @n1,@n2,@n3; --修改会话变量 set @n1 = 'a'; set @n2 = 'b'; set @n3 = 'c'; select @n1,@n2,@n3; end; --调用过程 call my_pro3(@n1,@n2,@n3); 触发器-------------------------------------------------------------------- 触发器概念 基本概念 触发器是一种特殊类型的存储过程,它不同于我们前面介绍过的存储过程。触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。 触发器:trigger,是一种非常接近于js中的事件的知识。提前给某张表的所有记录(行)绑定一段代码,如果改行的操作满足条件(触发),这段提前准备好的代码就会自动执行。 作用 1、可在写入数据表前,强制检验或转换数据。(保证数据安全) 2、触发器发生错误时,异动的结果会被撤销。(如果触发器执行错误,那么前面用户已经执行成功的操作也会被撤销:事务安全) 3、部分数据库管理系统可以针对数据定义语言(DDL)使用触发器,称为DDL触发器。 4、可依照特定的情况,替换异动的指令 (INSTEAD OF)。(mysql不支持) 优点 1、 触发器可通过数据库中的相关表实现级联更改。(如果某张表的数据改变,可以利用触发器来实现其他表的无痕操作[用户不知道]) 2、 保证数据安全:进行安全校验 缺点 1、 对触发器过分的依赖,势必影响数据库的结构,同时增加了维护的复杂程度。 2、 造成数据在程序层面不可控。(PHP层) 创建触发器 基本语法 Create trigger 触发器名字 触发时机 触发事件 on 表 for each row Begin ..... End 触发对象:on 表 for each row,触发器绑定实质是表中的所有行,因此当每一行发生指定的改变的时候,就会触发触发器。 触发时机 触发时机:每张表中对应的行都会有不同的状态,当SQL指令发生的时候,都会令行中数据发生改变,每一行总会有两种状态:数据操作前和操作后 Before:在表中数据发生改变前的状态 After:在表中数据已经发生改变后的状态 触发事件 触发事件:mysql中触发器针对的目标是数据发生改变,对应的操作只有写操作(增删改) Insert:插入操作 Update:更新操作 Delete:删除操作 注意事项 一张表中,每一个触发时机绑定的触发事件对应的触发器类型只能有一个:一张表中只能有一个对应after insert触发器 因此,一张表中最多的触发器只能有6个:before insert,before update,before delete,after insert,after update,after delete 需求:有两张表,一张是商品表,一张是订单表(保留商品ID),每次订单生成,商品表中对应的库存就应该发生变化。 需求:有两张表,一张是商品表,一张是订单表(保留商品ID),每次订单生成,商品表中对应的库存就应该发生变化。 1、 创建两张表:商品表和订单表 create table my_goods( id int primary key auto_increment, name varchar(20) not null, inv int )charset utf8; create table my_orders( id int primary key auto_increment, goods_id int not null, goods_number int not null )charset utf8; insert into my_goods values(null,'手机',1000),(null,'电脑',500),(null,'游戏机',100); 2、 创建触发器:如果订单表发生数据插入,对应的商品就应该减少库存 Create trigger 名字 after insert on my_orders for each row create trigger after_insert_order_t after insert on my_orders for each row begin --更新商品库存 update my_goods set inv = inv -1 where id = 1; end; 查看触发器 1、 查看全部触发器 Show triggers; 2、 查看触发器的创建语句 Show create trigger 触发器名字; 触发触发器 想办法让触发器执行:让触发器指定的表中,对应的时机发生对应的操作即可。 1、 表为my_orders 2、 在插入之后 3、 插入操作 删除触发器 基本语法:drop trigger 触发器名字; 触发器应用 记录关键字:new、old 触发器针对的是数据表中的每条记录(每行),每行在数据操作前后都有一个对应的状态,触发器在执行之前就将对应的状态获取到了, 将没有操作之前的状态(数据)都保存到old关键字中,而操作后的状态都放到new中。 在触发器中,可以通过old和new来获取绑定表中对应的记录数据。 基本语法:关键字.字段名 Old和new并不是所有触发器都有: Insert:插入前全为空,没有old Delete:清空数据,没有new 触发器案例-商品自动扣除库存----------- create trigger a_i_o_t after insert on my_orders for each row begin --更新商品库存:new代表着新增的订单 update my_goods set inv = inv - new.goods_number where id = new.goods_id; end; 如果库存数量没有商品订单多怎么办? 操作目标:订单表,操作时机:下单前;操作事件:插入 --判断库存 create trigger b_i_o_t before insert on my_orders for each row begin --取出库存数据进行判断 select inv from my_goods where id=new.goods_id into @inv; --判断 if @inv < new.goods_number then --中断操作:暴力解决,主动出错 insert into xxx values('xxx'); end if; end;
标签:语句,究极,速成,语法,MySQL,查询,数据,主键,select 来源: https://www.cnblogs.com/svipero/p/12568995.html