還可以修改表中特定列的特征:
· 列的標識屬性
· 字符串列的長度
· 列的數據類型
· 列的可空性
· 列的約束
對于修改列有一些限制:
· 在修改字符串列的長度時,只能增加長度。
· 在修改列的數據類型時,新的數據類型必須與現有的數據類型兼容。例如,可以將 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 中。