还可以修改表中特定列的特征:
· 列的标识属性
· 字符串列的长度
· 列的数据类型
· 列的可空性
· 列的约束
对于修改列有一些限制:
· 在修改字符串列的长度时,只能增加长度。
· 在修改列的数据类型时,新的数据类型必须与现有的数据类型兼容。例如,可以将 CHAR 列转换为 VARCHAR 列,但是不能将它们转换为 GRAPHIC 或数字列。数字列可以转换为任何其他数字数据类型,只要新数据类型的长度足以容纳其中的值。例如,可以将 INTEGER 列转换为 BIGINT,但是 DECIMAL(10,2) 列不能转换为 SMALLINT。
· 固定长度的字符串可以转换为可变长度的字符串,可变长度的字符串也可以转换为固定长度的字符串。例如,CHAR(100) 可以转换为 VARCHAR(150)。对于可变长度的图形字符串也有类似的限制。
以下语句将 DiaoSiNAME 列的 DATATYPE 从 VARCHAR(100) 改为 VARCHAR(200),并将 ISBN 列的可空性改为 NOT NULL:
ALTER TABLE DiaoSi ALTER DiaoSiNAME SET DATA TYPE VARCHAR(200) ALTER ISBN SET NOT NULL |
表的某些特征不可以更改。例如,不可以修改某些列的数据类型、表驻留的表空间或列的次序。要更改这样的特征,必须保存表数据,删除表,然后重新创建表。
删除表
DROP TABLE 语句将表从数据库中删除,数据和表定义都被删除。如果为表定义了索引或者约束,它们也同时被删除。
下面的 DROP TABLE 语句从数据库中删除 BOOKS 表:
DROP TABLE DiaoSi 表的某些特征不可以更改。例如,不可以修改某些列的数据类型、表驻留的表空间或列的次序。要更改这样的特征,必须保存表数据,删除表,然后重新创建表。 |
参照完整性约束
参照完整性约束 用于定义表之间的关系并确保这些关系保持有效。假设有一个表包含关于作者的信息,而另一个表列出这些作者已经写的书。在 BOOKS 表和 AUTHORS 表之间有这样一种关系 —— 每本书都有一个作者,该作者必须存在于 AUTHORS 表中。每个作者都有一个存储在 AUTHORID 列中的惟一的标识符。AUTHORID 在 BOOKS 表中用于识别每本书的作者。要定义这种关系,应该把 AUTHORS 表的 AUTHORID 列定义为主键,然后在 BOOKS 表上定义一个外键,从而与 AUTHORS 表中的 AUTHORID 列建立关系:
CREATE TABLE AUTHORS (AUTHORID INTEGER NOT NULL PRIMARY KEY, LNAME VARCHAR(100), FNAME VARCHAR(100)) CREATE TABLE BOOKS (BOOKID INTEGER NOT NULL PRIMARY KEY, BOOKNAME VARCHAR(100), ISBN CHAR(10), AUTHORID INTEGER REFERENCES AUTHORS) |
拥有与另一个表相关的主键的表(这里的 AUTHORS 表)被称为父表(parent table)。与父表相关的表(这里的 BOOKS 表)被称为从属表(dependent table)。可以为一个父表定义多个从属表。
还可以定义同一个表中各行之间的关系。在这种情况下,父表和从属表是同一个表。
如果为一组表定义了参照约束,当对这些表执行更新操作时,DB2 就会强制这些表遵守参照完整性规则:
· DB2 确保只向定义了参照完整性约束的列中插入有效数据。这意味着在父表中必须总是有这样一行,该行的键值等于正要插入到从属表中的行的外键值。例如,如果一本新书要插入到 BOOKS 表中,它的 AUTHORID 为 437,那么 AUTHORS 表中必须有 AUTHORID 为 437 的一行。
· 当从父表中删除一行,而该行在从属表中有从属行时,DB2 也强制实施一些规则。DB2 采取的操作取决于为表定义的删除规则。可以指定四个规则:RESTRICT、NO ACTION、CASCADE 和SET NULL。
o 如果指定了 RESTRICT 或 NO ACTION,那么 DB2 不允许删除父行。必须首先删除从属表中的行才能删除父表中的行。这条规则是默认设置,所以当定义 AUTHORS 和 BOOKS表时这个规则也适用于它们。
o 如果指定了 CASCADE,那么从父表中删除行时还会自动地删除所有从属表中的从属行。
o 如果指定了 SET NULL,那么从父表中删除父行时从属行中的外键值被设置为空(如果可以为空的话)。
· 在更新父表中的键值时,可以指定两条规则:RESTRICT 和 NO ACTION。如果从属表中有从属行,则 RESTRICT 不允许更新键值。如果在更新完成时在从属表中有从属行,而从属行在父表中没有父键,则 NO ACTION 将导致对父键值的更新操作被拒绝。
表检查约束
表检查约束 用于确保列数据不违反为列定义的规则,并限制表的某一列中的值。DB2 确保在插入和更新时不违反这些约束。
假设向 BOOKS 表中添加一个表示书籍类型的列,该列允许的值为 ‘F’(小说)和 ‘N’(非小说)。可以添加一个列 BOOKTYPE,它带有以下的检查约束:
ALTER TABLE BOOKS ADD BOOKTYPE CHAR(1) CHECK (BOOKTYPE IN ('F','N') ) |
可以在创建表时定义检查约束,也可以在以后使用 ALTER TABLE SQL 语句添加它们。可以通过删除检查约束,然后使用 ALTER TABLE SQL 语句重新创建它们来修改检查约束。
视图
视图 允许不同的用户或应用程序以不同的方式查看相同的数据。这不仅使得数据更容易访问,还可以用它来限制用户可以查看或更新哪些行和列。
例如,假设一个公司有一个包含该公司职员信息的表。经理只需看到他的职员的地址、电话号码和工资信息,而电话簿应用程序需要查看公司中所有职员以及他们的地址和电话号码,但不需查看他们的工资。可以创建一个只显示一个特定部门内职员的所有信息的视图,再创建另一个只显示所有职员的姓名、地址和电话号码的视图。
对于用户来说,视图看起来就像表一样。除视图定义之外,视图在数据库内并不占用空间;视图中显示的数据来自另一个表。可以根据现有的一个表(或多个表)、另一个视图或者表和视图的任意组合创建一个视图。在另一个视图的基础上定义的视图被称为嵌套视图。
可以用不同于基表中相应列的列名定义视图。还可以定义一些检查插入或更新的数据是否一直满足视图条件的视图。
数据库中定义的视图的列表存储在系统编目表 SYSIBM.SYSVIEWS 中,SYSIBM.SYSVIEWS 还有一个根据它定义的名为 SYSCAT.VIEWS 的视图。系统编目还有一个 SYSCAT.VIEWDEP,对于数据库中定义的每一个视图所依赖的每个视图或表,SYSCAT.VIEWDEP 中都有一行。另外,每个视图都在 SYSIBM.SYSTABLES 中有一个条目,在 SYSIBM.SYSCOLUMNS 中有多个条目,因为可以像表一样使用视图。
创建视图
CREATE VIEW SQL 语句用于定义视图。SELECT 语句用于指定将在视图中显示哪些行与列。
例如,假设想创建一个只显示 BOOKS 表中非小说类书籍的视图:
CREATE VIEW NONFICTIONBOOKS AS SELECT * FROM BOOKS WHERE BOOKTYPE = 'N' |
定义这个视图后,SYSCAT.VIEWS、SYSCAT.VIEWDEP 和 SYSCAT.TABLES 中将有对应的条目。
要在视图中定义不同于基表中那些列的列名,可以在 CREATE VIEW 语句中指定它们。以下语句创建一个 MYBOOKVIEW 视图,该视图包含两列:TITLE(代表 BOOKNAME 列)和 TYPE(代表 BOOKTYPE 列)。
CREATE VIEW MYBOOKVIEW (TITLE,TYPE) AS SELECT BOOKNAME,BOOKTYPE FROM BOOKS |
DROP VIEW SQL 语句用于从数据库中删除视图。如果删除一个视图所基于的表或另一个视图,那么这个视图依然在数据库中被定义,但变得不起作用。SYSCAT.VIEWS 的 VALID 列表明视图是有效的(‘Y’)还是无效的(‘X’)。即使重新创建基表,无效的视图仍然是无效的;必须也重新创建它。
可以从数据库中删除 NONFICTIONBOOKS 视图:
DROP VIEW NONFICTIONBOOKS |
不能修改视图;要更改视图定义,必须删除视图,然后重新创建它。DB2 提供的 ALTER VIEW 语句只用于修改引用类型。
只读视图和可更新视图
在创建一个视图时,可以将它定义为只读视图 或者可更新视图。视图的 SELECT 语句决定视图是只读的还是可更新的。一般情况下,如果视图中的行可以映射到基表中的行,那么该视图就是可更新的。例如,就像前面示例中定义的那样,视图 NONFICTIONBOOKS 是可更新的,因为视图中的每一行都是基表中的行。
创建可更新视图的规则很复杂,它们取决于查询的定义。例如,使用 VALUES、DISTINCT 或 JOIN 特性的视图是不可更新的。通过查看 SYSCAT.VIEWS 的 READONLY 列很容易就能确定视图是不是可更新的:Y 表示只读,N 表示非只读。
DB2 SQL Reference 中说明了创建可更新视图的详细规则(请参阅 参考资料)。
先前定义的 NONFICTIONBOOKS 视图只包含 BOOKTYPE 为 N 的行。如果向这个视图中插入一个 BOOKTYPE 为 F 的行,DB2 将把该行插入到基表 BOOKS 中。但是,如果以后从视图中进行选择,通过该视图却看不到新插入的行。如果不想允许用户插入视图范围以外的行,那么在定义视图时可以使用检查选项。使用 WITH CHECK OPTION 定义视图会让 DB2 检查使用视图的语句是否满足视图的条件。
下面的语句用 WITH CHECK OPTION 定义一个视图:
CREATE VIEW NONFICTIONBOOKS AS SELECT * FROM BOOKS WHERE BOOKTYPE = 'N' WITH CHECK OPTION |
这个视图仍然限制用户只能看到非小说类的书;另外,它还防止用户插入 BOOKTYPE 列的值不为 N 的行,并防止把现有行中 BOOKTYPE 列的值更新为 N 以外的值。例如,下列语句将不再允许使用:
INSERT INTO NONFICTIONBOOKS VALUES (...,'F'); UPDATE NONFICTIONBOOKS SET BOOKTYPE = 'F' WHERE BOOKID = 111 |
带检查选项的嵌套视图
在定义嵌套视图时,检查选项可以用于限制操作。但是,还可以指定其他子句来定义如何继承限制。检查选项可以定义为 CASCADED 或 LOCAL。如果没有指定关键字,CASCADED 是默认值。为说明 CASCADED 和 LOCAL 行为的不同,我们来看几个可能的场景。
当用 WITH CASCADED CHECK OPTION 创建视图时,所有针对该视图执行的语句都必须满足视图和所有底层视图的条件 —— 即使那些视图不是带检查选项定义的,也是如此。假设在创建 NONFICTIONBOOKS 时没有带检查选项,也可以使用 CASCADED 关键字在视图 NONFICTIONBOOKS 的基础上创建视图 NONFICTIONBOOKS1:
CREATE VIEW NONFICTIONBOOKS AS SELECT * FROM BOOKS WHERE BOOKTYPE = 'N' CREATE VIEW NONFICTIONBOOKS1 AS SELECT * FROM NONFICTIONBOOKS WHERE BOOKID > 100 WITH CASCADED CHECK OPTION |
将不允许下列 INSERT 语句,因为它们不满足其中至少一个视图的条件:
INSERT INTO NONFICTIONBOOKS1 VALUES( 10,..,'N') INSERT INTO NONFICTIONBOOKS1 VALUES(120,..,'F') INSERT INTO NONFICTIONBOOKS1 VALUES( 10,..,'F') |
但是,会 允许下面的 INSERT 语句,因为这两个视图的条件它都满足:
INSERT INTO NONFICTIONBOOKS1 VALUES(120,...,'N') |
接下来,假设用 WITH LOCAL CHECK OPTION 在视图 NONFICTIONBOOKS 的基础上创建视图 NONFICTIONBOOKS2。现在,针对这个视图执行的语句只需要满足指定了检查选项的视图的条件:
CREATE VIEW NONFICTIONBOOKS AS SELECT * FROM BOOKS WHERE BOOKTYPE = 'N' CREATE VIEW NONFICTIONBOOKS2 AS SELECT * FROM NONFICTIONBOOKS WHERE BOOKID > 100 WITH LOCAL CHECK OPTION |
在这种情况下,将不允许下面的 INSERT 语句,因为它们不满足 NONFICTIONBOOKS2 视图的 BOOKID > 100 这个条件:
INSERT INTO NONFICTIONBOOKS2 VALUES(10,..,'N') INSERT INTO NONFICTIONBOOKS2 VALUES(10,..,'F') |
但是,尽管值 N 不满足 NONFICTIONBOOKS 视图的 BOOKTYPE = 'N' 这个条件,也会允许下面的 INSERT 语句:
INSERT INTO NONFICTIONBOOKS2 VALUES(120,..,'N') INSERT INTO NONFICTIONBOOKS2 VALUES(120,..,'F') |
索引
索引 是表的一个或多个列的键值的有序列表。创建索引的原因有两个:
· 确保一个或多个列中值的惟一性。
· 提高表查询的性能。DB2 优化器使用索引提高执行查询时的性能,或者以索引的顺序显示查询结果。
索引可以定义为惟一的或非惟一的。非惟一的 索引允许重复的键值;惟一的 索引只允许一个键值在列表中出现一次。惟一的索引允许出现单个空值。然而,第二个空值会导致重复现象,因此不允许。
索引是使用 CREATE INDEX SQL 语句创建的。为支持 PRIMARY KEY 或 UNIQUE 约束,还会隐式地创建索引。当创建惟一索引时,会检查键数据的惟一性,如果发现重复的键数据则该操作失败。
索引可以创建为升序、降序或双向。选择哪个选项取决于应用程序如何访问数据。
创建索引
在示例中,BOOKID 列上有一个主键。用户常常是搜索书的标题,所以在 BOOKNAME 上建立索引比较合适。下面这个语句在 BOOKNAME 列上创建一个非惟一的升序索引:
CREATE INDEX IBOOKNAME ON BOOKS (BOOKNAME) |
索引名 IBOOKNAME 用于创建和删除这个索引。除此之外,在查询或更新表时不使用该名称。
在默认情况下,索引按升序创建,但也可以创建降序索引。甚至可以为索引中的各个列指定不同的顺序。下面的语句在 AUTHORID 和 BOOKNAME 列上定义一个索引。AUTHORID 列的值按降序排序,在同一个 AUTHORID 值中 BOOKNAME 列的值按升序排序:
CREATE INDEX I2BOOKNAME ON BOOKS (AUTHOID DESC, BOOKNAME ASC) |
在数据库中创建索引时,按照指定的顺序存储键。索引要求数据处于指定的顺序,从而帮助提高查询的性能。升序索引还用于确定 MIN 列函数的结果;降序索引用于确定 MAX 列函数的结果。如果应用程序还需要数据按与索引相反的顺序排序,那么 DB2 允许创建双向索引。双向 索引使您不必创建逆向索引,而且它使优化器不需要按逆向对数据进行排序。它还允许高效地获得 MIN 和 MAX 函数值。要创建双向索引,应该在 CREATE INDEX 语句中指定 ALLOW REVERSE SCANS 选项:
CREATE INDEX BIBOOKNAME ON BOOKS (BOOKNAME) ALLOW REVERSE SCANS |
DB2 不允许创建具有相同定义的多个索引。即使对于为支持主键或惟一性约束而隐式创建的索引,这一点也适用。所以,既然 BOOKS 表已经有了一个在 BOOKID 列上定义的主键,那么尝试在 BOOKID 列上创建索引将失败。
创建一个索引花费的时间比较长。DB2 必须读取每一行来提取键,对这些键进行排序,然后将键值列表写到数据库中。如果表比较大,那么将使用临时表空间对键进行排序。
索引存储在表空间中。如果表驻留在数据库管理的表空间中,就可以选择将索引放在不同的表空间中。在创建表时,使用 INDEXES IN 子句定义这一点。表索引的位置在创建表时设置,除非删除并重新创建表,否则无法改变索引的位置。
DB2 还提供了 DROP INDEX SQL 语句从数据库中删除索引。索引是无法修改的。如果需要更改索引,例如向键中添加另一个列,必须删除并重新创建该索引。
聚集索引
在每个表上,可以将一个索引创建为聚集索引。如果常常以某一次序引用表数据,那么聚集索引比较有用。聚集索引(clustering index) 定义数据在数据库中存储的次序。在插入期间,DB2 会试图将新的行放置得靠近有相似键的行。这样的话,在查询以聚集索引序列请求数据期间,可以更快地检索数据。
要将索引创建为聚集索引,应该在 CREATE INDEX 语句上指定 CLUSTER 子句:
CREATE INDEX IAUTHBKNAME ON BOOKS (AUTHORID,BOOKNAME) CLUSTER |
这个语句在 AUTHORID 和 BOOKNAME 列上创建一个索引,并将其作为聚集索引。如果编写的查询要求列出作者及其所写的所有书籍,这个索引会提高查询的性能。
在索引中使用包含的列
在创建索引时,可以选择包含额外的列数据,这些额外的列数据将与键存储在一起,但实际上它们不是键本身的一部分,所以不被排序。在索引中包含额外列的主要原因是为了提高某些查询的性能:因为索引页面中已经提供了数据值,DB2 就不需要访问数据页面。只能为惟一索引定义包含的列。但是,在强制实施索引的惟一性时不考虑包含的列。
假设我们经常需要获得按 BOOKID 排序的书名列表。查询将如下所示:
SELECT BOOKID,BOOKNAME FROM BOOK ORDER BY BOOKID |
下面的语句会创建一个可能提高性能的索引:
CREATE UNIQUE INDEX IBOOKID ON BOOKS (BOOKID) INCLUDE(BOOKNAME) |
这样的话,查询结果所需的所有数据都出现在索引中,不需要检索数据页面。
那么,为什么不干脆在索引中包括所有的数据?首先,这需要占用数据库中更多的物理空间,因为本质上表数据与索引中的数据是重复的。其次,每当更新数据值时,数据的所有拷贝都需要更新,在发生许多更新的数据库中,这是一项很大的开销。
应该创建什么索引?
下面是创建索引时应该考虑的一些事项:
· 由于索引是键值的持久性列表,它们要占用数据库空间。所以,创建许多索引就需要数据库中有更多的存储空间。所需的空间量由键列的长度决定。DB2 提供了一个工具帮您估计索引的大小。
· 索引是值的额外副本,所以当表中的数据被更新时,它们也必须被更新。如果表数据经常被更新,就要考虑额外的索引会对更新性能产生什么样的影响。
· 如果在适当的列上定义索引,索引会大大提高查询的性能。
DB2 提供了一个称为 Index Advisor 的工具帮助您确定要定义哪些索引。Index Advisor 允许指定将对表执行的工作负载,然后它将建议要为表创建的索引。
DB2常见的表和视图
[db2inst1@rac1 ~]$ db2 'select * from syscat.tables where owner=user'可以查到
DB2的模式
db2的用户和模式的区别
头一回使用db2,对它的用户管理感到非常奇怪。新建一个用户的时候居然不用输入密码。。后来才知道db2的用户都是操作系统中的用户,口令都是在操作系统中设置的。db2的用户登录验证使用的是操作系统的验证。所以一般都是先建立操作系统用户,但在用户分组的时候可以任意。。db2只是使用了操作系统的验证。而权限的设置都保存在了数据库中。至于在操作系统中的db2admns、db2users这两个组,看下组描述也大概清楚了,他们是给操作系统用的。
db2中有一个“模式”概念,每一个数据表都属于一个模式。每一个模式都属于一个用户。一个用户可以有多个模式。通常每个用户都会有一个默认的模式,模式名和用户名相同。我第一次使用db2的时候出现这么一个问题。。就是新建了一个用户,当新建一个表时,在模式名的列表中却没有出现新建的用户名。解决方法是,用新建的用户连接一下数据库。右键点击“数据库名”,在弹出的菜单中点击“连接”,输入新建的用户名和口令,点击“确定”。然后再新建数据表,这个时候在模式输入框中就会出现新建的用户名了。
为了提供数据库对象(比如表、索引和视图)的逻辑视图,使用一个或多个模式对它们进行分类。模式(schema)
是数据库对象的一个逻辑分类。可以使用相同或不同的模式创建多个数据库对象。例如,在表空间 SYSCATSPACE 中,所有基本系统表和索引都分组在同一个模式
SYSIBM 中。基本编目表和索引的所有视图分组在模式 SYSCAT 或 SYSSTAT 中。