第4章 表中数据的基本操作
前面介绍了数据表的创建以及数据表的相关操作。本章将开始介绍通过SELECT、INSERT、UPDATE和DELETE命令查询、添加、更新和删除表中的数据。另外,还将简单介绍数据库中数据的复制以及导入、导出操作。
4.1 查询数据表
查询数据表可以说是对数据表使用最频繁的一种操作了,查询数据表只需要记住SELECT语句就可以对数据表进行简单地查询。本节讲解使用该语句查询数据表,以及在SQL Developer工具中查询数据表。
4.1.1 查询表中的数据
第3章已经介绍了如何在数据库中创建表,那么如何使用语句查询表中的数据呢?不论是在Oracle数据库还是在SQL Server数据库中,查询数据表中的数据都是使用标准的SQL语句中的SELECT语句来完成的。这里,只介绍简单的查询操作,对于比较复杂的查询可以参考本书后面的章节。查询表中的数据的一般语法如下:
SELECT 列名1, 列名2, … FROM 表名
在SELECT关键词后面放置的是要在查询结果中显示的列名,这些列名来源于FROM后面表中的列名。如果想查询表中的全部数据,可以在SELECT后面使用“*”代替列名。
在使用SELECT语句查询时,一定要在查询的多个列名之间,用英文状态下的逗号隔开。
【实例4-1】查询BOOKINFO表的图书名称和作者的数据。
查询语句如下:
01 SELECT BOOKNAME, AUTHOR FROM BOOKINFO 02 /
【代码解析】
◆ BOOKNAME, AUTHOR是准备查询的列名,在列名之间要用逗号隔开。
【执行效果】
在SQL*Plus中执行以上脚本,效果如图4.1所示。
图4.1 【实例4-1】查询结果
在此可以看出,查询时只显示了在SELECT语句后面指定的列名,如果只需要显示表中的部分列时可以使用此方法;如果需要查询表中的全部数据,可以参考【实例4-2】。
【实例4-2】查询BOOKINFO表中的全部数据。
查询语句如下所示:
SELECT * FROM BOOKINFO;
【代码解析】
◆ “*”代表查询表中的全部字段。
4.1.2 使用SQL Developer工具查询表中的数据
查询表中所有列的效率会比查询指定的列效率低,所以在实际应用中应尽量少用查询所有数据的方法。
SQL Developer是目前经常使用的一款Oracle操作工具,大多数企业都使用该工具操作Oracle数据库。它比Oracle自带的企业管理器使用起来更加方便,如图4.2所示是SQL Developer主界面。
图4.2 SQL Developer主界面
通过SQL Developer工具可以很方便地操作Oracle数据库,特别对数据库对象和数据的操作是最方便的。下面就以查询BOOKINFO表为例,查看该表中的数据。
【实例4-3】查询BOOKINFO表的全部数据。
在如图4.2所示界面的左侧文件夹中找到“表”文件夹,该文件夹就是当前登录用户所创建的表。在其中找到已经创建的BOOKINFO表,并右击该表,出现如图4.3所示的右键菜单。
图4.3 表操作的右键菜单
在弹出的右键菜单中,选择【打开】选项,在右侧的窗口中显示出BOOKINFO表中的全部数据,如图4.4所示。
图4.4 查询BOOKlNFO表的全部记录
至此,就完成了查询BOOKINFO表的全部记录的操作,实际上就等价于“SELECT * FROM BOOKINFO”。
如果想在查询结果中只显示几个列,则可以在查询结果上面的语句部分自行编写SQL语句。
4.2 添加数据
在PL/SQL语言中,使用INSERT命令可以将新的数据行追加到表中。使用该命令可以向表中插入整行数据,也可以对部分列插入数据。在Oracle数据库中使用它,一次只能向表中添加一行记录。
4.2.1 添加操作的基本语法
在PL/SQL中,INSERT命令的基本语法如下:
INSERT [INTO] table_or_view_name [ ( column_list ) ] VALUES ({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中,列出的数据位置必须与字段的排列位置相对应。也就是说,第1个值插入第1列,第2个值插入第2列,依此类推。
对表进行INSERT操作时,需要目标表上的INSERT权限。在默认情况下,INSERT权限被授予sysadmin固定服务器角色成员、db_owner和db_datawriter固定数据库角色成员以及表的所有者。sysadmin、db_owner和db_securityadmin角色成员及表的所有者可以将权限传递给其他用户。
4.2.2 直接向表中添加数据
下面将结合具体的实例讲解使用INSERT命令向数据表中添加一行数据。为了便于理解,新创建一个实例表BOOKS,其表结构及约束如表4.1所示。
表4.1 BOOKS表的结构及约束
BOOKS表的创建代码如下:
01 CREATE TABLE BOOKS 02 ( 03 B_ID INT NOT NULL UNIQUE, 04 B_Name VARCHAR(40) NOT NULL , 05 B_Publish VARCHAR(16), 06 B_Price NUMBER DEFAULT 0.00, 07 B_Pubdate DATE DEFAULT SYSDATE 08 )
执行效果如图4.5所示。
图4.5 创建BOOKS表
【实例4-4】使用INSERT命令向BOOKS表中插入记录。
本实例将使用INSERT命令向BOOKS表中添加两行记录,实例代码如下:
01 INSERT INTO BOOKS ..插入一行记录 02 (B_ID,B_Publish,B_Name,B_Price,B_Pubdate) 03 VALUES 04 (1001,'大众出版社','计算机文化基础',34.6, to_date('2010.1.1','yyyy.mm.dd')); 05 06 INSERT INTO BOOKS ..插入一行记录 07 VALUES 08 (1002,'计算机硬件基础','科学出版社',44.5, to_date('2011.1.1','yyyy.mm.dd'));
【代码解析】
◆ B_Pubdate在数据库中是日期型,向该字段中插入日期时需要对字符串类型进行转换,字符串类型转换成日期型使用的函数是to_date(字符串,'日期的格式')。
【执行效果】
在SQL*Plus中执行以上脚本,效果如图4.6所示。
图4.6 向BOOKS表中插入记录
此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
查询结果如图4.7所示。
图4.7 查询结果
可见,实例代码中的两种方式均成功地向表中插入了记录。如果采用第1种方式,即在表名后指明列名,则VALUES后的值必须与列名的顺序相对应;而如果在表名后不指明列名,即第2种方式,则默认是按照表中的所有列及其在表中的排列顺序插入数据的。
在如图4.7所示的窗口中,为了能够整齐地显示查询结果,可以先设置显示的格式,如:COLUMN B_NAME FORMAT A20。
4.2.3 数据中NULL值的处理
在数据库表中,有些字段可以为空(NULL),因此,向表中插入数据时,如果要插入为NULL的字段值,则可以在INSERT INTO关键词后不列出该列的列名。也可以列出该列的列名,但在VALUES关键词后将该列的值设置为NULL。比如下面的实例。
【实例4-5】使用INSERT命令插入带有空值的记录。
本实例将使用INSERT命令向BOOKS表中添加2行记录,其中包含有空值。实例代码如下:
01 INSERT INTO BOOKS ..插入一行记录 02 VALUES 03 (1003,'数据库基础','北京大学出版社',NULL,NULL); 04 05 INSERT INTO BOOKS ..插入一行记录 06 VALUES 07 (1004,'计算机硬件基础',NULL,54.5, to_date('2011.1.1','yyyy.mm.dd'));
【代码解析】
相比交互式的SQL语句,存储过程主要具有如下优点。
◆ 存储过程允许组件式编程。它被创建以后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句,从而极大地提高了程序的可移植性。
◆ 第3行和第7行分别使用了NULL来表示数据,它们表示数据为空,即不存入任何数据。
【执行效果】
执行效果如图4.8所示。
图4.8 插入空值记录
运行该代码,此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
得到的查询结果如图4.9所示。
如果插入的某字段值为空,则该字段对应的VALUE值为“NULL”,允许什么都不写。
图4.9 查询结果
可见,两种方式均成功地实现了带有NULL值记录的插入操作。当然,能够向表中添加带有NULL值的记录,其前提是表中该字段允许为空值,即创建表时,没有NOT NULL约束;否则,会引发INSERT命令执行失败。比如下面的操作代码:
01 INSERT INTO BOOKS ..插入一行记录 02 VALUES 03 (1005,NULL,'科学出版社',24.5, to_date('2011.1.1','yyyy.mm.dd'));
执行该代码,系统会提示执行失败,并给出错误提示信息,如图4.10所示。
图4.10 为非空列插入空值错误提示
这是因为在创建BOOKS表时,B_Name字段定义为NOT NULL,而在INSERT命令中, B_Name字段对应的值为NULL,因此就出现了错误。这时候,如果暂时不清楚该字段的具体值,则可以用空格或其他字符代替。这里用“*”代替,代码如下:
01 INSERT INTO BOOKS ..插入一行记录 02 VALUES 03 (1005,'****','科学出版社',24.5, to_date('2011.1.1','yyyy.mm.dd'));
此时,代码就能成功执行。运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
得到的查询结果如图4.11所示。
图4.11 查询结果
4.2.4 插入值是默认值的处理
与NULL值相似,创建表时,可以通过DEFAULT关键词指定列的默认值。向带有默认值的表插入记录时,如果未指定该列的值,系统会自动采用定义的默认值作为该列的值。当然,也可以在INSERT命令中,显式地指定该列采用默认值。比如下面的实例。
【实例4-6】使用INSERT命令插入采用默认值的记录。
本实例将使用INSERT命令向BOOKS表中添加2行记录,其中有的字段采用默认值。实例代码如下:
01 INSERT INTO BOOKS ..插入一行记录 02 (B_ID,B_Name,B_Publish,B_Pubdate) 03 VALUES 04 (1006,'遥感信息处理','科学出版社', to_date('2011.1.1','yyyy.mm.dd')); 05 06 INSERT INTO BOOKS ..插入一行记录 07 VALUES 08 (1007,'图形图像处理',NULL,29.5, DEFAULT);
【执行效果】
在SQL*Plus中的执行效果如图4.12所示。
图4.12 插入带有默认值的记录
运行该代码,此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
得到的查询结果如图4.13所示。
图4.13 查询结果
可见,这两种方式均成功地实现了默认值的添加。
当使用INSERT命令向一个表中插入一条新记录,但其中有一个或几个字段没有提供数据时,如果要使INSERT命令成功执行,则需要满足下面几个条件之一:
(1)该列具有默认值,则使用列的默认值。
(2)具有timestamp数据类型,则使用当前的时间戳值。
(3)可为空值,则使用空值。
(4)是计算列,则使用计算值。
4.2.5 插入值是唯一值的处理
在Oracle数据库中创建表时,允许为列设置UNIQUE属性。这个属性意味着,在当前表中,该列中的值必须是完全唯一的,并且只能出现一次。有了这种限制,向表中插入数据或修改数据时,可能会导致出问题。
比如在BOOKS表中,B_ID字段就设置有UNIQUE属性,即唯一性约束。使用INSERT命令向BOOKS表中插入数据时,如果B_ID字段的值在该表中已经存在,则插入操作就会失败。比如下面的实例。
【实例4-7】插入带有唯一值(UNIQUE)的记录。
采用下面的INSERT命令向BOOKS表中添加一行记录:
01 INSERT INTO BOOKS ..插入一行记录 02 (B_ID,B_Name,B_Publish,B_Price,B_Pubdate) 03 VALUES 04 (1003,'计算机图形学','科学出版社',33, to_date('2011.1.1','yyyy.mm.dd'));
【执行效果】
执行该代码,系统会提示执行失败,并给出错误提示信息,如图4.14所示。
图4.14 违反唯一约束错误提示
这是因为在BOOKS表中,B_ID字段具有UNIQUE约束,而要插入的记录,值“1003”已经存在,因此插入操作失败。
一个规范化的表应有一个唯一字段或关键字段,这个字段在表之间连接数据时是有用的,在使用索引时通常可以提高查询速度。
4.2.6 使用lNSERT...SELECT插入数据
前面介绍了使用INSERT命令向表中插入行,而有时用户需要根据已有表和视图的记录,将其中特定的数据添加到目标表中,这时就可以使用INSERT...SELECT语句来实现。该语句实际上包含两部分:INSERT(插入语句)和SELECT(查询语句),其语法可表示如下:
INSERT [INTO] table_or_view_name [ ( column_list ) ] SELECT column_list FROM data_source
这样,通过INSERT...SELECT语句可以一次性向目标表中插入大量数据。另外,使用该语句时,需要注意下面几点。
◆ SELECT语句不能从正在被插入的表和视图中选择数据。
◆ 在INSERT INTO语句中,列的数目必须等于从SELECT语句返回列的数目。
◆ 在INSERT INTO语句中,列的数据类型必须与从SELECT语句返回列的数据类型相同。
下面通过一个实例讲解INSERT...SELECT语句的用法。
【实例4-8】使用INSERT...SELECT语句向表中添加数据。
本实例将使用INSERT...SELECT语句,将BOOKINFO表中的图书记录添加到BOOKS表中。实例代码如下:
01 INSERT INTO BOOKS 02 (B_ID,B_Name,B_Publish,B_Price,B_Pubdate) 03 SELECT bookid,bookname,publish,price,pubdate 04 FROM BOOKINFO;
【执行效果】
在SQL*Plus中的执行效果如图4.15所示。
图4.15 使用lNSERT...SELECT语句插入数据
运行该代码,此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
得到的查询结果如图4.16所示。
图4.16 BOOKS表查询结果
可见,通过INSERT...SELECT语句执行一次操作就向目标表中添加了多行记录。
INSERT...SELECT语句通常用于创建查找表,以提高检索性能。查找表可以包含分布在多个数据库的多个表中的数据。因为多个表连接处理起来比简单查询要慢,对一个查找表执行SELECT查询,则明显快于执行又长又复杂的连接查询。
INSERT...SELECT语句的另一个用途是备份表,备份将要删除、截断数据或重新装入数据的表。
4.2.7 使用SQL Developer工具添加数据
使用SQL Developer工具添加数据的操作可以像在Excel表格中输入数据一样简单,下面就以向BOOKS表中添加数据为例,演示SQL Developer工具的使用。
【实例4-9】使用SQL Developer工具向BOOKS表中添加数据。
在如图4.3所示的界面中,右击选择BOOKS表,在弹出的右键菜单中选择【打开】选项,如图4.17所示。
图4.17 编辑BOOKS表界面
在此界面中的最后一行后面添加数据,输入要添加的数据后单击工具栏上的对号,即可保存结果,提交后记录才真正添加到数据库中。
4.3 修改数据
在PL/SQL语言中,可以使用UPDATE命令更改表或视图中的现有数据。该语句既可以一次修改一条记录,也可以一次修改多条记录,甚至可以一次修改表中的全部数据行。
4.3.1 修改操作的基本语法
在PL/SQL中,UPDATE命令的基本语法如下:
UPDATE <table_or_view_name> SET column_name = {expression | DEFAULT | NULL} [ ,...n ] WHERE <search_condition>
【语法说明】
◆ table_or_view_name为要更新行的表或视图的名称,且引用的视图必须可更新,并且只在该视图的FROM子句中引用一个基表。如果该表不在当前服务器或数据库中,或不是当前用户所有,这个名称可用连接服务器、数据库和所有者名称来限定。
◆ column_name为要更改数据的列,它必须已存在于table_or_view_name中。
◆ search_condition为要更新的行指定需满足的条件。
如果对行的更新违反了某个约束或规则,或者违反了对列的NULL设置,或者新值是不兼容的数据类型,则取消该语句,返回错误,并且不更新任何记录。
当UPDATE语句在表达式求值过程中遇到算术错误(溢出、被零除)时,则不进行更新。批处理的剩余部分不再执行,并且返回错误消息。
一定不要忽略WHERE子句,如果没有指明WHERE子句,则数据库表中所有行的记录都将被更新。
4.3.2 使用UPDATE语句更新数据行
使用UPDATE语句更新表中的数据时,可以使用WHERE子句指定要修改的行,使用SET子句给出新的数据。下面给出一个实例,说明如何使用该语句更新表中的一行数据。
【实例4-10】使用UPDATE使用更新表中的一行数据。
本实例使用UPDATE语句,将BOOKS表中图书编号为“1005”的图书名称(B_Name)更新为“随机信号处理”。实例代码如下:
01 UPDATE BOOKS 02 SET B_Name='随机信号处理' 03 WHERE B_ID=1005;
【执行效果】
在SQL*Plus中的执行效果如图4.18所示。
图4.18 更新数据
运行该代码,此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
得到的查询结果如图4.19所示。
图4.19 BOOKS表查询结果
当然,使用UPDATE语句也可以一次更新多行数据。比如下面的实例。
【实例4-11】使用UPDATE语句更新表中的多行数据。
本实例使用UPDATE语句,将BOOKS表中所有的科学出版社的图书价格(B_Price)设置为9折。实例代码如下:
01 UPDATE BOOKS 02 SET B_Price=B_Price*0.9 03 WHERE B_Publish='科学出版社';
【执行效果】
在SQL*Plus中的执行效果如图4.20所示。
图4.20 更新多行数据
运行该代码,此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
得到的查询结果如图4.21所示。
图4.21 BOOKS表查询结果
4.3.3 根据条件修改表中的数据
有时候,需要根据其他表的信息来更新目标表中的某些数据。这时,可以在UPDATE语句中,使用FROM子句引入参考表,通过WHERE子句指定更新条件。使用语法可表示如下:
UPDATE <table_or_view_name> SET column_name = {expression | DEFAULT | NULL} [ ,...n ] FROM <table_source> WHERE <search_condition>
FROM子句后指定表、视图或派生表源,为更新操作提供条件。如果更新的对象在该子句中出现了不止一次,则对此对象的一个(且仅仅一个)引用不能指定表别名,其中对该对象的所有其他引用都必须包含对象别名。当然,在FROM子句中也可以指定进行多表连接。
4.3.4 使用SQL Developer工具修改数据
前面已经讲解过使用SQL Developer工具查询数据和添加数据,修改数据和添加数据一样,都是在如图4.3所示的界面中右击选择表,在弹出的右键菜单中选择【打开】选项,在右侧的窗口中选择【数据】选项,可以看到表中的全部数据,直接编辑要修改的数据,然后保存即可。这里就不再讲述了,请读者自行练习。
4.4 删除数据
当不再使用表中的记录时,可以使用DELETE语句将其删除。使用DELETE语句可以一次删除一条或多条记录,而且可以使用WHERE子句指定删除条件。
4.4.1 删除操作的基本语法
在PL/SQL中,DELETE命令的基本语法如下:
DELETE [FROM] table_or_view_name WHERE search_condition
其中,FROM为可选的关键词,可用在DELETE关键词与目标table_or_view_name之间。
如果要删除表中的所有行,请使用未指定WHERE子句的DELETE语句,或者使用TRUNCATE TABLE语句。TRUNCATE TABLE比DELETE执行速度快,且使用的系统和事务日志资源少。另外,使用DELETE语句时,应注意以下几点。
◆ DELETE语句不能删除单个字段的值,它只能删除整行数据。要删除单个字段的值,可以使用上节介绍的UPDATE语句,将其更新为NULL。
◆ 使用DELETE语句仅能删除记录即表中的数据,不能删除表本身。要删除表,需要使用前面介绍的DROP TABLE语句。
◆ 同INSERT和UPDATA语句一样,从一个表中删除记录将引起其他表的参照完整性问题。这是一个潜在问题,需要时刻注意。
4.4.2 删除表中的数据
DELETE语句可以删除数据库表中的单行数据、多行数据以及所有行数据。另外,与UPDATE语句一样,也可以使用FROM子句根据其他表的信息删除目标表的记录行,还可以在WHERE子句中通过子查询删除数据。
【实例4-12】使用DELETE语句删除表中的行。
本实例使用DELETE语句,将BOOKS表中所有大众出版社的图书记录删除。实例代码如下:
01 DELETE FROM BOOKS 02 WHERE B_Publish='大众出版社';
【执行效果】
在SQL*Plus中的执行效果如图4.22所示。
图4.22 删除记录
运行该代码,此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS
得到的查询结果如图4.23所示。
图4.23 BOOKS表查询结果
由此可见,所有大众出版社的图书记录均被删除。
4.4.3 有关TRUNCATE的使用
使用TRUNCATE TABLE语句可以删除表中的所有行,而不记录单个行删除操作。其使用语法如下:
TRUNCATE TABLE table_name
下面通过实例说明其使用方法。
【实例4-13】使用TRUNCATE TABLE语句删除表中的所有数据。
本实例将实现删除BOOKS表中的所有记录。实例代码如下:
01 TRUNCATE TABLE BOOKS;
【执行效果】
在SQL*Plus中的执行效果如图4.24所示。
图4.24 使用TRUNCATE语句删除表中的所有记录
运行该代码,则BOOKS表中的所有记录都将被删除。此时,运行下面的代码查询BOOKS表的记录:
SELECT * FROM BOOKS;
得到的查询结果如图4.25所示。
图4.25 BOOKS表查询结果
可见,虽然BOOKS表中的数据均被删除,但表结构并没有被删除,即BOOKS表仍然存在,这与前面介绍的删除表的DROP TABLE语句是不同的。
虽然使用DELETE语句和TRUNCATE TABLE语句都能够删除表中的所有数据,但是使用TRUNCATE TABLE语句比使用DELETE语句的执行效率要高。这是因为:使用DELETE语句,系统将一次一行地处理要删除的表中的记录,在从表中删除行之前,在事务处理日志中记录相关的删除操作和删除行中的列值,以便在删除失败时,可以使用事务处理日志来恢复数据。
使用TRUNCATE TABLE语句则一次性完成删除与表有关的所有数据页的操作。另外, TRUNCATE TABLE语句并不更新事务处理日志。因此,使用TRUNCATE TABLE语句从表中删除行后,将不能用ROLLBACK命令取消行的删除操作。
4.4.4 使用SQL Developer工具删除数据
使用SQL Developer工具删除数据,只需要在编辑数据的界面上选中要删除的数据,点击工具栏上面的减号即可删除数据。工具栏如图4.26所示。
图4.26 工具栏
4.5 小结
本章主要讲解了如何操作数据表中的数据,也就是SQL语句中的DML(数据操纵语言)部分的内容,包括数据的添加、数据的修改、数据的删除以及查询操作。在本章中着重讲解了数据的添加操作。在添加数据时,讲解了插入值是默认值的处理、插入值是唯一值的处理,以及使用INSERT…SELECT语句插入数据。此外,还介绍了使用SQL Developer工具添加、修改、删除数据的操作。