第一章SQL的介绍1。1、什么是sqlSQL:StructureQueryLanguage。(结构化查询语言),通过sql操作数据库(操作数据库,操作表,操作数据)SQL被美国国家标准局(ANSI)确定为关系型数据库语言的美国标准,后来被国际化标准组织(ISO)采纳为关系数据库语言的国际标准各数据库厂商(MySql,oracle,sqlserver)都支持ISO的SQL标准。各数据库厂商在标准的基础上做了自己的扩展。各个数据库自己特定的语法1。2、sql的分类DataDefinitionLanguage(DDL数据定义语言)如:操作数据库,操作表DataManipulationLanguage(DML数据操纵语言),如:对表中的记录操作增删改DataQueryLanguage(DQL数据查询语言),如:对表中数据的查询操作DataControlLanguage(DCL数据控制语言),如:对用户权限的设置1。3、MySQL的语法规范和要求 (1)mysql的sql语法不区分大小写 MySQL的关键字和函数名等不区分大小写,但是对于数据值是否区分大小写,和字符集与校对规则有关。 ci(大小写不敏感),cs(大小写敏感),bin(二元,即比较是基于字符编码的值而与language无关,区分大小写) (2)命名时:尽量使用26个英文字母大小写,数字09,下划线,不要使用其他符号userid (3)建议不要使用mysql的关键字等来作为表名、字段名等,如果不小心使用,请在SQL语句中使用(飘号)引起来 (4)数据库和表名、字段名等对象名中间不要包含空格 (5)同一个mysql软件中,数据库不能同名,同一个库中,表不能重名,同一个表中,字段不能重名 (6)标点符号:必须成对必须英文状态下半角输入方式字符串和日期类型可以使用单引号’’列的别名可以使用双引号,给表名取别名不要使用双引号。取别名时as可以省略如果列的别名没有包含空格,可以省略双引号,如果有空格双引号不能省略。 (7)SQL脚本中如何加注释单行注释:注释内容单行注释:空格注释内容其中后面的空格必须有多行注释:注释内容以下两句是一样的,不区分大小写showdatabases;SHOWDATABASES;创建表格createtablestudentinfo(。。。);表名错误,因为表名有空格createtablestudentinfo(。。。);其中name使用飘号,因为name和系统关键字或系统函数名等预定义标识符重名了。CREATETABLEtstu(idINT,nameVARCHAR(20));selectidas编号,nameas姓名fromtstu;起别名时,as都可以省略selectidas编号,nameas姓名fromtstu;如果字段别名中没有空格,那么可以省略selectidas编号,nameas姓名fromtstu;错误,如果字段别名中有空格,那么不能省略第二章DDL操作数据库2。1、创建数据库(掌握)语法createdatabase数据库名〔characterset字符集〕〔collate校对规则〕注:〔〕意思是可选的意思 字符集(charset):是一套符号和编码。练习 创建一个day01的数据库(默认字符集)createdatabaseday01; 创建一个day012的数据库,指定字符集为gbk(了解)createdatabaseday012charactersetgbk;2。2、查看所有的数据库查看所有的数据库 语法showdatabases;查看数据库的定义结构【了解】 语法showcreatedatabase数据库名; 查看day01这个数据库的定义showcreatedatabaseday01;2。3、删除数据库 语法dropdatabase数据库名; 删除day012数据库dropdatabaseday012;2。4、修改数据库【了解】 语法alterdatabase数据库名characterset字符集; 修改day01这个数据库的字符集(gbk)alterdatabaseday01charactersetgbk; 注意:是utf8,不是utf8不是修改数据库名2。5、其他操作 切换数据库,选定哪一个数据库use数据库名;注意:在创建表之前一定要指定数据库。use数据库名 练习:使用day01useday01; 查看正在使用的数据库selectdatabase();第三章DDL操作表3。1、创建表语法createtable表名(列名类型〔约束〕,列名类型〔约束〕。。。);类型 数值类型 整型系列:xxxIntint(M),必须和unsignedzerofill一起使用才有意义 浮点型系列:float,double(或real)double(M,D):表示最长为M位,其中小数点后D位例如:double(5,2)表示的数据范围〔999。99,999。99〕,如果超过这个范围会报错。定点型系列:decimal(底层实际上是使用字符串进行存储)decimal(M,D):表示最长为M位,其中小数点后D位 位类型:bit字节范围是:18,值范围是:bit(1)bit(64),默认bit(1) 用来存储二进制数。对于位字段,直接使用select命令将不会看到结果。可以使用bit()或hex()函数进行读取。插入bit类型字段时,使用bit()函数转为二进制值再插入,因为二进制码是01。 日期时间类型 日期时间类型:year,date,datetime,timestamp 注意一下每一种日期时间的表示范围 timestamp和datetime的区别:timestamp范围比较小timestamp和时区有关showvariableslike‘timezone’;settimezone‘8:00’;timestamp受MySQL版本和服务器的SQLMode影响很大表中的第一个非空的timestamp字段如果插入和更新为NULL则会自动设置为系统时间 字符串类型 MySQL中提供了多种对字符数据的存储类型,不同的版本可能有所差异。常见的有:char,varchar,xxtext,binary,varbinary,xxblob,enum,set等等 字符串类型char,varchar(M)char如果没有指定宽度,默认为1个字符varchar(M),必须指定宽度 binary和varbinary类似于char和varchar,不同的是它们包含二进制字符串,不支持模糊查询之类的。 一般在保存少量字符串的时候,我们会选择char和varchar;而在保存较大文本时,通常会选择使用text或blob系列。blob和text值会引起一些性能问题,特别是在执行了大量的删除操作时,会在数据表中留下很大的空洞,为了提高性能,建议定期时候用optimizetable功能对这类表进行碎片整理。可以使用合成的(Synthetic)索引来提高大文本字段的查询性能,如果需要对大文本字段进行模糊查询,MySql提供了前缀索引。但是仍然要在不必要的时候避免检索大型的blob或text值。 enum枚举类型,它的值范围需要在创建表时通过枚举方式显式指定,对于1255个成员的枚举需要1个字节存储;对于【25565535】个成员需要2个字节存储。例如:genderenum(‘男’,‘女’)。如果插入枚举值以外的值,会按第一个值处理。一次只能从枚举值中选择一个。 set集合类型,可以包含064个成员。一次可以从集合中选择多个成员。如果选择了18个成员的集合,占1个字节,依次占2个,3个8个字节。例如:hoppyset(‘吃饭’,‘睡觉’,‘玩游戏’,‘旅游’),选择时’吃饭,睡觉’或’睡觉,玩游戏,旅游’ 示例FieldTypeNullKeyDefaultExtraeidint(11)NOPRINULLautoincrementenamevarchar(20)NONULLtelchar(11)NONULLgenderchar(1)YES男salarydoubleYESNULLcommissionpctdouble(3,2)YESNULLbirthdaydateYESNULLhiredatedateYESNULLjobidint(11)YESNULLemailvarchar(32)YESNULLmidint(11)YESNULLaddressvarchar(150)YESNULLnativeplacevarchar(10)YESNULLdidint(11)YESNULL 约束即规则,规矩限制;作用:保证用户插入的数据保存到数据库中是符合规范的 约束种类:notnull:非空;eg:usernamevarchar(40)notnullusername这个列不能有null值unique:唯一约束,后面的数据不能和前面重复;eg:cardNochar(18)unique;cardNo列里面不可以有重复数据primarykey;主键约束(非空唯一);一般用在表的id列上面。一张表基本上都有id列的,id列作为唯一标识的autoincrement:自动增长,必须是设置了primarykey之后,才可以使用autoincrementidintprimarykeyautoincrement;id不需要我们自己维护了,插入数据的时候直接插入null,自动的增长进行填充进去,避免重复了。 注意:先设置了primarykey再能设置autoincrement只有当设置了autoincrement才可以插入null,否则插入null会报错 id列:给id设置为int类型,添加主键约束,自动增长或者给id设置为字符串类型,添加主键约束,不能设置自动增长 练习 创建一张学生表(含有id字段,姓名字段不能重复,性别字段不能为空默认值为男。id为主键自动增长)CREATETABLEstudent(idINTPRIMARYKEYAUTOINCREMENT,主键自增长NAMEVARCHAR(30)UNIQUE,唯一约束genderCHAR(1)NOTNULLDEFAULT男);3。2、查看表【了解】 查看所有的表showtables; 查看表的定义结构 语法desc表名; 练习:查看student表的定义结构descstudent;3。3、修改表【掌握,但是不要记忆】 语法增加一列altertable【数据库名。〕表名称add【column】字段名数据类型;altertable【数据库名。〕表名称add【column】字段名数据类型first;altertable【数据库名。〕表名称add【column】字段名数据类型after另一个字段;修改列的类型约束:altertable表名modify字段类型约束;修改列的名称,类型,约束:altertable表名change旧列新列类型约束;删除一列:altertable表名drop列名;修改表名:renametable旧表名to新表名; 练习 给学生表增加一个grade字段,类型为varchar(20),不能为空ALTERTABLEstudentADDgradeVARCHAR(20)NOTNULL; 给学生表的gender字段改成int类型,不能为空,默认值为1altertablestudentmodifygendervarchar(20); 给学生表的grade字段修改成class字段ALTERTABLEstudentCHANGEgradeclassVARCHAR(20)NOTNULL; 把class字段删除ALTERTABLEstudentDROPclass; 把学生表修改成老师表(了解)RENAMETABLEstudentTOteacher;3。4、删除表【掌握】 语法droptable表名; 把teacher表删除droptableteacher;第四章DML操作表记录增删改【重点】 准备工作:创建一张商品表(商品id,商品名称,商品价格,商品数量。)createtableproduct(pidintprimarykeyautoincrement,pnamevarchar(40),pricedouble,numint);4。1、插入记录 语法方式一:插入指定列,如果没有把这个列进行列出来,以null进行自动赋值了。 eg:只想插入pname,price,insertintotproduct(pname,price)values(‘mac’,18000);insertinto表名(列,列。。)values(值,值。。); 注意:如果没有插入了列设置了非空约束,会报错的方式二:插入所有的列,如果哪列不想插入值,则需要赋值为null insertinto表名values(值,值。。。。); eg:insertintoproductvalues(null,苹果电脑,18000。0,10);insertintoproductvalues(null,华为5G手机,30000,20);insertintoproductvalues(null,小米手机,1800,30);insertintoproductvalues(null,iPhonex,8000,10);insertintoproductvalues(null,iPhone7,6000,200);insertintoproductvalues(null,iPhone6s,4000,1000);insertintoproductvalues(null,iPhone6,3500,100);insertintoproductvalues(null,iPhone5s,3000,100);insertintoproductvalues(null,方便面,4。5,1000);insertintoproductvalues(null,咖啡,11,200);insertintoproductvalues(null,矿泉水,3,500);4。2、更新记录语法update表名set列值,列值〔where条件〕练习 将所有商品的价格修改为5000元updateproductsetprice5000; 将商品名是苹果电脑的价格修改为18000元UPDATEproductsetprice18000WHEREpname苹果电脑; 将商品名是苹果电脑的价格修改为17000,数量修改为5UPDATEproductsetprice17000,num5WHEREpname苹果电脑; 将商品名是方便面的商品的价格在原有基础上增加2元UPDATEproductsetpriceprice2WHEREpname方便面;4。3、删除记录delete 根据条件,一条一条数据进行删除 语法deletefrom表名〔where条件〕注意:删除数据用delete,不用truncate 类型 删除表中名称为’苹果电脑’的记录deletefromproductwherepname苹果电脑; 删除价格小于5001的商品记录deletefromproductwhereprice5001; 删除表中的所有记录(要删除一般不建议使用delete语句,delete语句是一行一行执行,速度过慢)deletefromproduct;truncate 把表直接DROP掉,然后再创建一个同样的新表。删除的数据不能找回。执行速度比DELETE快truncatetable表;工作中删除数据物理删除:真正的删除了,数据不在,使用delete就属于物理删除逻辑删除:没有真正的删除,数据还在。搞一个标记,其实逻辑删除是更新eg:state1启用0禁用第五章DQL操作表记录查询【重点】5。1、基本查询语法select要查询的字段名from表名〔where条件〕5。2、简单查询 查询所有行和所有列的记录语法selectform表查询商品表里面的所有的列selectfromproduct; 查询某张表特定列的记录语法select列名,列名,列名。。。from表查询商品名字和价格selectpname,pricefromproduct;去重查询distinct语法SELECTDISTINCT字段名FROM表名;要数据一模一样才能去重去重查询商品的名字SELECTDISTINCTpname,priceFROMproduct注意点:去重针对某列,distinct前面不能先出现列名 别名查询语法select列名as别名,列名from表列别名as可以不写select别名。from表as别名表别名(多表查询,明天会具体讲)查询商品信息,使用别名SELECTpid,pnameAS商品名,priceAS商品价格,numAS商品库存FROMproduct运算查询(,,,,等) 把商品名,和商品价格10查询出来:我们既可以将某个字段加上一个固定值,又可以对多个字段进行运算查询selectpname,price10aspricefromproduct;selectname,chinesemathenglishastotalfromstudent 注意运算查询字段,字段之间是可以的字符串等类型可以做运算查询,但结果没有意义5。3、条件查询(很重要)语法select。。。from表where条件取出表中的每条数据,满足条件的记录就返回,不满足条件的记录不返回运算符 1、比较运算符大于:小于:大于等于:小于等于:等于:不能用于null判断不等于:!或安全等于:可以用于null值判断 2、逻辑运算符(建议用单词,可读性来说)逻辑与:或and逻辑或:或or逻辑非:!或not逻辑异或:或xor 3、范围区间范围:betweenxandynotbetweenxandy集合范围:in(x,x,x)notin(x,x,x) 4、模糊查询和正则匹配(只针对字符串类型,日期类型)likexxx模糊查询是处理字符串的时候进行部分匹配如果想要表示0n个字符,用如果想要表示确定的1个字符,用regexp正则 5、特殊的null值处理(1)判断时xxisnullxxisnotnullxxnull(2)计算时ifnull(xx,代替值)当xx是null时,用代替值计算练习 查询商品价格3000的商品selectfromproductwhereprice3000; 查询pid1的商品selectfromproductwherepid1; 查询pid1的商品(!)selectfromproductwherepid1; 查询价格在3000到6000之间的商品selectfromproductwherepricebetween3000and6000; 查询pid在1,5,7,15范围内的商品selectfromproductwhereid1;selectfromproductwhereid5;selectfromproductwhereid7;selectfromproductwhereid15;selectfromproductwhereidin(1,5,7,15); 查询商品名以iPho开头的商品(iPhone系列)selectfromproductwherepnamelikeiPho; 查询商品价格大于3000并且数量大于20的商品(条件and条件and)selectfromproductwhereprice3000andnum20; 查询id1或者价格小于3000的商品selectfromproductwherepid1orprice3000;5。4、排序查询 排序是写在查询的后面,代表把数据查询出来之后再排序环境的准备创建学生表(有sid,学生姓名,学生性别,学生年龄,分数列,其中sid为主键自动增长)CREATETABLEstudent(sidINTPRIMARYKEYautoincrement,snameVARCHAR(40),sexVARCHAR(10),ageINT,scoreDOUBLE);INSERTINTOstudentVALUES(null,zs,男,18,98。5);INSERTINTOstudentVALUES(null,ls,女,18,96。5);INSERTINTOstudentVALUES(null,ww,男,15,50。5);INSERTINTOstudentVALUES(null,zl,女,20,98。5);INSERTINTOstudentVALUES(null,tq,男,18,60。5);INSERTINTOstudentVALUES(null,wb,男,38,98。5);INSERTINTOstudentVALUES(null,小丽,男,18,100);INSERTINTOstudentVALUES(null,小红,女,28,28);INSERTINTOstudentVALUES(null,小强,男,21,95);单列排序 语法:只按某一个字段进行排序,单列排序SELECT字段名FROM表名〔WHERE条件〕ORDERBY字段名〔ASCDESC〕;ASC:升序,默认值;DESC:降序 案例:以分数降序查询所有的学生SELECTFROMstudentORDERBYscoreDESC组合排序 语法:同时对多个字段进行排序,如果第1个字段相等,则按第2个字段排序,依次类推SELECT字段名FROM表名WHERE字段值ORDERBY字段名1〔ASCDESC〕,字段名2〔ASCDESC〕; 练习:以分数降序查询所有的学生,如果分数一致,再以age降序SELECTFROMstudentORDERBYscoreDESC,ageDESC5。5、聚合函数 聚合函数用于统计,通常会和分组查询一起使用,用于统计每组的数据聚合函数列表 语法SELECT聚合函数(列名)FROM表名〔where条件〕; 案例求出学生表里面的最高分数SELECTMAX(score)FROMstudent求出学生表里面的最低分数SELECTMIN(score)FROMstudent求出学生表里面的分数的总和(忽略null值)SELECTSUM(score)FROMstudent求出学生表里面的平均分SELECTAVG(score)FROMstudent求出学生表里面的平均分(缺考了当成0分处理)SELECTAVG(IFNULL(score,0))FROMstudent统计学生的总人数(忽略null)SELECTCOUNT(sid)FROMstudentSELECTCOUNT()FROMstudent 注意:聚合函数会忽略空值NULL 我们发现对于NULL的记录不会统计,建议如果统计个数则不要使用有可能为null的列,但如果需要把NULL也统计进去呢?我们可以通过IFNULL(列名,默认值)函数来解决这个问题。如果列不为空,返回这列的值。如果为NULL,则返回默认值。求出学生表里面的平均分(缺考了当成0分处理)SELECTAVG(IFNULL(score,0))FROMstudent;5。6、分组查询 GROUPBY将分组字段结果中相同内容作为一组,并且返回每组的第一条数据,所以单独分组没什么用处。分组的目的就是为了统计,一般分组会跟聚合函数一起使用分组 语法SELECT字段1,字段2。。。FROM表名〔where条件〕GROUPBY列〔HAVING条件〕; 案例根据性别分组,统计每一组学生的总人数SELECTsex性别,COUNT(sid)总人数FROMstudentGROUPBYsex根据性别分组,统计每组学生的平均分SELECTsex性别,AVG(score)平均分FROMstudentGROUPBYsex根据性别分组,统计每组学生的总分SELECTsex性别,SUM(score)总分FROMstudentGROUPBYsex分组后筛选having 分组后的条件,不能写在where之后,where关键字要写在groupby之前 根据性别分组,统计每一组学生的总人数5的(分组后筛选)SELECTsex,count()FROMstudentGROUPBYsexHAVINGcount(sid)5 根据性别分组,只统计年龄大于等于18的,并且要求组里的人数大于4SELECTsex性别,COUNT(sid)总人数FROMstudentWHEREage18GROUPBYsexHAVINGCOUNT(sid)4where和having的区别【面试】 where子句作用1)对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,即先过滤再分组。2)where后面不可以使用聚合函数 having字句作用1)having子句的作用是筛选满足条件的组,即在分组之后过滤数据,即先分组再过滤。2)having后面可以使用聚合函数5。7、分页查询语法select。。。from。。。。limita,b 案例分页查询limit关键字是使用在查询的后边,如果有排序的话则使用在排序的后边limit的语法:limitoffset,length其中offset表示跳过多少条数据,length表示查询多少条数据SELECTFROMproductLIMIT0,3查询product表中的前三条数据(0表示跳过0条,3表示查询3条)SELECTFROMproductLIMIT3,3查询product表的第四到六条数据(3表示跳过3条,3表示查询3条)分页的时候,只会告诉你我需要第几页的数据,并且每页有多少条数据假如,每页需要3条数据,我想要第一页数据:limit0,3假如,每页需要3条数据,我想要第二页数据:limit3,3假如,每页需要3条数据,我想要第三页数据:limit6,3结论:length每页的数据条数,offset(当前页数1)每页数据条数limit(当前页数1)每页数据条数,每页数据条数5。8、查询的语法小结select。。。from。。。where。。。groupby。。。orderby。。。limitselect。。。from。。。where。。。select。。。from。。。where。。。orderby。。。select。。。from。。。where。。。limit。。。select。。。from。。。where。。。orderby。。。imit第六章数据库三范式 好的数据库设计对数据的存储性能和后期的程序开发,都会产生重要的影响。建立科学的,规范的数据库就需要满足一些规则来优化数据的设计和存储,这些规则就称为范式。6。1、第一范式:确保每列保持原子性 第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。 第一范式的合理遵循需要根据系统的实际需求来定。比如某些数据库系统中需要用到地址这个属性,本来直接将地址属性设计成一个数据库表的字段就行。但是如果系统经常会访问地址属性中的城市部分,那么就非要将地址这个属性重新拆分为省份、城市、详细地址等多个部分进行存储,这样在对地址中某一部分操作的时候将非常方便。这样设计才算满足了数据库的第一范式,如下表所示。 如果不遵守第一范式,查询出数据还需要进一步处理(查询不方便)。遵守第一范式,需要什么字段的数据就查询什么数据(方便查询)6。2、第二范式:确保表中的每列都和主键相关 第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。 比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库表的联合主键,如下表所示 这样就产生一个问题:这个表中是以订单编号和商品编号作为联合主键。这样在该表中商品名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。所以在这里违反了第二范式的设计原则。 而如果把这个订单信息表进行拆分,把商品信息分离到另一个表中,把订单项目表也分离到另一个表中,就非常完美了。如下所示imgsrca2020imgdataimg。jpgdatasrcimgq7。q578。comef121796032bca5c7a380d。jpgstylezoom:67; 这样设计,在很大程度上减小了数据库的冗余。如果要获取订单的商品信息,使用商品编号到商品信息表中查询即可6。3、第三范式:确保每列都和主键列直接相关,而不是间接相关 第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。 比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。imgsrca2020imgdataimg。jpgdatasrcimgq7。q578。comef1217a3c383c41ac5c889。jpgstylezoom:67; 这样在查询订单信息的时候,就可以使用客户编号来引用客户信息表中的记录,也不必在订单信息表中多次输入客户信息的内容,减小了数据冗余第七章外键约束7。1、外键约束的概念 在遵循三范式的前提下,很多时候我们必须要进行拆表,将数据分别存放在多张表中,以减少冗余数据。但是拆分出来的表与表之间是有着关联关系的,我们必须得通过一种约束来约定表与表之间的关系,这种约束就是外键约束7。2、外键约束的作用 外键约束是保证一个或两个表之间的参照完整性,外键是构建于一个表的两个字段或是两个表的两个字段之间的参照关系。7。3、创建外键约束的语法在建表时指定外键约束createtable〔数据名。〕从表名(字段名1数据类型primarykey,字段名2数据类型,。。。。,〔constraint外键约束名〕foreignkey(从表字段)references主表名(主表字段)〔onupdate外键约束等级〕〔ondelete外键约束等级〕外键只能在所有字段列表后面单独指定如果要自己命名外键约束名,建议主表名从表名关联字段名fk);在建表后指定外键约束altertable从表名称add〔constraint外键约束名〕foreignkey(从表字段名)references主表名(主表被参照字段名)〔onupdatexx〕〔ondeletexx〕;7。4、删除外键约束的语法ALTERTABLE表名称DROPFOREIGNKEY外键约束名;查看约束名SELECTFROMinformationschema。tableconstraintsWHEREtablename表名称;删除外键约束不会删除对应的索引,如果需要删除索引,需要用ALTERTABLE表名称DROPINDEX索引名;查看索引名showindexfrom表名称;7。5、外键约束的要求在从表上建立外键,而且主表要先存在。一个表可以建立多个外键约束通常情况下,从表的外键列一定要指向主表的主键列从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样7。6、外键约束等级Cascade方式:在主表上updatedelete记录时,同步updatedelete掉从表的匹配记录Setnull方式:在主表上updatedelete记录时,将从表上匹配记录的列设为null,但是要注意子表的外键列不能为notnullNoaction方式:如果子表中有匹配的记录,则不允许对父表对应候选键进行updatedelete操作Restrict方式:同noaction,都是立即检查外键约束Setdefault方式(在可视化工具SQLyog中可能显示空白):父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别如果没有指定等级,就相当于Restrict方式7。7、外键约束练习部门表createtabledept(idintprimarykey,deptnamevarchar(50),deptlocationvarchar(50));员工表CREATETABLEemp(eidintprimarykey,namevarchar(50)notnull,sexvarchar(10),deptidint);给员工表表的deptid添加外键指向部门表的主键altertableempaddforeignkey(deptid)referencesdept(id)第八章多表间关系8。1、一对多关系概念 一对多的关系是指:主表的一行数据可以同时对应从表的多行数据,反过来就是从表的多行数据指向主表的同一行数据。应用场景 分类表和商品表、班级表和学生表、用户表和订单表等等建表原则 将一的一方作为主表,多的一方作为从表,在从表中指定一个字段作为外键,指向主表的主键 建表语句练习创建分类表CREATETABLEcategory(cidINTPRIMARYKEYAUTOINCREMENT,cnameVARCHAR(50));创建商品表CREATETABLEproduct(pidINTPRIMARYKEYAUTOINCREMENT,pnameVARCHAR(50),priceDOUBLE,cidINT)给商品表添加一个外键altertableproductaddforeignkey(cid)referencescategory(cid)8。2、多对多关系概念 两张表都是多的一方,A表的一行数据可以同时对应B表的多行数据,反之B表的一行数据也可以同时对应A表的多行数据应用场景 订单表和商品表、学生表和课程表等等建表原则 因为两张表都是多的一方,所以在两张表中都无法创建外键,所以需要新创建一张中间表,在中间表中定义两个字段,这俩字段分别作为外键指向两张表各自的主键 建表语句练习创建学生表CREATETABLEstudent(sidINTPRIMARYKEYAUTOINCREMENT,snameVARCHAR(50));创建课程表CREATETABLEcourse(cidINTPRIMARYKEYAUTOINCREMENT,cnameVARCHAR(20));创建中间表CREATETABLEsctable(snoINT,cnoINT);给sno字段添加外键指向student表的sid主键ALTERTABLEsctableADDCONSTRAINTfkey01FOREIGNKEY(sno)REFERENCESstudent(sid);给cno字段添加外键指向course表的cid主键ALTERTABLEsctableADDCONSTRAINTfkey03FOREIGNKEY(cno)REFERENCEScourse(cid);8。3、一对一关系(了解)第一种一对一关系 我们之前学习过一对多关系,在一对多关系中主表的一行数据可以对应从表的多行数据,反之从表的一行数据则只能对应主表的一行数据。这种一行数据对应一行数据的关系,我们可以将其看作一对一关系第二种一对一关系 A表中的一行数据对应B表中的一行数据,反之B表中的一行数据也对应A表中的一行数据,此时我们可以将A表当做主表B表当做从表,或者是将B表当做主表A表当做从表建表原则 在从表中指定一个字段创建外键并指向主表的主键,然后给从表的外键字段添加唯一约束第九章多表关联查询 多表关联查询是使用一条SQL语句,将关联的多张表的数据查询出来9。1、环境准备创建一张分类表(类别id,类别名称。备注:类别id为主键并且自动增长)CREATETABLEtcategory(cidINTPRIMARYKEYautoincrement,cnameVARCHAR(40));INSERTINTOtcategoryvalues(null,手机数码);INSERTINTOtcategoryvalues(null,食物);INSERTINTOtcategoryvalues(null,鞋靴箱包);创建一张商品表(商品id,商品名称,商品价格,商品数量,类别。备注:商品id为主键并且自动增长)CREATETABLEtproduct(pidINTPRIMARYKEYautoincrement,pnameVARCHAR(40),priceDOUBLE,numINT,cnoINT);insertintotproductvalues(null,苹果电脑,18000,10,1);insertintotproductvalues(null,iPhone8s,5500,100,1);insertintotproductvalues(null,iPhone7,5000,100,1);insertintotproductvalues(null,iPhone6s,4500,1000,1);insertintotproductvalues(null,iPhone6,3800,200,1);insertintotproductvalues(null,iPhone5s,2000,10,1);insertintotproductvalues(null,iPhone4s,18000,1,1);insertintotproductvalues(null,方便面,4。5,1000,2);insertintotproductvalues(null,咖啡,10,100,2);insertintotproductvalues(null,矿泉水,2。5,100,2);insertintotproductvalues(null,法拉利,3000000,50,null);给商品表添加外键ALTERTABLEtproductADDFOREIGNKEY(cno)REFERENCEStcategory(cid);9。2、交叉查询【了解】 交叉查询其实就是将多张表的数据没有条件地连接在一起进行展示语法selecta。列,a。列,b。列,b。列froma,b;selecta。,b。froma,b;或者selectfroma,b;练习 使用交叉查询类别和商品selectfromtcategory,tproduct; 通过查询结果我们可以看到,交叉查询其实是一种错误的做法,在查询到的结果集中有大量的错误数据,我们称交叉查询到的结果集是笛卡尔积笛卡尔积 假设集合A{a,b},集合B{0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况。9。3、内连接查询 交叉查询产生这样的结果并不是我们想要的,那么怎么去除错误的、不想要的记录呢,当然是通过条件过滤。通常要查询的多个表之间都存在关联关系,那么就通过关联关系(主外键关系)去除笛卡尔积。这种通过条件过滤去除笛卡尔积的查询,我们称之为连接查询。连接查询又可以分为内连接查询和外连接查询,我们先学习内连接查询隐式内连接查询 隐式内连接查询里面是没有innerjoin关键字select〔字段,字段,字段〕froma,bwhere连接条件(b表里面的外键a表里面的主键)显式内连接查询 显式内连接查询里面是有innerjoin关键字select〔字段,字段,字段〕froma〔inner〕joinbon连接条件〔where其它条件〕内连接查询练习 查询所有类别下的商品信息,如果该类别下没有商品则不展示1隐式内连接方式selectfromtcategoryc,tproductpWHEREc。cidp。cno;2显示内连接方式查询手机数码这个分类下的所有商品的信息以及分类信息SELECTFROMtproducttpINNERJOINtcategorytcONtp。cnotc。cidWHEREtc。cname手机数码;SELECTfromtcategorycINNERJOINtproductpONc。cidp。cno内连接查询的特点 主表和从表中的数据都是满足连接条件则能够查询出来,不满足连接条件则不会查询出来9。4、外连接查询 我们发现内连接查询出来的是满足连接条件的公共部分,如果要保证查询出某张表的全部数据情况下进行连接查询。那么就要使用外连接查询了。外连接分为左外连接和右外连接左外连接查询 概念 以join左边的表为主表,展示主表的所有数据,根据条件查询连接右边表的数据,若满足条件则展示,若不满足则以null显示。可以理解为:在内连接的基础上保证左边表的数据全部显示 语法select字段fromaleft〔outer〕joinbon条件 练习 查询所有类别下的商品信息,就算该类别下没有商品也需要将该类别的信息展示出来SELECTFROMtcategorycLEFTOUTERJOINtproductpONc。cidp。cno右外连接查询 概念 以join右边的表为主表,展示右边表的所有数据,根据条件查询join左边表的数据,若满足则展示,若不满足则以null显示。可以理解为:在内连接的基础上保证右边表的数据全部显示 语法select字段fromaright〔outer〕joinbon条件 练习 查询所有商品所对应的类别信息SELECTFROMtcategorycRIGHTOUTERJOINtproductpONc。cidp。cno9。5、union联合查询实现全外连接查询 首先要明确,联合查询不是多表连接查询的一种方式。联合查询是将多条查询语句的查询结果合并成一个结果并去掉重复数据。 全外连接查询的意思就是将左表和右表的数据都查询出来,然后按照连接条件连接union的语法查询语句1union查询语句2union查询语句3。。。练习用左外的Aunion右外的BSELECTFROMtcategorycLEFTOUTERJOINtproductpONc。cidp。cnounionSELECTFROMtcategorycRIGHTOUTERJOINtproductpONc。cidp。cno9。6、自连接查询 自连接查询是一种特殊的多表连接查询,因为两个关联查询的表是同一张表,通过取别名的方式来虚拟成两张表,然后进行两张表的连接查询准备工作员工表CREATETABLEemp(idINTPRIMARYKEY,员工idenameVARCHAR(50),员工姓名mgrINT,上级领导joindateDATE,入职日期salaryDECIMAL(7,2)工资);添加员工INSERTINTOemp(id,ename,mgr,joindate,salary)VALUES(1001,孙悟空,1004,20001217,8000。00),(1002,卢俊义,1006,20010220,16000。00),(1003,林冲,1006,20010222,12500。00),(1004,唐僧,1009,20010402,29750。00),(1005,李逵,1006,20010928,12500。00),(1006,宋江,1009,20010501,28500。00),(1007,刘备,1009,20010901,24500。00),(1008,猪八戒,1004,20070419,30000。00),(1009,罗贯中,NULL,20011117,50000。00),(1010,吴用,1006,20010908,15000。00),(1011,沙僧,1004,20070523,11000。00),(1012,李逵,1006,20011203,9500。00),(1013,小白龙,1004,20011203,30000。00),(1014,关羽,1007,20020123,13000。00);查询孙悟空的上级SELECTemployee。,manager。enamemgrnameFROMempemployee,empmanagerwhereemployee。mgrmanager。idANDemployee。ename孙悟空自连接查询练习 查询员工的编号,姓名,薪资和他领导的编号,姓名,薪资这些数据全部在员工表中把temployee表,即当做员工表,又当做领导表领导表是虚拟的概念,我们可以通过取别名的方式虚拟SELECTemployee。id员工的编号,emp。ename员工的姓名,emp。salary员工的薪资,manager。id领导的编号,manager。ename领导的姓名,manager。salary领导的薪资FROMempemployeeINNERJOINempmanagerempemployee:employee。,表示的是员工表的empmanager:如果用manager。,表示的是领导表的ONemployee。mgrmanager。id员工的mgr指向上级的id表的别名不要加,给列取别名,可以用,列的别名不使用也可以,但是要避免包含空格等特殊符号。第十章子查询 如果一个查询语句嵌套在另一个查询语句里面,那么这个查询语句就称之为子查询,根据位置不同,分为:where型,from型,exists型。注意:不管子查询在哪里,子查询必须使用()括起来。10。1、where型 子查询是单值结果(单行单列),那么可以对其使用(,等比较运算符)查询价格最高的商品信息selectfromtproductwhereprice(selectmax(price)fromtproduct) 子查询是多值结果,那么可对其使用(【not】in(子查询结果),或all(子查询结果),或all(子查询结果),any(子查询结果),或any(子查询结果),查询价格最高的商品信息SELECTFROMtproductWHEREpriceALL(SELECTpriceFROMtproduct)selectfromtproductorderbypricedesclimit0,110。2、from型 子查询的结果是多行多列的结果,类似于一张表格。 必须给子查询取别名,即临时表名,表的别名不要加和空格。思路一:使用连接查询使用外连接,查询出分类表的所有数据SELECTtc。cname,COUNT(tp。pid)FROMtcategorytcLEFTJOINtproducttpONtp。cnotc。cidGROUPBYtc。cname思路二:使用子查询第一步:对tproduct根据cno进行分组查询,统计每个分类的商品数量SELECTcno,COUNT(pid)FROMtproductGROUPBYcno第二步:用tcategory表去连接第一步查询出来的结果,进行连接查询,此时要求查询出所有的分类SELECTtc。cname,IFNULL(tn。total,0)总数量FROMtcategorytcLEFTJOIN(SELECTcno,COUNT(pid)totalFROMtproductGROUPBYcno)tnONtn。cnotc。cid10。3、exists型查询那些有商品的分类SELECTcid,cnameFROMtcategorytcWHEREEXISTS(SELECTFROMtproducttpWHEREtp。cnotc。cid); 链接:blog。csdn。netqq42076902articledetails121701974