第5章 数据操作
针对数据库中的数据操作包括数据查询、数据添加、数据修改和数据删除等操作。数据查询是指查询数据库中的数据信息,数据添加是指向数据库中添加数据,数据修改是指修改数据库中原有的数据信息,数据删除指的是删除数据库中的数据信息。本章将讲解一下与数据操作相关的一些内容。
5.1 查询语句
SQL语句的使用目的是与数据库进行通信,如果不能够对数据库中的数据进行操作和查询,那么存储其中的数据将毫无意义。在对数据库中的数据进行查询时,应该使用结构化查询语言(SQL)中的SELECT语句。查询(SELECT)语句是SQL语句中使用最频繁的语句之一,是SQL语句的核心。在有关SQL的语句查询中,几乎所有的SQL数据查询功能都是围绕着SELECT语句进行的。
5.1.1 查询语句的基本结构
SELECT语句由一系列灵活的子句组成,这些子句共同确定检索哪些数据。SELECT语句的完整语法较复杂,但其主要子句可归纳如下。
SELECT select_list
[ INTO new_table]
FROM table_source
[ WHERE search_condition]
[ GROUP BY group_by_expression]
[ HAVING search_condition]
[ ORDER BY order_expression [ ASC|DESC ] ]
必需的子句只有SELECT子句和FROM子句,其他的子句都是可选的。各子句具体含义如下:
- SELECT子句:指定由查询返回的列。
- INTO子句:将检索结果存储到新表或视图中。
- FROM子句:用于指定引用的列所在的表或视图。如果对象不止一个,那么它们之间必须用逗号分开。
- WHERE子句:指定用于限制返回的行的搜索条件。如果SELECT语句没有WHERE子句,DBMS假设目标表中的所有行都满足搜索条件。
- GROUP BY子句:指定用来放置输出行的组,并且如果SELECT子句中包含聚合函数,则计算每组的汇总值。
- HAVING子句:指定组或聚合的搜索条件。HAVING通常与GROUP BY子句一起使用。如果不使用GROUP
BY子句,HAVING的行为与WHERE子句一样。 - ORDER BY子句:指定结果集的排序。ASC关键字表示升序排列结果,DESC关键字表示降序排列结果。如果没有指定任何一个关键字,那么ASC就是默认的关键字。如果没有ORDER BY子句,DBMS将根据输入表中的数据来显示数据。
为了让DBMS显示表中的值,最简单的就是执行带有FROM子句的SELECT语句即可。而在实践中,几乎所有的SELECT语句都包括强制输出数据满足某种标准的WHERE子句;另外,许多SELECT语句涉及从多个表中选择列的问题。
当执行SELECT语句时,DBMS的执行步骤可表示如下:
(1)首先执行FROM子句,组装来自不同数据源的数据,即根据FROM子句中的一个或多个表创建工作表。如果在FROM子句中有两个或多个表,DBMS将执行CROSS JOIN运算对表进行交叉连接,作为工作表。
(2)如果有WHERE子句,实现基于指定的条件对记录行进行筛选,即DBMS将WHERE子句列出的搜索条件作用于第(1)步中生成的工作表。DBMS将保留那些满足搜索条件的行,删除那些不满足搜索条件的行。
(3)如果有GROUP BY子句,它将把数据划分为多个分组。DBMS将第(2)步生成的结果表中的行分成多个组,每个组中所有行的group_by_expression字段具有相同的值。接着,DBMS将每组减少到单行,而后将其添加到新的结果表中,用以代替第(1)步的工作表。
(4)如果有HAVING子句,它将筛选分组。DBMS将HAVING子句列出的搜索条件作用于第(3)步生成的“组合”表中的每一行。DBMS将保留那些满足搜索条件的行,删除那些不满足搜索条件的行。
(5)将SELECT子句作用于结果表。删除结果表中不包含在select_list中的列。如果SELECT子句包含DISTINCT关键字,DBMS将从结果中删除重复的行。
(6)如果有ORDER BY子句,则按指定的排序规则对结果进行排序。
(7)对于交互式的SELECT语句,在屏幕上显示结果,对于嵌入式SQL,使用游标将结果传递给宿主程序中。
以上就是SELECT语句的基本执行过程。对于初学者来讲,可能很难理解。之所以在这里就提出,是为了让读者对SELECT语句有一个整体的了解。下面就开始从简单的查询开始,详细讲解SELECT查询语句的具体使用。
5.1.2 SELECT…FROM的使用
在SQL数据库中,通常情况下每个表都包含若干列信息。用户在查询表中的记录时,大多数情况下只是关心表的一列或者几列的信息。这时,只需要使用SELECT语句的常规使用方式即可。
【语法说明】
SELECT…FROM语句使用的语法结构如下所示。
SELECT 列名1[,列名2,…列名n]
FROM 表名
SELECT关键词指明了要查询的表的列的名称,FROM关键词指明了要查询的列所在表的名字。
【上机实战】
查询图书信息表(T_BOOKINFO)中所有的数据信息,其实现的代码如下所示。
- SELECT * FROM T_BOOKINFO
代码执行后,其查询结果如图5.1所示。
图5.1 查询数据表中所有的数据信息
在SQL语言中,SQL关键词对大小写不敏感,所以对SELECT关键词来说,SELECT、select或者Select都是一样的。在SQL
Server中,其字段名称对大小写也不敏感。
如果要查询数据表中指定的列数据,可以通过下面的代码来实现。
SELECT B_ID,B_NAME,B_PUBLISH,B_VALUE
FROM T_BOOKINFO
上述代码实现的是,查询图书信息表(T_BOOKINFO)中的编号(B_ID)、图书名称(B_NAME)、出版社(B_PUBLISH)和价格(B_VALUE)列数据信息,语句执行后的查询结果如图5.2所示。
图5.2 查询数据表中指定列的数据信息
注意,在列出的最后一列的名字后面不能加逗号,否则会造成语法错误。
5.1.3 WHERE子句的使用
WHERE子句获取FROM子句返回的结果集,并应用WHERE子句中定义的搜索条件对结果集进行筛选,符合搜索条件的那些数据作为查询结果的一部分返回,不符合搜索条件的从结果中去除。
【语法说明】
WHERE子句的语法结构如下所示。
SELECT column
FROM table_name
WHERE column condition value
该语句中column用来表示列名称,tale_name表示数据表名称,condition表示查询条件,value表示查询的值。
【上机实战】
查询图书信息表(T_BOOKINFO)中出版社为“清华大学出版社”的图书信息,其实现的代码如下所示。
SELECT *
FROM T_BOOKINFO
WHERE B_PUBLISH='清华大学出版社'
代码执行以后,其查询结果如图5.3所示。
图5.3 查询图书信息表中出版社为“清华大学出版社”的图书信息
通过WHERE语句也可以查询数据表中某一指定范围的数据信息,下面的代码演示的是查询图书信息表(T_BOOKINFO)中的编号(B_ID)、图书名称(B_NAME)、出版社(B_PUBLISH)和价格(B_VALUE)列数据信息,并且查询图书价格在30与50之间的图书信息。
SELECT B_ID,B_NAME,B_PUBLISH,B_VALUE
FROM T_BOOKINFO
WHERE B_VALUE>=30 AND B_VALUE <=50
代码执行后,其查询结果如图5.4所示。
图5.4 查询指定范围的数据信息
5.1.4 使用DISTINCT语句去除重复结果信息
前面介绍的最基本的查询方式会返回从表格中搜索到的所有行的数据,而不管这些数据是否重复,这常常不是用户所希望看到的。使用DISTINCT关键字就能够从返回的结果数据集合中删除重复的行,使返回的结果更简洁。
【语法说明】
在SELECT子句中,通过指明DISTINCT关键字去除列中的重复信息。其语法如下所示。
SELECT DISTINCT column
FROM table_name_name
DISTINCT关键字去除的是SELECT子句查询的列的重复信息。如果SELECT子句查询的列为多列,那么只有这些列的信息同时重复的记录才被去除。
【上机实战】
查询图书信息表(T_BOOKINFO)中存在的所有图书出版社的名称,即查询B_PUBLISH列的数据,且去除重复的记录。
首先来看一下不使用DISTINCT关键字去除重复列中数据的情况,其实现的代码如下所示。
SELECT B_PUBLISH
FROM T_BOOKINFO
代码执行以后,其查询结果如图5.5所示。
图5.5 不使用DISTINCT关键字查询的数据信息
从上图可以看出,查询出的数据结构有很多重复行数据。使用DISTINCT语句去除B_PUBLISH列重复行数据的实现代码如下所示。
SELECT DISTINCT B_PUBLISH
FROM T_BOOKINFO
代码执行以后,其查询结果如图5.6所示
图5.6 使用DISTINCT关键字查询的数据信息
说明:DISTINCT的使用是要付出代价的。因为要去掉重复值,必须对结果集中的记录进行排序,使得相同的记录聚集在一起,只有按这种方法对记录进行分组,才能去掉重复值,而这一工作甚至比查询本身还费时间。
在使用DISTINCT关键字后,如果表中有多个为NULL的数据,服务器会把这些数据视为相等。
下面的代码演示的是查询图书信息表(T_BOOKINFO)中存在的所有图书的备注信息,即查询B_MARK列的数据,且去除重复的记录。
SELECT DISTINCT B_MARK
FROM T_BOOKINFO
代码执行以后,其运行结果如图5.7所示。
图5.7 去除重复值的B_MARK列数据
可见,所有的NULL值被视为相等的,且排序时在最前面。
5.1.5 GROUP BY子句的使用
在SQL中提供了分组查询的功能,在SELECT语句中使用GROUP BY子句可以实现对查询结果进行分类,从而满足用户不同的需求。
【语法说明】
GROUP子句的基本语法格式如下所示。
SELECT [ALL|DISTINCT] select_list
FROM table_list | view_list
[WHERE conditions]
[GROUP BY [ALL]group_list]
上述语句中group_list是指进行分组所依据的表达式,select_list表示查询列的集合,table_list | view_list表示的是数据表名或视图名,conditions表示的是查询条件。
【上机实战】
查询图书信息表(T_BOOKINFO)中的数据信息,并且将查询结果按照出版社进行分组。
首先通过下面的SELECT语句查询图书信息表(T_BOOKINFO)中中的数据信息。
SELECT *
FROM T_BOOKINFO
执行语句后的查询结果如图5.8所示。
图5.8 查询图书信息表(T_BOOKINFO)中的数据信息
从图中可以看出查询的结果并没有进行分组,下面将演示如何按照出版社(B_PUBLISH)字段进行分组,并显示各个出版社出版图书的平均单价。
SELECT B_PUBLISH,AVG(B_VALUE)
FROM T_BOOKINFO
GROUP BY B_PUBLISH
代码执行后,其查询结果如图5.9所示。
图5.9 将查询结果进行分组
从图中可以看出,查询结果按照出版社进行了分组,并且统计出了每个出版社出版图书的平均单价。
上面的示例演示了如何按照单列字段进行分组,也可以按照多列字段进行分组。
下面的代码演示的是在图书信息表(T_BOOKINFO)中,按照出版社名称(B_PUBLISH)字段和作者(B_AUTHOR)字段同时进行分组,并显示图书价格的和。
SELECT B_PUBLISH,B_AUTHOR,SUM(B_VALUE)
FROM T_BOOKINFO
GROUP BY B_PUBLISH,B_AUTHOR
代码执行后的查询结果如图5.10所示。
图5.10 将查询结果按照多字段进行分组
从上面的查询结果可以看出,查询的结果集首先按照出版社(B_PUBLISH)字段进行分组,然后在该分组的基础上再按照作者(B_AUTHOR)字段进行分组。
在SQL中,当GROUP BY子句中用于分组的列中含有NULL时,可以将所有的NULL分在同一组中进行处理。
下面的代码演示的是在图书信息表(T_BOOKINFO)中,按照出版社名称(B_PUBLISH)字段和图书备注(B_MARK)字段同时进行分组,并显示分组后的图书本数信息。
SELECT B_PUBLISH,B_MARK,COUNT(*) AS 图书本数
FROM T_BOOKINFO
GROUP BY B_PUBLISH,B_MARK
代码执行后,其执行结果如图5.11所示。
图5.11 GROUP BY子句中的NULL处理
可以将由GROUP BY分组统计出来的数据进行排序。下面分别通过示例来讲解如何实现将分组统计出来的数据按照价格信息进行升序排序和降序排序。
下面的代码演示的是在图书信息表(T_BOOKINFO)中,按照出版社名称(B_PUBLISH)字段和作者(B_AUTHOR)字段同时进行分组,并显示图书价格的和。分组完成之后按照图书价格和进行升序排序。
SELECT B_PUBLISH,B_AUTHOR,SUM(B_VALUE)
FROM T_BOOKINFO
GROUP BY B_PUBLISH,B_AUTHOR
ORDER BY SUM(B_VALUE) ASC
代码执行后,其查询结果如图5.12所示。
图5.12 将分组查询结果进行升序排序
注意:在执行升序排序操作时,ASC关键字可以省略不写。
下面的代码演示的是在图书信息表(T_BOOKINFO)中,按照出版社名称(B_PUBLISH)字段和作者(B_AUTHOR)字段同时进行分组,并显示图书价格的和。分组完成之后按照图书价格和进行降序排序。
SELECT B_PUBLISH,B_AUTHOR,SUM(B_VALUE)
FROM T_BOOKINFO
GROUP BY B_PUBLISH,B_AUTHOR
ORDER BY SUM(B_VALUE) DESC
代码执行后,其查询结果如图5.13所示。
图5.13 将分组查询结果进行降序排序
5.1.6 HAVING子句的使用
GROUP BY子句进行分组之后,如果想筛选某些符合条件的分组,可以使用HAVING子句。
【上机实战】
在图书信息表(T_BOOKINFO)中,按照出版社名称(B_PUBLISH)字段和作者(B_AUTHOR)字段同时进行分组,并显示图书价格的和。分组完成之后按照图书价格和进行升序排序,同时只显示图书价格和大于60的数据信息。
SELECT B_PUBLISH,B_AUTHOR,SUM(B_VALUE)
FROM T_BOOKINFO
GROUP BY B_PUBLISH,B_AUTHOR
HAVING SUM(B_VALUE)>60
ORDER BY SUM(B_VALUE)
代码执行后,其执行结果如图5.14所示。
图5.14 HAVING子句的应用
5.1.7 BETWEEN的使用
在WHERE子句中,使用BETWEEN关键字可以更方便地限制查询数据的范围。当然,还可以使用NOT BETWEEN关键字查询限定数据范围之外的记录。
【语法说明】
BETWEEN运算符的语法结构如下所示。
SELECT column
FROM table_name
WHERE column BETWEEN value1 AND value2
该语句中column用来表示列的名称,tale_name表示数据表的名称,value1与value2分别表示查询区间的起始值与末尾值。
【上机实战】
查询图书信息表(T_BOOKINFO)中的图书编号(B_ID)、图书名称(B_NAME)、出版社名称(B_PUBLISH)、出版日期(B_DATE)、作者(B_AUTHOR)和图书价格(B_VALUE)字段,并且只显示图书价格在30与60之间的图书信息。
SELECT B_ID,B_NAME,B_PUBLISH,B_DATE,B_AUTHOR,B_VALUE
FROM T_BOOKINFO
WHERE B_VALUE BETWEEN 30 AND 60
代码执行以后,其执行结果如图5.15所示。
图5.15 查询图书价格在30~60之间的图书信息
5.1.8 模糊查询的实现
模糊查询指的是可以用通用的、笼统的、模糊的条件代替具体的查询条件,这在不确定查询内容的具体细节时用处很大,另外,模糊查询提取的数据不一定准确,这也是其不足之处。通过下面将要讲解的实例,读者可以清楚地理解模糊查询的作用。
1.使用LIKE运算符进行查询
LIKE运算符用于匹配字符串或字符串子串。如果匹配的数据类型是整数、小数、货币等类型,则不能使用LIKE运算符。因此例如身份证号码等数字若定义为CHAR类型,则可以使用LIKE子句进行匹配;若定义为INT数据类型,则不能使用LIKE子句进行匹配。
LIKE运算符需要和通配符一起使用。SQL中的通配符如表5.1所示。
表5.1 SQL中的通配符
通配符名称 说明 示例
‘_’ 表示一个字符 Select sName From employee Where sName='李_'
% 表示任意长度的字符 Select sName From employee Where sName='李_%'
[] 表示括号内所指定范围内的一个字符 Select sName From employee Where sName='李[1-2]'
[^] 不在括号中指定范围内的任意一个字符 Select sName From employee Where sName='李[^1-2]'
说明:只有CHAR、VARCHAR和TEXT数据类型的数据才能使用LIKE运算符和通配符。
在不使用通配符,直接使用LIKE运算符的条件下,不可以实现模糊查询。
【上机实战】
查询图书信息表(T_BOOKINFO)中的图书编号(B_ID)、图书名称(B_NAME)、出版社名称(B_PUBLISH)、出版日期(B_DATE)、作者(B_AUTHOR)和图书价格(B_VALUE)字段,并且显示作者为“李俊民”的图书信息。
SELECT B_ID,B_NAME,B_PUBLISH,B_DATE,B_AUTHOR,B_VALUE
FROM T_BOOKINFO
WHERE B_AUTHOR LIKE '李俊民'
代码执行以后,执行的结果如图5.16所示。
图5.16 使用LIKE运算符进行查询
从图中可以看出,查询执行以后,将查询出图书信息表(T_BOOKINFO)中所有作者是“李俊民”的图书信息。实际上,这里LIKE运算符的作用与等号(=)运算符的作用相同,也就是说,可以用等号(=)运算符替换LIKE运算符。
也可以使用NOT LIKE运算符来查询数据。
下面的代码演示的是,查询图书信息表(T_BOOKINFO)中的图书编号(B_ID)、图书名称(B_NAME)、出版社名称(B_PUBLISH)、出版日期(B_DATE)、作者(B_AUTHOR)和图书价格(B_VALUE)字段,并且显示作者不是 “李俊民”的图书信息。
SELECT B_ID,B_NAME,B_PUBLISH,B_DATE,B_AUTHOR,B_VALUE
FROM T_BOOKINFO
WHERE B_AUTHOR NOT LIKE '李俊民'
代码执行以后,其执行结果如图5.17所示。
图5.17 使用NOT LIKE运算符进行查询
从图中可以看出,查询执行以后,将查询出图书信息表(T_BOOKINFO)中作者除了“李俊民”以外所有的图书信息。这里NOT LIKE运算符的作用与不等号(<>)运算符的作用相同,即可以用不等号(<>)运算符替换NOT LIKE运算符。
2.使用“%”通配符进行查询
“%”通配符在SQL中经常会被用到,其表示对任意字符的匹配。“%”通配符通常情况下有3种用法,即在开头或结尾匹配、在中间匹配和在两端匹配。
(1)开头或结尾匹配
将“%”通配符放在与其匹配字符的前面或后面,可以查询出与其类似的数据信息。
【上机实战】
查询图书信息表(T_BOOKINFO)中所有图书名称中包含 “SQL”字符,并且在该字符前面还有其他字符的图书信息。为了便于读者进行学习比较,这里将查询图书信息表(T_BOOKINFO)中的所有记录显示出来。
SELECT *
FROM T_BOOKINFO
语句执行结果如图5.18所示。
图5.18 显示数据表中所有的记录信息
使用“_”通配符查询图书信息的代码如下所示。
SELECT *
FROM T_BOOKINFO
WHERE B_NAME LIKE '%提高'
代码执行以后,结果如图5.19所示。
图5.19 将“%”通配符放在与其一起作为匹配字符的后面
“%”通配符也可以放在与其一起作为匹配字符的前面。
下面的代码演示的是,查询图书信息表(T_BOOKINFO)中所有图书名称中包含 “SQL”字符,并且在该字符后面还有其他字符的图书信息。
SELECT *
FROM T_BOOKINFO
WHERE B_NAME LIKE 'SQL%'
代码执行以后,结果如图5.20所示。
图5.20 将“%”通配符放在与其一起作为匹配字符的前面
(2)中间匹配
可以将“%”通配符放在与其匹配字符的两端。
下面的代码演示的是,查询图书信息表(T_BOOKINFO)中所有图书出版社中包含 “大学”字符的图书信息。
SELECT *
FROM T_BOOKINFO
WHERE B_PUBLISH LIKE '%大学%'
代码执行以后,结果如图5.21所示。
图5.21 将“%”通配符放在与其一起作为匹配字符的两端
3.两端匹配
可以将与“%”通配符一起相匹配的匹配字符放在“%”通配符的两端,即将通配符放在中间。
下面的代码演示的是,查询图书信息表(T_BOOKINFO)中所有图书名称以 “SQL”字符开头并且以“语言”字符结尾的图书信息。
SELECT *
FROM T_BOOKINFO
WHERE B_NAME LIKE 'SQL%语言'
代码执行以后,结果如图5.22所示。
图5.22 将“%”通配符放在与其一起作为匹配字符的中间
3.使用“”通配符通配符进行查询
“”通配符表示与任意一个字符相匹配。当然,如果表示要与两个字符相匹配,需要使用两个“”通配符,即写成“__”。用户在查询字符串的个数时,确定不了其中的一个或几个字符的确切值时,需要使用“”通配符。
【上机实战】
查询图书信息表(T_BOOKINFO)中所有图书名称以“SQL”开头的图书信息,使用“_”通配符查询图书信息的代码如下所示。
SELECT *
FROM T_BOOKINFO
WHERE B_NAME LIKE '%SQL_%'
代码执行以后,执行的结果如图5.23所示。
图5.23 使用“”通配符查询数据信息
“”通配符也可以放在与其一起作为匹配字符的前面。
下面的代码演示的是,查询图书信息表(T_BOOKINFO)中所有图书名称以“提高”结尾的图书信息。
SELECT *
FROM T_BOOKINFO
WHERE B_NAME LIKE '%_提高%'
代码执行以后,执行的结果如图5.24所示。
图5.24 使用“”通配符查询数据信息
“”通配符也可以放在与其一起作为匹配字符的中间,即将通配符放在中间。
下面的代码演示的是,查询图书信息表(T_BOOKINFO)中所有图书名称以“SQL”开头、以“语言”结尾的图书信息。
SELECT *
FROM T_BOOKINFO
WHERE B_NAME LIKE '%SQL_____语言%'
说明:查询条件的开头字符和结尾字符的中间空几个字符,中间就放置几个“_”运算符。
代码执行以后,结果如图5.25所示。
图5.25 将“”通配符放在与其一起作为匹配字符的中间
如果用户只知道要查询的字符串个数,而不确定其中的任何一个字符时,可以使用“”通配符查询数据信息。
5.2 数据的增加—INSERT
在SQL语言中,使用INSERT命令将新的数据行追加到表中。使用INSERT命令可以向表中整行插入数据,也可以对部分列进行插入。在SQL Server中,使用INSERT命令,一次只能向表中添加一行记录。
5.2.1 把数据直接插入到表中
在通过SQL语句创建一个新表后,新表中不包含有任何的数据。可以通过INSERT语句向数据表中添加数据。
【语法说明】
在SQL中,INSERT命令的基本使用语法如下。
INSERT
[INTO]
table_or_view_name
[ ( column_list ) ]
VALUES ({DEFAULT | NULL | expression } [ ,...n ])
其中,INTO为一个可选的关键字,可以将它用在INSERT和目标表之间;table_or-view_name为要添加数据的表或视图的名称,若为视图,则必须是可更新的视图;(column_list)为要在其中插入数据的一列或多列的列表。必须用括号将column_list括起来,并且用逗号进行分隔。如果表名table_name后面没有接指定列(column_list),则认为是整行插入;VALUES引入要插入的数据值的列表。对于column_list(如果已指定)或表中的每个列,都必须有一个数据值,必须用圆括号将值列表括起来。
说明:如果VALUES列表中的各值与表中各列的顺序不相同,或者未包含表中各列的值,则必须使用column_list显式指定存储每个传入值的列。
使用INSERT命令向表中插入行时,应遵循下面的规则:
- 如果将一个空字符串(’ ')加载到varchar或text数据类型的列,则默认操作是加载一个零长度的字符串。
- 插入的数据类型应与被加入字段的数据类型相同,且必须满足该列的约束(如空值约束、字段长度等)。如果INSERT语句违反约束或规则,或者包含与列的数据类型不兼容的值,则该语句将失败,并且数据库引擎显示错误消息。
在VALUES中,列出的数据位置必须与字段的排列位置相对应。也就是说,第一个值插入第一列,第二个值插入第二列,依此类推。
【上机实战】
向图书信息表(T_BOOKINFO)中的图书编号(B_ID)、图书名称(B_NAME)、出版社名称(B_PUBLISH)、作者(B_AUTHOR)和备注(B_MARK)字段中插入数据信息,其实现的代码如下所示。
INSERT INTO T_BOOKINFO(B_ID,B_NAME,B_PUBLISH,B_AUTHOR,B_MARK)
VALUES('1013','ASP.NET完全手册','清华大学出版社','赵刚','无')
代码执行以后,数据信息被插入到图书信息表(T_BOOKINFO)中,查询数据表中的数据结果如图5.26所示。
图5.26 向数据表中插入数据
从图中可以看出,图书编号(B_ID)为1012的图书信息被添加到数据表当中,但是,添加数据信息中的B_DATE字段B_VALUE字段中的值为NULL,这是因为在INSERT语句中没有指定要向这两个字段中添加数据信息。
在向数据表中添加数据时,应该注意添加数据的数据类型与数据表字段中的数据类型是否一致,如果不一致DBMS就会提示错误信息,如通过下面的代码向T_BOOKINFO数据表中插入数据。
INSERT INTO T_BOOKINFO(B_ID,B_NAME,B_PUBLISH,B_AUTHOR,B_MARK)
VALUES('1013','ASP.NET完全手册','清华大学出版社',赵刚,'无')
代码执行后,将弹出如图5.26所示的错误提示信息。这是因为图书信息表(T_BOOKINFO)中的作者(B_AUTHOR)字段的数据类型是字符型,而由于与其对应添加的数据“赵刚”没有带引号,则系统会认为该数据信息为整形数据,所以在执行插入数据操作时DBMS弹出了错误提示信息,如图5.27所示。因此,在向数据表中添加数据时,一定要使添加数据的数据类型与数据表字段中的数据类型保持一致。
图5.27 由于数据类型错误而弹出的错误提示信息
如果向数据表中某个字段中添加的数据长度大于数据表字段定义的长度,DBMS也会弹出错误信息,如下面的代码所示。
INSERT INTO T_BOOKINFO(B_ID,B_NAME,B_PUBLISH,B_AUTHOR,B_MARK)
VALUES('10135678910123','ASP.NET完全手册','清华大学出版社','赵刚','无')
代码执行之后,DBMS将提示如图5.28所示的错误提示信息。查看数据表,发现数据没有添加成功。这是由于图书信息表(T_BOOKINFO)中的图书编号(B_ID)字段是为10个字符长度的字符型数据字段,而添加与其对应的数据信息的长度远远超过了10个字符的长度,因此,DBMS会阻止向数据表中添加象这样不符合规范的数据信息。
图5.28 插入字符数超范围的提示信息
如果VALUES后面指定的值与数据表中字段的数目不相同,例如插入数值数大于字段数,则DBMS也会弹出“值过多”的错误提示信息,如下面的代码所示。
INSERT INTO T_BOOKINFO(B_ID,B_NAME,B_PUBLISH,B_AUTHOR,B_MARK)
VALUES('1013','ASP.NET完全手册','清华大学出版社','赵刚',36,'无')
代码执行以后,DBMS弹出了如图5.29所示的错误提示信息。这是因为插入的数值数(多了一个“36”的数值)大于字段数的缘故。
图5.29 提示“值过多”的错误提示信息
如果插入数值数小于字段数,则DBMS也会弹出“值过多”的错误提示信息,如下面的代码所示。
INSERT INTO T_BOOKINFO(B_ID,B_NAME,B_PUBLISH,B_AUTHOR,B_VALUE,B_MARK)
VALUES('1013','ASP.NET完全手册','清华大学出版社','赵刚','无')
代码执行以后,DBMS弹出了如图5.30所示的错误提示信息。这是因为插入的字段数(多了一个“B_VALUE”字段)大于插入数值数的缘故。
图5.30 提示“没有足够的值”的错误提示信息
5.2.2 向数据表中添加多行数据
前面讲解都是如何使用INSERT语句向数据表中插入单条数据。如果需要向数据表中插入大量的数据,那么使用向数据表中插入单条数据的方法,在效率上会受到很大的限制。可以通过使用INSERT…VALUES语句,向数据表中批量地插入数据。
【语法说明】
使用INSERT…VALUES语句向数据表中插入多行数据的语法结构如下所示。
INSERT INTO table_name
[(column1,column2,…columnN)]
VALUES(value11,value12,…value1N),
(value21,value22,…value2N),
…
(valueN1,valueN2,…valueNN)
代码中的table_name表示要插入数据的数据表名称。VALUES关键词后面的值表示批量插入的数值,其插入的每一行记录都通过括号与逗号分隔开。
【上机实战】
使用INSERT…VALUES语句同时向图书信息表(T_BOOKINFO)中插入3条记录信息,并将插入数据后的数据表中的记录信息显示出来,其实现的代码如下所示。
INSERT INTO T_BOOKINFO(B_ID,B_NAME,B_PUBLISH,B_AUTHOR,B_MARK)
VALUES('1014','ASP.NET快速入门','清华大学出版社','李刚','无'),
VALUES('1015','ASP.NET技术实战','清华大学出版社','赵刚','无'),
VALUES('1016','ASP.NET技术宝典','清华大学出版社','王红','无')
代码执行以后,其执行结果如图5.31所示。
图5.31 向数据表中同时插入多行数据信息
5.2.3 从其他表中添加数据
通过使用INSERT INTO…SELECT语句,可以从一个数据表中读取数据,并且将读取的数据插入另一个数据表中当中。
【语法说明】
INSERT INTO…SELECT语句的语法结构如下所示。
INSERT INTO table_name1(column1,column2,…,columnN)
SELECT column1,column2,…,columnN
FROM table_name2
WHERE condition
从代码中可以看出,该语句是将查询的结果插入到数据表当中。在使用上述语句时,应该遵循以下几点准则。
- SELECT语句不能从正在被插入的表中选择数据,即table name与tablename2是同一个表。
- SELECT语句返回的列的数目必须等于INSERT INTO语句中列的数目。
- SELECT语句返回的列的数据类型必须与INSERT INTO语句中列的数据类型相同。
使用SELECT语句插入数据的一个重要用途是备份表,即备份将要删除、修改或新插入数据的表。下面通过几个示例来具体讲解使用SELECT语句插入数据的方法。
【上机实战】
新建一个数据表T_B_Infos,并且将图书信息表(T_BOOKINFO)中的图书编号(B_ID)、图书名称(B_NAME)、图书出版社(B_PUBLISH)和作者(B_AUTHOR)信息,插入到新创建的T_B_Infos数据表当中,其实现的代码如下所示。
CREATE TABLE T_B_Infos
(
tNo varchar(10) NOT NULL,
tName varchar(30),
tpublish varchar(20),
tauthor varchar(10)
)
INSERT INTO T_B_Infos(tNo,tName,tpublish,tauthor)
SELECT B_ID,B_NAME,B_PUBLISH,B_AUTHOR
FROM T_BOOKINFO
代码执行以后,T_B_Infos数据表被创建,并且将图书信息表(T_BOOKINFO)中的数据信息添加到T_B_Infos数据表当中。通过下面的代码查看T_B_Infos数据表中的数据信息。
SELECT *
FROM T_B_Infos
代码执行以后,其执行结果如图5.32所示。
图5.32 从一个数据表中向另一个数据表中插入的数据信息
可以从现有的数据表中查询符合条件的数据插入到另一个数据表当中。
下面的代码是从图书信息表(T_BOOKINFO)中查询出版社(B_PUBLISH)为“远方出版社”的图书编号(B_ID)、图书名称(B_NAME)、图书出版社(B_PUBLISH)和作者(B_AUTHOR)信息,并且将查询出符合条件的信息添加到T_B_Infos数据表当中。为了便于为了读者进行分析比较,现将T_BOOKINFO数据表和T_B_Infos数据表中的数据信息显示出来。
显示T_BOOKINFO数据表中的数据信息。
SELECT *
FROM T_BOOKINFO
显示T_B_Infos数据表中的数据信息。
SELECT *
FROM T_B_Infos
上述代码执行以后,运行结果分别如图5.33与图5.34所示。
图5.33 T_BOOKINFO数据表中的数据信息
图5.34 T_B_Infos数据表中得数据信息
使用INSERT INTO…SELECT语句将T_BOOKINFO数据表中的数据信息插入到T_B_Infos数据表当中,其实现的代码如下所示。
INSERT INTO T_B_Infos(tNo,tName,tpublish,tauthor)
SELECT B_ID,B_NAME,B_PUBLISH,B_AUTHOR
FROM T_BOOKINFO
WHERE B_PUBLISH='远方出版社'
代码执行以后,查询T_B_Infos数据表中的数据结果如图5.35所示。
图5.35 新添加数据之后T_B_Infos数据表中的数据信息
5.2.4 插入NULL值
NULL是指即不为零也不为空格的值,其实际上是记录某一列中根本不存在数据。如果数据表中的字段被设置为非空(NOT NULL),则在向数据表中添加数据时,该字段中不允许添加NULL,也就是说必须添加一个值,否则DBMS就会弹出错误提示信息。
【上机实战】
向图书信息表(T_BOOKINFO)中添加整行数据,并且保证出版日期(B_DATE)字段、图书价格(B_VALUE)字段和作者(B_AUTHOR)字段中添加的数据是空值(NULL),同时将添加后的数据显示出来。
INSERT INTO T_BOOKINFO
VALUES('1012','vb200例','机械工业出版社',NULL,NULL,NULL,'无')
代码执行以后,T_BOOKINFO数据表中的数据信息如图5.36所示。
图5.36 T_BOOKINFO数据表中的数据信息
从图中可以看出,新添加的图书编号为1012的图书信息中的出版日期(B_DATE)字段、图书价格(B_VALUE)字段和作者(B_AUTHOR)字段字段中的值都为NULL。实际上,NULL也是一个值,只不过是空值而以。上述代码的结果也可以使用下面的代码来实现。
INSERT INTO T_BOOKINFO(B_ID,B_NAME,B_PUBLISH,B_MARK)
VALUES('1012','vb200例','机械工业出版社','无')
代码执行以后,其结果与图5.35所示的结果相同。这说明,通过指定字段向数据表中添加数据时,数据添加完成以后,数据表中没有指定的字段中的数值都为NULL值。
如果数据表中的某个字段设置为不允许添加空记录信息,则如果在添加数据时指定向该字段中添加NULL时,DBMS就会提示错误信息。如图书信息表(T_BOOKINFO)中的作者名称(B_AUTHOR)字段被设置为不允许添加空记录信息,然而在添加数据时确指定该字段添加的值为NULL,如下面的代码所示。
INSERT INTO T_BOOKINFO
VALUES('1012','vb200例','机械工业出版社',NULL,NULL,NULL,'无')
语句执行以后,DBMS提示如图5.37所示的提示信息。出错的原因是因为数据表中的作者名称(B_AUTHOR)字段被定义为不允许添加空记录(NOT NULL),因此,在添加数据时,如果作者名称(B_AUTHOR)字段对应的值为NULL,则违背了表对作者名称(B_AUTHOR)字段的非空约束,因此,DBMS会提示错误信息。
图5.37 向非空约束字段中插入空值弹出的错误提示信息
5.3 数据的修改—UPDATE
在SQL语言中,可以使用UPDATE命令更改表或视图中的现有数据。UPDATE语句既可以一次修改一条记录,也可以一次修改多条记录,甚至可以一次修改表中的全部数据行。
5.3.1 更新某一列的数据
使用UPDATE语句可以更新数据表中的数据信息。
【语法说明】
在SQL中,UPDATE命令的基本使用语法如下。
UPDATE <table_or_view_name>
SET column_name = {expression | DEFAULT | NULL} [ ,...n ]
语句中得各项参数如下所示。
- table_or-view_name为要更新行的表或视图的名称,且引用的视图必须可更新,并且只在该视图的FROM子句中引用一个基表。如果该表不在当前服务器或数据库中,或不为当前用户所有,这个名称可用链接服务器、数据库和所有者名称来限定。
- column_name为要更改数据的列,column_name必须已存在于table_or-view_name中。
如果对行的更新违反了某个约束或规则,或者违反了对列的 NULL设置,或者新值是不兼容的数据类型,则取消该语句,返回错误并且不更新任何记录。
当UPDATE语句在表达式求值过程中遇到算术错误(溢出、被零除)时,则不进行更新。批处理的剩余部分不再执行,并且返回错误消息。
【上机实战】
将图书信息表(T_BOOKINFO)中的备注(B_MARK)字段中的数据信息全部修改为“无”
UPDATE T_BOOKINFO
SET B_MARK='无'
代码执行以后,T_BOOKINFO数据表中的备注(B_MARK)字段中的数据信息被修改,修改完成之后,T_BOOKINFO数据表中的数据信息如图5.38所示。
图5.38 修改T_BOOKINFO数据表中B_MARK字段中的数据信息
5.3.2 按条件更新数据
前面讲解了更新数据表中所有行数据的实现方法,本节中再讲解一下按照条件更新数据的实现方法。
【语法说明】
在SQL中,UPDATE命令的基本使用语法如下。
UPDATE <table_or_view_name>
SET column_name = {expression | DEFAULT | NULL} [ ,...n ]
WHERE <search_condition>
语句中得各项参数如下所示。
- table_or-view_name为要更新行的表或视图的名称,且引用的视图必须可更新,并且只在该视图的FROM子句中引用一个基表。如果该表不在当前服务器或数据库中,或不为当前用户所有,这个名称可用链接服务器、数据库和所有者名称来限定。
- column_name为要更改数据的列,column_name必须已存在于table_or-view_name中。
- search_condition为要更新的行指定需满足的条件。
【上机实战】
将图书信息表(T_BOOKINFO)中“清华大学出版社”出版图书的价格在原来的基础上,再加10元,为了便于比较,现将修改数据前T_BOOKINFO数据表中的数据显示出来。
SELECT *
FROM T_BOOKINFO
代码执行以后,其查询结果如图5.39所示。
图5.39 修改数据之前T_BOOKINFO数据表中的数据信息
将图书信息表(T_BOOKINFO)中“清华大学出版社”出版图书的价格在原来的基础上,再加10元,其实现的代码如下所示。
UPDATE T_BOOKINFO
SET B_VALUE=B_VALUE + 10
WHERE B_PUBLISH='清华大学出版社'
代码执行以后,数据信息被修改,修改之后T_BOOKINFO数据表中数据信息如图5.40所示。
图5.40 修改数据之后T_BOOKINFO数据表中的数据信息
5.3.3 更改数据字段中的NULL值
在通过UPDATE更改数据字段中的数据时,有可能被更改的数据字段中的值为NULL。
【上机实战】
将T_B_INFOS数据表中出版社为空的出版社信息修改为“人民邮电出版社”,为了便于比较,现将修改数据前T_B_INFOS数据表中的数据显示出来。
SELECT *
FROM T_B_INFOS
代码执行以后,运行结果如图5.41所示。
图5.41 修改之前T_B_INFOS中的数据信息
将T_B_INFOS数据表中出版社为空的出版社信息修改为“人民邮电出版社”,其实现的代码如下所示。
UPDATE T_B_INFOS
SET TPUBLISH='人民邮电出版社'
WHERE TPUBLISH IS NULL
代码执行以后,查询T_B_INFOS数据表中的数据信息。
SELECT *
FROM T_B_INFOS
代码执行以后,运行结果如图5.42所示。
图5.42 修改之后T_B_INFOS中的数据信息
5.3.4 通过视图更新数据
在使用UPDATE语句时,可以通过视图更新数据表中的数据。视图其实是一张虚拟的表,所以对视图的更新实际上是对视图底层数据表的更新。
【上机实战】
对图书信息表(T_BOOKINFO)创建视图,用于显示图书编号(B_ID)、图书名称(B_NAME)、出版社名称(B_PUBLISH)、作者(B_AUTHOR)和备注(B_MARK)字段中的数据信息。并且通过所创建的视图将对图书信息表(T_BOOKINFO)中出版社为“清华大学出版社”的图书备注信息更改为“清华”。首先将对图书信息表(T_BOOKINFO)中的数据信息显示出来。
SELECT * FROM T_BOOKINFO
代码运行以后,如图5.43所示。
图5.43 修改之前T_BOOKINFO数据表中的数据信息
对T_BOOKINFO数据表创建视图,具体代码如下所示。
CREATE VIEW View_B_INOFS
AS
SELECT B_ID,B_NAME,B_PUBLISH,B_AUTHOR,B_MARK
FROM T_BOOKINFO
通过视图View_B_INOFS更改图书信息表(T_BOOKINFO)中的数据信息,实现代码如下所示。
UPDATE View_B_INOFS
SET B_MARK='清华'
WHERE B_PUBLISH='清华大学出版社'
代码执行以后,T_BOOKINFO数据表中的数据信息被修改。通过下面的代码再次查询数据表中的数据信息。
SELECT *
FROM T_BOOKINFO
代码执行以后,执行结果如图5.44所示。
图5.44 修改之后T_BOOKINFO数据表中的数据信息
5.4 数据的删除—DELETE
数据表中的数据如果不在需要,可以将其删除,以便节省DBMS的存储空间。在SQL中,使用DELETE语句删除数据表中的数据信息。
5.4.1 按条件删除数据
在SQL中,使用DELETE命令可以删除数据表中指定条件下的数据信息。
【语法说明】
使用DELETE命令删除数据表中指定条件下数据信息的语法结构如下所示。
DELETE
[FROM] table_or_view_name
WHERE search_condition
语句中的search_condition指的是删除数据信息的条件。
【上机实战】
使用DELETE语句删除T_B_INFOS数据表中作者是“李娜”的图书信息,为了便于比较,现将T_B_INFOS数据表中的数据信息显示出来。
SELECT *
FROM T_B_INFOS
代码执行以后,T_B_INFOS数据表中的数据信息如图5.45所示。
图5.45 删除数据之前T_B_INFOS数据表中的数据信息
使用DELETE语句删除T_B_INFOS数据表中作者是“李娜”的图书信息,其实现的代码如下所示。
DELETE
FROM T_B_INFOS
WHERE TAUTHOR='李娜'
代码执行以后,符合条件的数据信息被删除,再次查询T_B_INFOS数据表中的数据信息如图5.46所示。
图5.46 删除数据之后T_B_INFOS数据表中的数据信息
从上图中可以看出,T_B_INFOS数据表中作者是“李娜”的图书信息已经被删除。
使用DELETE语句还可以删除数据表中条件为NULL的数据信息。下面的代码演示的是如何删除T_B_INFOS数据表中作者为空的图书信息,其实现的代码如下所示。
DELETE
FROM T_B_INFOS
WHERE TAUTHOR IS NULL
代码执行以后,T_B_INFOS数据表中作者为空的图书信息被删除,再次查询T_B_INFOS数据表中的数据信息如图5.47所示。
图5.47 删除T_B_INFOS数据表中作者为空的图书信息
5.4.2 通过视图删除表数据
通过视图也可以删除数据表中的行数据信息。
【语法说明】
使用DELETE语句通过视图删除其基表中数据信息的语法结构如下所示。
DELETE FROM View_name
WHERE condition
其中,View_name指的是视图的名称,condition指的是删除数据的条件。
【上机实战】
通过视图View_B_INOFS删除图书信息表(T_BOOKINFO)中所有图书备注信息为“清华”的图书信息,为了便于比较,现将T_BOOKINFO数据表中的数据信息显示出来。
SELECT *
FROM T_BOOKINFO
代码执行以后,执行结果如图5.48所示。
图5.48 删除数据之前T_BOOKINFO数据表中的数据信息
通过视图View_B_INOFS删除图书信息表(T_BOOKINFO)中所有图书备注信息为“清华”的图书信息,其实现的代码如下所示。
DELETE
FROM View_B_INOFS
WHERE B_MARK='清华'
代码执行以后,图书信息表(T_BOOKINFO)中所有图书备注信息为“清华”的图书信息被删除。通过下面的代码再次查询数据表中的数据信息。
SELECT *
FROM T_BOOKINFO
代码执行以后,执行结果如图5.49所示。
图5.49 通过视图删除数据后T_BOOKINFO数据表中的数据信息
5.4.3 删除全部数据
在SQL中,使用DELETE命令还可以删除数据表中全部的数据信息。
【语法说明】
DELETE命令删除数据表中全部数据的语法结构如下所示。
DELETE
[FROM] table_or_view_name
其中,FROM为可选的关键字,可用在DELETE关键字与目标table_or_view_name之间。
使用DELETE语句时,应注意以下几点:
- DELETE语句不能删除一个单个字段的值,它只能删除整行数据。要删除单个字段的值,可以使用上节介绍的UPDATE语句,将其更新为NULL。
- 使用DELETE语句仅能删除记录即表中的数据,不能删除表本身。要删除表,需要使用前面介绍的DROP TABLE语句。
- 同INSERT和UPDATA语句一样,从一个表中删除记录将引起其他表的参照完整性问题。这是一个潜在问题,需要时刻注意。
【上机实战】
使用DELETE语句删除T_B_INFOS数据表中所有的数据信息。
DELETE
FROM T_B_INFOS
代码执行以后,T_B_INFOS数据表中的数据信息全部被删除。
5.4.4 使用TRUNCATE TABLE语句
在SQL中,除了通过省略WHERE子句的方式删除数据表中所有的记录之外,还可以使用TRUNCATE TABLE语句删除表中的所有数据。
【语法说明】
TRUNCATE TABLE语句语法格式如下所示。
TRUNCATE TABLE table_name
虽然通过使用DELETE语句省略WHERE子句的形式和使用TRUNCATE TABLE语句都能够删除数据表中的所有数据。但是TRUNCATE TABLE语句比用DELETE语句要快得多,二者的区别主要表现为以下两点:
- 使用DELETE语句,系统将一次一行地处理要删除表中的记录,在从表中删除记录之前,在事务处理日志中记录相关的删除操作和删除行中的列值,以防止删除失败时,可以使用事务处理日志来恢复数据。
- TRUNCATE TABLE则一次性完成删除与表有关的所有数据页的信息。另外,TRUNCATE
TABLE语句并不能更新事务处理日志。由此,在SQL Server中,使用TRUNCATE
TABLE语句从表中删除数据信息之后,将不能用ROLLBACK命令取消行的删除操作。
【代码实战】
使用TRUNCATE TABLE语句删除T_B_INFOS数据表中所有的数据信息。
TRUNCATE TABLE T_B_INFOS
代码执行以后,通过SELECT语句删除数据表中记录信息,发现T_B_INFOS数据表中的所有的数据信息全部被删除。