程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> DB2 基礎: 結構化數據類型和類型化表簡介

DB2 基礎: 結構化數據類型和類型化表簡介

編輯:DB2教程

IBM® DB2® Universal Database™ (DB2 UDB) for Linux™、UNIX® 和 Windows® 都支持結構化數據類型。結構化數據類型 是一種用戶定義的數據類型,它包含了一系列的屬性,每一個屬性都有一個數據類型。屬性 是專門用來幫助描述類型實例的特性。例如,如果我們定義了一個稱為 address_t 的結構化類型,那麼 city 可能就是這個結構化類型的一個屬性。結構化類型可以很輕松就將地址這樣的數據用作一個獨立單元或單獨的數據項,無需將每個項(或屬性)存儲到單獨的列中。

最常見的情況是,結構化類型被存儲到數據庫中:

對於一個或多個列中的值,可以使用結構化類型作為數據類型對它們進行定義。(參見 清單 1 和 清單 2。)

對於表(類型化表)中的行,其中的列是根據結構化類型的屬性定義的。在這種情況下,表是用結構化類型創建的,並且您不必在表定義中指定單獨的列。(參見 清單 3。)

結構化數據類型

結構化數據類型可以用作普通表中某一列的類型(清單 1 和清單 2),也可以用作整個表(或視圖)的類型,或者用作另一個結構化類型的屬性(清單 3)。當用作表的類型時,該表就被認為是一個類型化表(清單 3)。

您可以用同樣方式使用結構化類型列創建表,也可以只使用 DB2 內置數據類型創建一個表。在兩種情況下,都必須為表中的每一列分配一個數據類型。如果列是結構化類型列,則需要將結構化類型的名稱指定為其數據類型(清單 1)。

結構化數據類型展示了一個稱為繼承 的行為。結構化類型可以包含 子類型,以及重用其所有屬性並包含自己的特定屬性的其他結構化類型。子類型所繼承的屬性來自哪個類型,該類型就被認為是這個子類型的 超類型。類型層次結構 是基於同一超類型的一組子類型;層次結構中最頂端的超類型被認為是該層次結構的 根類型。

可以使用 CREATE TYPE 語句創建一個結構化類型,並使用 DROP 語句刪除結構化類型。

當您創建結構化類型時,DB2 為類型自動創建一個構造函數,並為類型的屬性創建 mutator 方法和 observer 方法。您可以使用構造函數和 mutator 方法來創建結構化類型的實例,然後將這些實例插入表的列中。

構造函數 和它關聯的結構化類型有相同的名稱。構造函數沒有參數,並且返回的類型實例中的所有屬性都為空。

mutator 方法 是為某個結構化類型(structured type)的每個屬性而存在的。當您在結構化類型的實例上調用一個 mutator 方法並為其相關的屬性指定一個新值時,該方法將返回一個新的實例,這個實例的屬性已經更新為新值。

observer 方法 是為某個結構化類型的每個屬性而存在的。當您在結構化類型的實例上調用 observer 方法並為其相關聯的屬性指定一個新值時,該方法將返回這個實例的一個屬性值。

為了在結構化類型的實例上調用 mutator 或 observer 方法,請使用雙點(..)運算符(清單 1、清單 2 和清單 3)。

類型化表

類型化表是一個使用用戶定義的結構化類型定義的表。類型化表以行的形式存儲結構化類型的實例,在這些行中,類型的每個屬性都存儲在單獨的列中;事實上,結構化類型的屬性的名稱和數據類型變成了類型化表的列的名稱和數據類型。與結構化類型類似,類型化表可以是由單獨的 根表、超表 和 子表 組成的 表層次結構 的一部分。

可以使用 CREATE TABLE 語句創建類型化表,並使用 DROP 語句刪除類型化表。正被刪除的類型化表不能擁有任何子類型。通過在 DROP 語句(DROP TABLE HIERARCHY <root-table-name>)中指定 HIERARCHY 關鍵詞,還可以刪除整個表層次結構。

一個詳細的例子

在該例中,我們將使用 DB2 UDB 附帶的 SAMPLE 數據庫。例子只要求一個數據庫連接來啟動操作,不要求其他任何東西,對此,SAMPLE 數據庫將表現得非常出色。

我們將創建一個有 4 個列的名為 CLIENTS 的表。CLIENT_ID 是系統生成的標識列;CLIENT_LNAME 和 CLIENT_FNAME 分別包含客戶的名和姓,並且 ADDRESS 是類型 Address_t 的結構化類型列。(一個有益的習慣是,使用 '_t'後綴來命名結構化類型,使它們的結構化類型特征變得更明顯。)在試圖創建 CLIENTS 表(清單 1)之前,需要創建這個結構化類型。我們將使用 CREATE TYPE 語句的最簡單形式,只指定 4 個屬性(street、city、province 和 postal_code)以及必需的 MODE DB2_SQL 子句。

為了從表中檢索結構化類型數據,必須有一些將類型轉換成一個標量值,換句話說,這些值的類型必須基於某種內置的 DB2 數據類型。為了完成這個轉換,首先必須創建一個 FROM SQL 轉換函數,然後用 轉換組 將轉換函數聯系起來。

首先,我們將使用 CREATE FUNCTION(SQL Scalar 、Table 或 Row)語句,創建一個名為 ADDRESS_TRANSFORM 的標量轉換函數。在此例中,我們指定了一個 Address_t 類型的名為addr 的輸入參數。並指定該函數返回一個足以保留連接的地址屬性的 VARCHAR(42)。SQL-function-body 由 RETURN 語句組成,在該語句中,結構化類型 Address_t 的實例的地址屬性通過 observer 方法(被'..' 運算符指定的)進行檢索並連接('||'運算符)到單一的字符串來形成一個郵寄地址。

在使用這個轉換函數之前,我們必須使用 CREATE TRANSFORM 語句來聯合帶有組名和類型的 ADDRESS_TRANSFORM 轉換函數。CREATE TRANSFORM 允許將現有的函數用作轉換函數。如果在運行一個引用結構化類型的應用程序時,沒有指定組名,那麼 DB2 就會嘗試使用一個稱為 DB2_PROGRAM 的組名,並假定那就是為結構化類型定義的組名。如果 DB2_PROGRAM 還沒有對結構化類型進行定義,那麼您可以為結構化類型創建組。

我們將發出 CREATE TRANSFORM 語句,指定 Address_t 結構化類型和 DB2_PROGRAM 組名。FROM SQL 子句定義了特定的函數,可以使用該函數將將一個值轉換成表示結構化類型的內置數據類型。WITH FUNCTION 子句指定了轉換函數(在這裡,該函數為 ADDRESS_TRANSFORM)。

現在我們准備把一些值插入 CLIENTS 表中。INSERT 語句的 VALUES 子句包括對 address_t() 的調用,它調用了address_t 結構化類型的構造函數來創建一個所有屬性都設置為空值的某一類型的實例。雙點運算符調用了 mutator 方法來設置每個地址屬性的值。

隨後的查詢指定了 CLIENTS 表中的 ADDRESS 列,從中檢索地址信息,並將其作為連接的郵寄地址。

清單 1. 使用一個結構化數據類型作為普通表中某一列的類型

connect to sample
 
... 
 
create type address_t as (street varchar(12), city varchar(12), province varchar(12), 
 postal_code char(6)) mode db2sql 
create table clients (clIEnt_id integer generated always as identity, 
 client_lname varchar(12), clIEnt_fname varchar(12), address address_t) 
create function address_transform (addr address_t) returns varchar(42) language sql 
 return addr..street || ', ' || addr..city || ', ' || addr..province || 
 ' ' || addr..postal_code 
create transform for address_t db2_program (from sql with function address_transform) 
insert into clients (client_lname, clIEnt_fname, address) values ('Nicholson', 'James', 
 address_t() ..street('20 Indian Rd') ..city('Toronto') ..province('Ontario') 
 ..postal_code('M6T2R1')) 
select client_id, client_fname, client_lname, address from clIEnts 
CLIENT_ID  CLIENT_FNAME CLIENT_LNAME ADDRESS 
----------- ------------ ------------ ------------------------------------------ 
     21 James    Nicholson  20 Indian Rd, Toronto, Ontario M6T2R1 
 1 record(s) selected. 
connect reset 

現在,假設我們想從 CLIENTS 表中檢索一個地址元素(比如說,城市)。為了實現這個目標,我們將調用 observer 方法(使用雙點運算符)獲取 ADDRESS 列中的結構化類型值的城市屬性。(清單 2)。

同樣的,如果想更新城市屬性值,可以調用 UPDATE 語句中的 mutator 方法(清單 2)。

清單 2. 更新普通表的某一列中的一個結構化類型實例

connect to sample
 
... 
 
select client_id, client_lname, address..city as city from clIEnts 
CLIENT_ID  CLIENT_LNAME CITY 
----------- ------------ ------------ 
     21 Nicholson  Toronto 
 1 record(s) selected. 
update clients set address..city = 'Oakville' where clIEnt_id = 21 
select client_id, client_lname, address..city as city from clIEnts 
CLIENT_ID  CLIENT_LNAME CITY 
----------- ------------ ------------ 
     21 Nicholson  Oakville 
 1 record(s) selected. 
connect reset 

為了闡明一個簡單的類型化表層次結構和繼承屬性,我們將創建三個新的結構化類型(清單 3):Emp_t、Salesperson_t 和 Engineer_t。Emp_t 是根類型,並且它的定義恰好包括我們先前創建的 Address_t 結構化類型。REF USING INTEGER 子句指定了 INTEGER 數據類型,將使用這個數據類型表示該結構化類型及其所有子類型的 REFERENCE 類型。反過來,REFERENCE 是一個系統類型,它是任何類型化表的對象標識符的數據類型。(因為類型化表包含其他對象引用的對象,所以每個類型化表都必須像它的第一列那樣擁有一個對象標識符。)

Salesperson_t 和 Engineer_t 是在 Emp_t 之下創建的子類型,Emp_t 是它們的超類型。這些子類型的定義包括不屬於 Emp_t 類型的其他屬性,但那就是這些子類型與它們的超類型的不同之處;屬性是超類型定義的一部分,不過,也可以被其子類型所繼承。

已經創建了所需的結構化類型,現在我們就可以創建基於這些類型(清單 3)的類型化表。小型表層次結構的超表稱為 EMP。在富有想象力的創造中,我們命名了對象標識符列 OID,並指定它的值由用戶生成。插入一個 OID 列的值之後,該值就無法再修改。INHERIT SELECT PRIVILEGES 子句指定,在超表上保留了SELECT 權限的用戶或組都將獲准在新表上擁有同等的權限。

我們現在准備把數據插入到 ENGINEER 和 SALESPERSON 表中。兩個例子中 INSERT 語句的 VALUES 子句包括了對 address_t()的調用,像先前的例子一樣,它為 address_t 結構化類型調用了構造函數,創建了一個所有屬性值都為空的類型實例。雙點運算符調用了 mutator 方法來設置每個地址屬性的值。VALUES 子句還為用戶指定的 OID 列的值包括了一個 casting 函數,因為該值必須強制轉換成目標表的 REFERENCE 類型。默認情況下,casting 函數的名稱和結構化類型的名稱相同(在這裡,這兩個名稱分別是 Engineer_t 和 Salesperson_t)。

針對層次結構中的三個表執行的查詢表明,ENGINEER 和 SALESPERSON 子表已經繼承了其超表(EMP)的列,其中包括對象標識符列(OID)。

清單 3. 類型化表層次結構,演示層次結構

connect to sample
 
... 
 
create type emp_t as (empno integer, lname varchar(12), fname varchar(12), 
deptno char(4), salary decimal(7,2), address address_t) ref using integer mode db2sql 
create type salesperson_t under emp_t as (commission decimal(7,2)) mode db2sql 
create type engineer_t under emp_t as (perf_bonus decimal(7,2), 
 recog_award decimal(7,2)) mode db2sql 
create table emp of emp_t (ref is oid user generated) 
create table salesperson of salesperson_t under emp inherit select privileges 
create table engineer of engineer_t under emp inherit select privileges 
insert into engineer (oid, empno, lname, fname, deptno, salary, 
 perf_bonus, recog_award, address) values (engineer_t(1), 42, 'Kidman', 'Jennifer', 
 'Z004', 65000.00, 4000.00, 2000.00, address_t() ..street('7 Dorval Rd') 
  ..city('Markham') ..province('Ontario') ..postal_code('L6G2R1')) 
insert into salesperson (oid, empno, lname, fname, deptno, salary, commission, address) 
 values (salesperson_t(2), 69, 'Theron', 'MaggIE', 'C012', 49000.00, 15000.00, 
 address_t() ..street('7 River St') ..city('Ottawa') ..province('Ontario') 
  ..postal_code('K9G6R2')) 
select * from emp 
OID     EMPNO    LNAME    FNAME    DEPTNO SALARY  ADDRESS 
----------- ----------- ------------ ------------ ------ --------- -------------------- 
     1     42 Kidman    Jennifer   Z004  65000.00 7 Dorval Rd, Mark... 
     2     69 Theron    MaggIE    C012  49000.00 7 River St, Ottaw... 
 2 record(s) selected. 
select oid, empno, lname, deptno, salary, perf_bonus, recog_award, address from engineer 
OID     EMPNO    LNAME    DEPTNO SALARY  PERF_BONUS RECOG_AWARD ADDRESS 
----------- ----------- ------------ ------ --------- ---------- ----------- ---------- 
     1     42 Kidman    Z004  65000.00  4000.00   2000.00 7 Dorva... 
 1 record(s) selected. 
select oid, empno, lname, deptno, salary, commission, address from salesperson 
OID     EMPNO    LNAME    DEPTNO SALARY  COMMISSION ADDRESS 
----------- ----------- ------------ ------ --------- ---------- ---------------------- 
     2     69 Theron    C012  49000.00  15000.00 7 River St, Ottawa,... 
 1 record(s) selected. 
connect reset 

結束語

我們已經看到,用戶定義的結構化數據類型是表示結構化(非原子的)數據的一種有效方法,這些數據需要作為單獨的數據元素或一個獨立的單元進行處理,這主要取決於應用程序。這個話題很廣泛,並且可能很復雜。本文向您介紹了結構化數據類型、類型層次結構和類型化表的基本概念,這些概念都通過實際例子得以闡明,您可以立刻使用和運行這些例子。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved