第一章数据的检索
第一节SELECT基本用法1、简单的数据检索、
“取出一张表中所有的数据”是最简单的数据检索任务,完成这个最简单任务的语句也是最简单的,我们只要执行【SELECT*FROM表名】即可.
2、检索出需要的列、
【SELECT*FROM表名】其中的星号“*”就意味着“所有列”,那么我们只要将星号“*”替换成我们要检索的列名就可以了。只要在SELECT语句后列出各个列的列名就可以了,需要注意的就是各个列之间要用半角的逗号“,”分隔开。即【SELECT列1,列2,列3,…FROM表名】【列列,
3、列别名、
别名的定义格式为【列名AS别名】定义别名的时候“AS”不是必须的,是可以省略的。如果数据库系【别名】。统支持中文列名,那么还可以用中文来为列设定别名,这样可读性就更好了。其具体的SQL语句是:可省略)【SELECT列1AS别名1,列2AS别名2,列3AS别名3,…FROM表名】(AS可省略)列列,
4、按条件过滤、
数据检索是数据库系统的一个非常重要的任务,它内置了对按条件过滤数据的支持,只要为SELECT语句指定WHERE语句即可。【Select*From表名Where范围】范围】【
5、数据汇总、
有时需要对数据库中的数据进行一些统计,SQL中提供了聚合函数聚合函数来完成计算统计结果集条数【Count】、聚合函数某个字段的最大值【Max】、某个字段的最小值【Min】、某个字段的平均值【AVG】以及某个字段的合计值【SUN】等数据统计的功能。总数:selectcount(*)astotalcountfromtable1总数:总数求和:平均:求和:selectsum(field1)assumvaluefromtable1平均:selectavg(field1)asavgvaluefromtable1最小:最大:最大:selectmax(field1)asmaxvaluefromtable1最小:selectmin(field1)asminvaluefromtable1注意:列名)】注意【COUNT(*)】统计的是结果集的总条数。而【COUNT(列名】统计的则是除了结果集中列名不【列名为空值(也就是不等于NULL)的记录的总条数。因此在使用聚合函数COUNT的时候一定要区分两种使用方式的区别,以防止出现数据错误。
6、排序、
SELECT语句允许使用ORDERBY子句来执行结果集的排序方式。ORDERBY子句位于SELECT语句的末尾,它允许指定按照一个列或者多个列进行排序,还可以指定排序方式是升序【ASC】(从小到大排列)还是降序【DESC】(从大到小排列)。对于ORDERBY子句来说,升序是默认的排序方式,如果要采用升序的话ASC可以省略。【排序:SELECT*FROMtable1ORDERBYfield1[ASC],field2[DESC]】排序:排序ORDERBY子句完全可以与WHERE子句一起使用,唯一需要注意的就是ORDERBY子句要放到WHERE子句之后,不能颠倒它们的顺序。
第二节高级数据过滤【数据过滤则是数据检索中最核心的部分】高级数据过滤【
1、通配符过滤【包括单字符匹配,多字符匹配,集合匹配,单字符匹配和多字符匹配还可以一起使用】、。
语句:用法详解】【SQL语句:SELECTLIKE用法详解】【%、_、[]、[^]、*、?、#、[!]】、、、、、、
LIKE语句的语法格式是:select*from表名where字段名like对应值(子串)对应值(子串),它主要是针对字符型字段的,它的作用是在一个字符型字段列中检索包含对应子串的。1:%包含零个或多个字符的任意字符串:包含零个或多个字符的任意字符串:零个或多个字符的任意字符串<1>LIKE'Mc%'将搜索以字母Mc开头的所有字符串(如McBadden)。<2>LIKE'%inger'将搜索以字母inger结尾的所有字符串(如Ringer、Stringer)。<3>LIKE'%en%'将搜索在任何位置包含字母en的所有字符串(如Bennet、Green、McBadden)。2:_(下划线)任何单个字符:(下划线)任何单个字符:LIKE'_heryl'将搜索以字母heryl结尾的所有六个字母的名称(如Cheryl、Sheryl)。3:[]指定范围([a-f])或集合([abcdef])中的任何单个字符:中的任何单个字符任何单个字符::<1>LIKE'[CK]ars[eo]n'将搜索下列字符串:Carsen、Karsen、Carson和Karson(如Carson)。
<2>LIKE'[M-Z]inger'将搜索以字符串inger结尾,以从M到Z的任何单个字母开头的所有名称(如Ringer)。4:[^]不属于指定范围([a-f])或集合([abcdef])的任何单个字符:任何单个字符::LIKE'M[^c]%'将搜索以字母M开头,并且第二个字母不是c的所有名称(如MacFeather)。5:*它同于DOS命令中的通配符,代表多个字符:c*c代表cc,cBc,cbc,cabdfec等多个字符。命令中的通配符,代表多个字符多个字符::6:?同于DOS命令中的?通配符,代表单个字符:b?b代表brb,bFb等:?同于命令中的?通配符,代表单个字符单个字符::?7:#大致同上,不同的是代只能代表单个数字。k#k代表k1k,k8k,k0k。单个数字。:大致同上,不同的是代只能代表单个数字8:[!]排除它只代表单个字符它只代表单个字符:下面来举例说明一下:例1,查询name字段中包含有“明”字的。【select*fromtable1wherenamelike'%明%'】例2,查询name字段中以“李”字开头。【select*fromtable1wherenamelike'李*'】例3,查询name字段中含有数字的。【select*fromtable1wherenamelike'%[0-9]%'】例4,查询name字段中含有小写字母的。【select*fromtable1wherenamelike'%[a-z]%'】例5,查询name字段中不含有数字的。【select*fromtable1wherenamelike'%[!0-9]%'】以上例子能列出什么值来显而易见。但在这里,我们着重要说明的是通配符“*”与“%”的区别。很多人会问,为什么我在以上查询时有个别的表示所有字符的时候用"%"而不用“*”?先看看下面的例子能分别出现什么结果:select*fromtable1wherenamelike'*明*'明select*fromtable1wherenamelike'%明%'明大家会看到,前一条语句列出来的是所有的记录,而后一条记录列出来的是name字段中含有“明”的记录,所以说,当我们作字符型字段包含一个子串的查询时最好采用“%”而不用“*”,用“*”的时候只在开头或者只在结尾时,而不能两端全由“*”代替任意字符的情况下。
2、空值检测ISNULL、ISNOTNULL】、空值检测【
在SQL语句中对空值的处理有些特别,不能使用普通的等于运算符进行判断,而要使用ISNULL关键字,使用方法为【待检测字段名ISNULL】;如果要检测“字段不为空”,则要使用ISNOTNULL,使用方法为【待检测字段名ISNOTNULL】。ISNULL/ISNOTNULL可以和其他的过滤条件一起使用。
3、反义运算符【=、>、<、>=、<=、!=、<>、notxxx=yyy、not(xxx=yyy)】、反义运算符【、、、、、、、、】
“=”、“<”、“>”等运算符都是用来进行数值判断的,有的时候则会想使用这些运算符的反义,也就是“!=”表、、“”示“不等于”、“!<”表示“不小于”,而“!>”表示“不大于”。不等于””表示“不小于””表示“不大于”使用“!”运算符的方式由于只能运行在MSSQLServer和DB2两种数据库系统上,如果在其他数据库系统上则可以用其他的变通的方式实现,最常用的变通实现方式有两种:使用同义运算符、使用NOT运算符。这样“不等于”、“不大于”和“不小于”就分别可以表示成“<>”、“<=”和“>=”。“”””
NOT运算符用来将一个表达式的值取反,也就是将值为“真”的表达式结果变为“假”,值为“假”的表达式结果变为“真”,使用方式也非常简单【NOT(表达式)】:如:NOT(FAge=22)。而且能够实现复杂的嵌套。
4、多值检测【OR、IN】、、】
我们可以使用OR语句来连接多个等于判断,但是为了解决进行多个离散值的匹配问题,SQL提供了IN语句,使用IN我们只要指定要匹配的数据集合就可以了,使用方法为【IN(值1,值2,值3……)】。使用IN我们还可以让字段与其他表中的值进行匹配,要实现这样的功能就需要IN来搭配子查询来使用,关于这一点我们将在后面的章节介绍。5、范围值检测【BETTWEENAND、NOTBETTWEENAND】、SQL提供了一个专门用于范围值检测的语句“BETTWEENAND”,它可以用来检测一个值是否处于某个范围中(包括范围的边界值,也就是闭区间),如果需要进行开区间或者半开半闭区间的范围值检测的话就必须使用其他的解决方案了。使用方法:【字段名BETTWEEN左范围值AND右范围值】,其等价于【字段名>=左范围值AND字段名<=右范围值】。使用“BETTWEENAND”我们还能够进行多个不连续范围值的检测。如:SELECT*FROMT_EmployeeWHERE(FsalaryBETWEEN2000AND3000)OR(FSalaryBETWEEN5000AND8000)
6、低效的“WHERE1=1”适用动态组装的SQL,如果数据检索对性能有比较高的要求不建议使用】、低效的“”【
第三节数据分组【GROUPBY】】1、数据分组入门、
数据分组用来将数据分为多个逻辑组,从而可以对每个组进行聚合运算。SQL语句中使用GROUPBY子句进行分组,使用方式为【GROUPBY分组字段】分组语句必须和聚合函数一起使用GROUPBY子句。分组语句必须和聚合函数一起使用分组语句必须和聚合函数一起使用,负责将数据分成逻辑组,而聚合函数则对每一个组进行统计计算。需要注意的是GROUPBY子句的位置,GROUPBY子句必须放到SELECT语句的之后,如果SELECT语句有WHERE子句,则GROUPBY子句必须放到WHERE语句的之后。需要分组的所有列都必须位于GROUPBY子句的列名列表中,也就是没有出现在GROUPBY子句中的列(聚合函数除外)是不能放到SELECT语句后的列名列表中的。如下面的两SQL语句:错误的SQL语句:【SELECTFAge,FSalaryFROMT_EmployeeGROUPBYFage】正确的SQL语句:【SELECTFAge,VAG(Fsalary)FROMT_EmployeeGROUPBYFage】GROUPBY子句中可以指定多个列,只需要将多个列的列名用逗号隔开即可。指定多个分组规则以后,数据库系统将按照定义的分组顺序来对数据进行逐层分组,首先按照第一个分组列进行分组,然后在每个小组内按照第二个分组列进行再次分组……逐层分组,从而实现“组中组”的效果,而查询的结果集是以最末一级分组来进行输出的。
2、数据分组与聚合函数、
我们可以使用聚合函数来对分组后的数据进行统计,也就是统计每一个分组的数据。我们甚至可以认为在没有使用GROUPBY语句中使用聚合函数不过是在一个整个结果集是一个组的分组数据中进行数据统计分析罢了。
3、HAVING、
语句
有的时候需要对部分分组进行过滤,HAVING语句中也可以像WHERE语句一样使用复杂的过滤条件。聚合函数不能在WHERE语句中使用,必须使用HAVING子句来代替。如下面两个例子:错误的SQL语句:【SELECTFAge,COUNT(*)FROMT_EmployeeGROUPBYFageWHERECOUNT(*)>1】正确的SQL语句:【SELECTFAge,COUNT(*)FROMT_EmployeeGROUPBYFageHAVINGCOUNT(*)>1】HAVING语句能够使用的语法和WHERE几乎是一样的,不过使用WHERE的时候ORDERBY子句要位于WHERE子句之后,而使用HAVING子句的时候ORDERBY子句要位于HAVING子句之后。需要特别注意,在HAVING语句中不能包含未分组的列名。
第四节限制结果集行数
在进行数据检索的时候有时候需要只检索结果集中的部分行,比如说“检索成绩排前三名的学生”、“检索工资水平排在第3位到第7位的员工信息”,这种功能被称为“限制结果集行数”。在虽然主流的数据库系统中都提供了限制结果集行数的方法,但是无论是语法还是使用方式都存在着很大的差异,即使是同一个数据库系统的不同版本(比如MSSQLServer2000和MSSQLServer2005)也存在着一定的差异。因此本节将按照数据库系统来讲解每种数据库系统对限制结果集行数的特性支持
(待续)待续)
抑制数据重复【第五节抑制数据重复【DISTINCT】】
DISTINCT关键字是用来进行重复数据抑制的最简单的功能,而且所有的数据库系统都支持DISTINCT,DISTINCT的使用也非常简单,只要在SELECT之后增加DISTINCT即可。DISTINCT是对整个结果集进行数据重复抑制的,而不是针对每一个列而不是针对每一个列。而不是针对每一个列
第六节计算字段
计算字段是数据库系统提供的对数据进行计算、转换或者格式化的功能,由于是在数据库系统内部进行的这些工作,而且数据库系统都这些工作进行了优化,所以其处理效率比在宿主语言中通过编写代码的方式进行处理要高效的多。
1、常量字段、
如:【select'杭州友佳'AS公司名称,rownum编号,zx01,zx02fromzx_file】“杭州友佳”中的这一列被称为“常量字段”(也称为“常量值”,它们完全可以被看成一个值确定的字段,其中的“公司名称”则是常量字段)的别名。
2、字段间计算、
如:SELECTFNumber,FName,FAge*FSalaryFROMT_Employee】中同样,【】这里的FAge*FSalary并不是一个实际的存在的列,但是在查询出来的数据中它们看起来是一个实际存在的字段,它们完全可以被看成一个普通字段,同样也可以为其指定别名。前面提到常量字段完全可以当作普通字段来看待,那么普通字段也可以和常量字段进行计算,甚至常量字段之间也可以进行计算。计算字段也可以在WHERE语句等子句或者UPDATE、DELETE中使用。
3、数据处理函数、
像普通编程语言一样,SQL也支持使用函数处理数据,常用的函数处理有:比如进行数值处理的数学函数、进行日期处理的日期函数、进行字符串处理的字符串函数,聚合函数等。我们来演示几个函数使用的典型场景。主流数据库系统都提供了计算字符串长度的函数,MYSQL、在Oracle、DB2中这个函数名称为LENGTH,而在MSSQLServer中这个函数的名称则为LEN。这个函数接受一个字符串类型的字段值做为参数,返回值为这个字符串的长度。如:【selectrownum编号,zx01,zx02,Length(zx02)fromzx_file】计算名字的长度主流系统都提供了取得字符串的子串的函数,在MYSQL、MSSQLServer中这个函数名称为SUBSTRING,而在Oracle、DB2这个函数名称为SUBSTR。这个函数接受三个参数,第一个参数为要取的主字符串,第二个参数为字串的起始位置(从1开始计数),第三个参数为字串的长度。如:【selectsubstr(zxdate,1,10)AS日期,zxdatefromzx_file】取出zxdate字段日期的前十位。多个函数还可以嵌套使用。主流系统都提供了计算正弦函数值的函数SIN和计算绝对值的函数ABS,它们都接受一个数值类型的参数。
4、字符串的拼接、
SQL允许两个或者多个字段之间进行计算,字符串类型的字段也不例外。在不同的数据库系统下的字符串拼接是有很大差异的,因此这里我们将讲解主流数据库下的字符串拼接的差异。需要注意的是,在Java、C#等编程语言中字符串是用半角的双引号来包围的,但是在有的数据库系统的SQL语法中双引号有其他的含义(比如列的别名),而所有的数据库系统都支持用单引号包围的形式定义的字符串,所以建议读者使用以单引号包围的形式定义的字符串,而且本书也将使用这种方式。
5、计算字段的其他用途、第七节不从实体表中取的数据
联合结果集第八节联合结果集
数据的增第二章数据的增、删、改
第一节数据的插入
1、简单的INSERT语句、INSERTINTO语句用来向数据表中插入数据。如执行下面的语句就可以向T_Person表中插入一条数据:【INSERTINTOT_Person(FName,FAge,FRemark)VALUES('Tom',18,'USA')】。VALUES前边的括号中列出的是要设置字段的字段名,字段名之间用逗号隔开;VALUES后边的括号中列出的是要设置字段的值,各个值同样用逗号隔开。需要注意的是VALUES前列出的字段名和VALUES后边列出的字段由于FName和值是按顺序一一对应一一对应的,不能打乱它们之间的对应关系,而且要保证两边的条数是一致两边的条数是一致的。一一对应两边的条数是一致FRemark字段是字符串类型的,所以需要用单引号(半角字符)将值包围起来,而整数类型的FAge字段的值则不需要用单引号包围起来。INSERT语句中列的顺序列的顺序可以是任意的;INSET语句中列的顺序不会影响数据插入的结果。列的顺序
2、简化的INSERT语句、
INSERT语句中也并不需要我们指定表中的所有列。(没有指定的列值默认为空NULL)。如:【INSERTINTOT_Person(FAge,FName)VALUES(22,'LXF')】INSERT语句还有另一种用法,可以不用指定要插入的表列,这种情况下将按照定义表中字段顺序按照定义表中字段顺序来进行按照定义表中字段顺序插入,我们执行下面的SQL:【INSERTINTOT_PersonVALUES('luren1',23,'China')】。这里省略了VALUES前面的字段定义,VALUES后面的值列表中按照CREATETABLE语句中的顺序排列。这种省略字段列表的方法可以简化输入,不过我们不推荐这种用法,因为省略字段列表之后就无法很容易的弄清楚列表中各个值到底对应哪个字段了,非常容易导致程序出现BUG并且给程序的调试带来非常大的麻烦。
3、非空约束对数据插入的影响、
正如“非空约束”表达的意思,如果对一个字段添加了非空约束,那么我们是不能向这个字段中插入NULL值的。如果插入空值的话,数据库系统会报错。
4、主键对数据插入的影响、
主键是在同一张表中必须是唯一的,如果在进行数据插入的时候指定的主键与表中已有的数据重复的话则会导致违反主键约束的异常。
5、外键对数据插入的影响、
外键是指向另一个表中已有数据的约束,因此外键值必须是在目标表中存在的。如果插入的数据在目标表因此外键值必须是在目标表中存在的因此外键值必须是在目标表中存在的中不存在的话则会导致违反外键约束异常。
第二节数据的更新1、简单的数据更新、
UPDATE语句用来对数据表中的数据进行更新。下边的语句用来将表T_Person中所有人员的FREMARK字段值更新为“SuperMan”【UPDATET_PersonSETFRemark='SuperMan'】:。我们还可以在SET语句中定义多个列定义多个列,这样就可以实现多列同时更新了。多个列之间需要使用逗号分隔开。定义多个列
2、带WHERE子句的UPDATE语句、
要实现更新满足符合特定条件的行的需求功能只要使用WHERE子句就可以了,在WHERE语句中我们设定适当的过滤条件,这样UPDATE语句只会更新符合WHERE子句中过滤条件的行,而其他行的数设定适当的过滤条件其他行的数据则不被修改。【UPDATET_PersonSETFAge=12WHEREFNAME='Tom'】由于FNAME字据则不被修改如:】。段等于'Tom'的只有一行,所以仅有一行记录被更新,但是如果有多个符合条件的行的话将会有多行被更新。我们可以使用复杂的WHERE语句来满足更加复杂的需求,我们还可以使用OR、NOT等运算符实现、更加复杂的逻辑,甚至能够使用模糊查询、子查询等实现高级的数据过滤模糊查询、模糊查询子查询等实现高级的数据过滤,
3、非空约束对数据更新的影响、
正如“非空约束”表达的意思,如果对一个字段添加了非空约束,那么我们是不能将这个字段中的值更新为NULL的。如果更新为空值的话,数据库系统会报错。
4、主键对数据更新的影响、
主键是在同一张表中必须是唯一的,如果在进行数据更新的时候指定的主键与表中已有的数据重复的话则会导致违反主键约束的异常。
5、外键对数据更新的影响、
外键是指向另一个表中已有数据的约束,因此外键值必须是在目标表中存在的。如果更新后的数据在目标表中不存在的话则会导致违反外键约束异常
第三节数据的删除
数据库中的数据一般都有一定的生命周期,当数据不再需要的时候我们就要将其删除,执行DELETE语句就可以将数据从表中删除。不过需要注意的就是如果被删除的数据行是某个外键关联关系中的被引用数据的话,则进行删除的时候会失败,如果要删除成功则必须首先删除引用者才可以首先删除引用者才可以。首先删除引用者才可以
1、简单的数据删除、
删除数据的SQL语句非常简单,我们只要指定要删除的表只要指定要删除的表就可以了,比如我们要将T_Debt和T_Person只要指定要删除的表表中的数据删除,那么执行下面的SQL语句即可:DELETEFROMT_Debt;DELETEFROMT_Person】【。由于T_Debt表中FPerson字段是指向表T_Person的FName字段的外键,所以必须首先删除T_Debt表中的数据后才能删除T_Person中的数据。初学者往往容易把DROPTABLE语句和DELETE混淆,虽然二者名字中都有“删除”两个字,不过DELETE语句仅仅是删除表中的数据行而表的结构还存在语句仅仅是删除表中的数据行,而表的结构还存在而表的结构还存在;而DROPTABLE语句则不仅将表中的数据行全部删除,而且还将表的结构也删除。据行全部删除,而且还将表的结构也删除。
2、带WHERE子句的DELETE语句、
DELETE语句将表中的所有数据都删除了,如果我们只想删除我们指定的数据行删除我们指定的数据行怎么办呢?和UPDATE删除我们指定的数据行语句类似,DELETE语句也提供了WHERE语句进行数据的过滤,这样只有符合过滤条件的数据行才会被删除。我们要删除年龄大于20岁或者来自火星(Mars)的人员,因此使用带复合逻辑WHERE子句,如下:【DELETEFROMT_PersonWHEREFAge>20orFRemark='Mars'】。
第三章表的连接第四章子查询索引与约束第五章索引与约束第六章函数第七章数据表的创建与管理第八章主流数据库的SQL语法差异解决方案