GBase 8s SQL 指南:教程———7修改数据

7修改数据

7.1修改数据库中的数据

下列语句修改数据:

  • DELETE
  • INSERT
  • MERGE
  • UPDATE

当与更高级的SELECT语句相比时,虽然这些SQL语句相对简单,但由于它们更改数据 库的内容,因此请小心使用它们。

如果在查询期间系统硬件或软件岀现故障,请考虑会发生什么。即使对应用程序的影响是 严重的,也不会破坏数据库自身。然而,如果正在进行修改时系统发生故障,则数据库的 状态就不确定了。显然,处于不确定状态的数据库具有深远的影响。在数据库中删除、插 入或更新行之前,请询问自己下列问题:

用户对数据库及其表的访问是否安全。即,是否将有限的数据库和表级别权限授予 特定用户?

修改了的数据是否保持数据库现有的完整性?

系统的状况是否使其对可能导致系统或硬件故障的外部事件具有相对较强的免疫 力?

如果对这些问题不能都回答“是”,也不用担心。对所有这些问题的解决方案都内建在GBase 8s数据库服务器内。在对修改数据的语句进行描述之后,这部分讨论这些解决方案。

7.2删除行

DELETE从表中移除任何行或行的组合。在提交该事务之后,您不可恢复删除了的行。

(在中断了的修改之下讨论事务。现在,请将事务与语句看做是一回事。)

当删除一行时,您还必须小心地删除其值依赖于该删除了的行的其他表的任何行。如果数 据库强制执行引用约束,则您可使用CREATE TABLEALTER TABLE语句的ON DELETE CASCADE选项来允许从与另一表的关系中的一个表进行级联删除。要获取关于 引用约束和ON DELETE CASCADE选项的更多信息,请参阅引用完整性。

7.2.1删除表的所有行

DELETE语句指定表并通常包含WHERE子句,该子句指定要从表中移除的一行或多行。 如果省略WHERE子句,则删除所有行。

重要:请不要执行下列语句。

DELETE FROM customer;

您可编写带有或不带FROM关键字的DELETE语句。

DELETE customer;

由于这些DELETE语句不包含WHERE子句,因此从customer表删除所有行。如果您尝 试使用DB-Access菜单选项来进行无条件的删除,则程序会警告您并要求确认。然而,从 程序之内执行无条件的DELETE可在不发出警告的情况下发生。

如果想要从名为from的表中删除行,则您必须首先设置DELIMIDENT环境变量,或使用 其所有者的名称来限定该表的名称:

DELETE legree.from;

要获取关于定界的标识符以及DELIMIDENT环境变量的更多信息,请参阅《GBase 8s SQL 指南:语法》中对“带引号的字符串”表达式以及“标识符”段的描述。

7.2.2使用TRUNCATE来删除所有行

您可使用TRUNCATE语句来快速地从表中移除所有行,同时还移除所有对应的索引数 据。在提交该事务之后,您不可恢复删除了的行。您可对包含任何列类型(包括智能大对 象)的表上使用TRUNCATE语句。

使用TRUNCATE语句来移除行的速度比使用DELETE语句来移除它们快。在

TRUNCATE语句之后,不必立即运行UPDATE STATISTICS语句。成功地执行 TRUNCATE之后,GBase 8s自动地更新该表及其系统目录中的索引的统计信息和分布情 况,以展示在该表中或在它的dbspace分区中没有任何行。

要了解日志记录的描述,请参阅事务日志记录。

TRUNCATE是数据定义语言语句,如果在该表上定义任何触发器,则该语句不激活 DELETE触发器。要了解关于使用触发器的说明,请参阅创建和使用触发器。

如果TRUNCATE语句指定的表是typed表,则成功的TRUNCATE操作从那个表中以 及从该表层级结构内的所有子表中移除所有行和B-tree结构。TRUNCATE不等同于 DELETE语句的ONLY关键字,DELETE语句将操作限制在typed表层级结构内的单个 表。

GBase 8s始终对TRUNCATE操作进行日志记录,即使对非日志记录的表也是如此。在支 持事务日志记录的数据库中,在同一事务之内的TRUNCATE之后,仅SQLCOMMIT WORKROLLBACK WORK语句是有效的。要获取关于使用TRUNCATE语句对性能 的影响的信息,请参阅GBase 8s性能指南》。要了解完整的语法,请参阅GBase 8s SQL 指南:语法》。

7.2.3删除指定的行

DELETE语句中的 WHERE子句与SELECT语句中的 WHERE子句的形式相同。您可 使用它来准确地指定应删除哪一行或哪些行。您可删除带有特定客户编号的客户,如下例 所示:

DELETE FROM customer WHERE customer_num = 175;

在此示例中,由于customer_num列有唯一约束,因此您可确保只删除一行。

7.2.4删除选择了的行

您还可选取基于非索引列的行,如下例所示:

DELETE FROM customer WHERE company = 'Druid Cyclery';

由于被测试的列没有唯一约束,因此此语句可能删除多行。(Druid Cyclery可能有两个商 店,两个商店的名称相同但客户编号不一样。)

要了解DELETE语句影响多少行,请从customer表中为Druid Cyclery选择符合条件的行 计数。

SELECT COUNT(*) FROM customer WHERE company = 'Druid Cyclery';

您还可选择这些行并显示它们,以确保它们是您想要删除的那些行。

然而,当数据库对于多个用户同时可用时,使用SELECT语句作为测试只是一种近似的方 法。在您执行SELECT语句与后续的DELETE语句之间的时间内,其他用户可能已修改 了该表并更改了结果。在此示例中,另一用户可能执行下列操作:

  • 为名为Druid Cyclery的另一客户插入新行
  • 在插入新行之前,删除一个或多个Druid Cyclery

更新Druid Cyclery行以具有新的公司名称,或更新某个其他客户以具有名称 Druid Cyclery o

在这短短的时间间隔内,虽然其他用户不太可能执行这些操作,但确实存在这种可能性。 相同的问题也影响UPDATE语句。在并发和锁定之下讨论解决此问题的方法,且在对多 用户环境编程中讨论得更详细。

您可能遇到的另一个问题是,在该语句完成之前出现硬件或软件故障。在此情况下,数据 库可能还没删除行,可能已删除了一些行,或已经删除了所有指定的行。数据库的状态未 知,这是我们不想看到的。要防止此情况,请使用事务日志记录,如中断了的修改讨论的 那样。

7.2.5删除包含row类型的行

当某行包含定义在ROW类型上的列时,您可使用点符号表示法来指定仅删除那些包含特 定字段值的行。例如,下列语句仅从employee表中删除address列中的city字段的值为San Jose 的那些行:

DELETE FROM employee

WHERE address.city = 'San Jose';

在前面的语句中,address列可能是命名的ROW类型或未命名的ROW类型。您用来指 定ROW类型的字段值的语法是相同的。

7.2.6删除包含集合类型的行

当某行包含定义在集合类型上的列时,您可在集合中搜索特定的元素,并删除在其中找到 那个元素的一行或多行。例如,下列语句删除其中的direct_reports列包含带有元素Baker的 集合的那些行:

DELETE FROM manager

WHERE 'Baker' IN direct_reports;

7.2.7从超级表中删除行

当您删除超级表的各行时,删除操作的作用域是超级表及其子表。假设您创建超级 表person在其下定义两个子表employeesales_rep下列对person表执行的DELETE语 句可从personemployeesales_rep全部三个表中删除行:

DELETE FROM person

WHERE name ='Walker';

要限制为仅删除超级表的行,您必须使用DELETE语句中的ONLY关键字。例如,下列 语句仅删除person表的行:

DELETE FROM ONLY(person)

WHERE name ='Walker';

重要:当您从超级表中删除行时,请小心使用,因为对超级表的删除的作用域包括该超级表及 其所有子表。

7.2.8复杂的删除条件

DELECT语句中的 WHERE子句可与SELECT语句中的一样复杂。它可包含通过AND OR连接的多个条件,且它可能包含子查询。

假设您发现stock表的某些行包含不正确的制造商代码。您不想更新它们,而是想要删除它 们以便重新输入它们。您知道,与正确的那些行不一样,这些行在manufact表中没有相匹 配的行。由于这些不正确的行在manufact表中没有相匹配的行,因此您可以编写下例中所 示的DELETE语句:

DELETE FROM stock

WHERE 0 = (SELECT COUNT(*) FROM manufact

WHERE manufact.manu_code = stock.manu_code);

该子查询对匹配的manufact行数进行计数;对stock的正确的行计数为1,对不正确的行 计数为0。选取不正确的行来删除。

提示: 使用复杂的条件来开发DELETE语句的一种方法是,先开发精确地返回要删除的行的

SELECT语句。将它编写为SELECT *;当它返回所期望的行集时,将SELECT *更改为读 取DELETE,并再执行它一次。

DELETE语句的WHERE子句不可使用测试同一表的子查询。即,当您从stock进行删除 时,您不可在也从stock中选择的WHERE子句中使用子查询。

此规则的关键在于FROM子句。如果在DELETE语句的FROM子句中命名表,则该表 不可还出现在DELECT语句的子查询的FROM子句中。

7.2.9 MERGE Delete 子句

不在WHERE子句中编写子查询,您可使用MERGE语句将来自源表和目标表的行连接 在一起,然后从目标删除与连接条件相匹配的那些行。(Delete MERGE中的源表还可为 一个集合派生的表,它的行是查询的结果,该查询连接其他的表和视图,但是在下列的示 例中,源是单个表。)

如在前面的示例中那样,假设您发现stock表的某些行包含不正确的制造商代码。您想要删 除它们以便重新输入它们,而不是更新它们。您可使用MERGE语句,指定stock作为目 标表,manufact作为源表,ON子句中的连接条件,并对于带有不正确的制造商代码 的stock行使用Delete子句,如下例所示:

MERGE INTO stock USING manufact

ON stock.manu_code != manufact.manu_code

WHEN MATCHED THEN DELETE;

在此示例中,会从stock表中删除那些满足ON子句中的连接条件的所有行。在此,对于 其中的manu_code列值不等于manufact中的任何manu_code值的stock的那些行,连接条 件中的不等谓词(stock.manu_code != manufact.manu_code)求值为真。

USING子句中必须罗列正连接到目标表的源表。

MERGE语句还可更新目标表的行,或将数据从源表插入到目标表,根据该行是否满足ON 子句为连接目标表与源表而指定的条件。单个MERGE语句还可同时组合DELETE

INSERT操作,或者可同时组合UPDATEINSERT操作而不删除任何行。MERGE语 句不更改源表。要获取关于Delete合并、Insert合并和Update合并的语法与限制的更多 信息,请参阅《GBase 8s SQL指南:语法》中MERGE语句的描述。

7.3插入行

INSERT将新的一行或多行添加到表。该语句有两个基本功能。它可使用您提供的列值创 建单个的新行,或可使用从其他表选择的数据创建一组新的行。

7.3.1单个行

在它的最简单形式中,INSERT语句从一列值的列表创建一个新行,并将其放置在表中。 下列语句展示如何将一行添加到stock表:

INSERT INTO stock

VALUES (115, 'PRC', 'tire pump', 108, 'box', '6/box');

stock表有下列列:

stock_num

标识商品的种类的编号。

manu_code

manufact表的外键。

description

该商品的描述。

unit_price

该商品的单价。

unit

计量的单位

unit_descr

说明计量单位的特征。

前一示例中VALUES子句中罗列的值与stock表的列有一一对应关系。要编写VALUES 子句,您必须知道表的列以及它们的前后次序。

可能的列值

VALUES子句仅接受常量值,不接受通用的SQL表达式。您可提供下列值:

  • 文字数值
  • 文字 DATETIME
  • 文字 INTERVAL

带引号的字符串

  • 表示 NULL 的关键字 NULL

表示当前日期的关键字TODAY

  • 表示当前日期和时间的关键字CURRENT (或SYSDATE

表示您的授权标识符的关键字USER

  • 表示正在运行数据库服务器的计算机名称的关键字DBSERVERNAME (或 SITENAME

注:MERGE语句可以替代INSERT语句,可使用与INSERT语句一样的VALUES子句语法来 将行插入到表内。MERGE语句执行源表与目标表的外部链接,然后将连接的结果集中的任何行 插入到目标表内,这些行的连接谓词求值为FALSEo MERGE语句不更改源表。除了插入行之外, MERGE语句可可选地同时组合DELETEINSERT操作,或同时组合UPDATEINSERT 操作。要获取关于Insert合并、Delete合并和Update合并的语法与限制的更多信息,请参 阅《GBase 8s SQL指南:语法》 中MERGE语句的描述。

对列值的限制

表的某些列可能不允许空值。如果您尝试向这样的列插入NULL则会拒绝该语句。表中 的其他列可能不允许重复的值。如果您指定与这样的列中已经存在的值重复的值,则会拒 绝该语句。有些列甚至可能限制允许的列值。请使用数据完整性约束来限制列。要获取更 多信息,请参阅数据完整性。

限制:请不要为包含货币值的列指定币种符号。请仅指定该金额的数值值。

数据库服务器可在数值与字符数据类型之间进行转换。您可将数值字符的字符串(例如, '-0075.6')作为数值列的值。数据库服务器将数值字符串转换为数值。仅当该字符串不表示 数值时才会发生错误。

您可指定数值或日期作为字符列的值。数据库服务器将那个值转换为字符串。例如,如果 您指定TODAY作为字符列的值,则使用表示当前日期的字符串。DBDATE环境变量 指定所使用的格式。)

序列数据类型

表仅可有一个SERIAL数据类型的列。它还可有SERIAL8列或BIGSERIAL列。

当您插入值时,请为序列列指定值零。数据库服务器按次序生成下一个实际值。序列列不 允许NULL值。

您可为序列列指定非零值(只要它不与那一列中任何现有的值重复),数据库服务器使用 该值。那个非零值可能为数据库服务器生成的值设置新的起始点。(数据库服务器为您生 成的下一个值是比该列中最大值大一的值。)

罗列特定的列名称

您不必为每列都指定值。相反,您可在表名称之后罗列列名称,然后仅为您命名了的那些 列提供值。下列示例展示将新行插入到stock表内的语句:

INSERT INTO stock (stock_num, description, unit_price, manu_code)

VALUES (115, 'tyre pump ', 114, 'SHM');

仅提供库存编号、描述、单价和制造商代码的数据。数据库服务器为其余列提供下列值:

它为未列出的序列列生成一个序列数值。

它为与它相关联的有特定缺省值的列生成一个缺省值。

它为任何允许空值的任何列生成NULL值,但它不为指定NULL作为缺省值的任 何列指定缺省值。

您必须为未指定缺省值或不允许NULL值的所有列罗列并提供值。

您可以任何顺序罗列列,只要这些列的值也以相同的顺序罗列。

在执行前一示例中的INSERT语句之后,将下列新行插入到stock表内:

stock_num manu_code description unit_price unit unit_descr

115 SHM tyre pump 114

unitunit_descr都为空,表示在那两列中存在NULL值。由于unit列允许NULL值, 因此不知道114美元可购买的轮胎充气泵(tire pump)的数目。当然,如果为这一列指定 了 box缺省值,则计量单位将为box。在任何情况下,当您将值插入到表的特定的列内时, 请注意那一行需要什么数据。

7.3.2将行插入到类型的表中

您可使用与将行插入到不基于ROW类型的表内的相同方法,将行插入到类型的表内。

当类型的表包含一 row类型列(定义该类型的表的命名了的ROW类型包含嵌套的ROW 类型)时,您插入到row类型列的方法,与为不基于ROW类型的表插入row类型列的 方法相同。下列部分,在列上插入的语法规则,描述如何执行插入到row类型列内。

此部分为示例使用row类型zip_taddress_temployee_t,以及 类型的表employee下 图展示创建row类型和表的SQL语法。

图:创建row类型和表的SQL语法。

CREATE ROW TYPE zip_t

(

z_code CHAR(5),

z_suffix CHAR(4)

);

CREATE ROW TYPE address_t

(

street

VARCHAR(20),

city

VARCHAR(20),

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值