この章では、バージョン対応表を使用した有効期間(有効日付)のサポートについて説明します。この章の内容は次のとおりです。
一部のアプリケーションでは、データにその妥当性を示す時間範囲を関連付けて格納する必要があります。つまり、各レコードは、そのレコードに関連付けられている時間範囲内でのみ有効です。
表をバージョン対応にするときに有効期間のサポートを有効化できます。(既存のバージョン対応表に有効期間のサポートを追加することもできます。第3.11項を参照してください。)有効期間のサポートを有効化すると、各行にはその行に関連付けられている有効期間を保持する列が追加されます。セッションの有効期間の範囲を指定すると、Workspace Managerにより問合せと挿入、更新および削除操作でその範囲が確実に正しく反映され、対応されます。有効期間の範囲には、過去または将来の期間を指定でき、過去、現在および将来を含めることができます。
例3-1に、有効期間のサポートの簡単な例を示します。この例では、次の操作を実行しています。
従業員とその給与の表を作成します。
有効期間のサポートを指定して表をバージョン対応にします。これにより、表にWM_VALID
列が自動的に追加されます。
この表に行を挿入します。行ごとに、従業員名、給与および有効期間のサポートを指定します。
セッションの有効期間の範囲を設定します。
従業員1人の新規の給与と有効期間を指定して1行を更新します。
表のバージョニングを無効化します。
例3-1:
この章の他の項で説明する有効期間のサポートの概念および手法を参照してください。
第1章で説明したWorkspace Managerの概念と手法をよく理解していると仮定します。
例3-1 有効期間のサポート
-- Create a very simple employees table (deliberately oversimplified -- for purposes of illustration). CREATE TABLE employees ( name VARCHAR2(16) PRIMARY KEY, salary NUMBER ); -- Version-enable the table. Specify TRUE for valid time support. EXECUTE DBMS_WM.EnableVersioning ('employees', 'VIEW_WO_OVERWRITE', FALSE, TRUE); INSERT INTO employees VALUES( 'Adams', 30000, WMSYS.WM_PERIOD(TO_DATE('01-01-1990', 'MM-DD-YYYY'), TO_DATE('01-01-2005', 'MM-DD-YYYY')) ); INSERT INTO employees VALUES( 'Baxter', 40000, WMSYS.WM_PERIOD(TO_DATE('01-01-2000', 'MM-DD-YYYY'), DBMS_WM.UNTIL_CHANGED) ); INSERT INTO employees VALUES( 'Coleman', 50000, WMSYS.WM_PERIOD(TO_DATE('01-01-2003', 'MM-DD-YYYY'), TO_DATE('12-31-9999', 'MM-DD-YYYY')) ); COMMIT; -- Set valid time period to virtually all time. EXECUTE DBMS_WM.SetValidTime(TO_DATE('01-01-1900', 'MM-DD-YYYY'), TO_DATE('01-01-9999', 'MM-DD-YYYY')); -- Update the salary for an existing employee. Perform "sequenced" update, so -- that existing time-related information is preserved. This results in two rows -- for Baxter. -- First, set valid time to the intended range for Baxter's raise. EXECUTE DBMS_WM.SetValidTime(TO_DATE('01-01-2003', 'MM-DD-YYYY'), DBMS_WM.UNTIL_CHANGED); -- Give Baxter a raise, effective 01-Jan-2003 until changed. UPDATE employees SET salary = 45000 WHERE name = 'Baxter'; -- Disable versioning. By default (keepWMValid parameter value of TRUE), -- the WM_VALID column is kept, with all its data. COMMIT; EXECUTE DBMS_WM.DisableVersioning ('employees');
WM_PERIOD
データ型は、セッションまたは作業領域およびバージョン対応表の行について有効期間の範囲を指定するために使用されます。WM_PERIOD
型の定義は、次のとおりです。
CREATE TYPE WM_PERIOD AS OBJECT ( validFrom TIMESTAMP WITH TIME ZONE, validTill TIMESTAMP WITH TIME ZONE);
validFrom
は範囲の開始日で、validTill
期間は指定した日付の前日までとなります。つまり、有効日付の範囲はvalidFrom
の日付からvalidTill
の日付の前日までとなります。
例3-2では、セッションの有効期間の範囲を2003年1月1日に設定しています。
例3-2 セッションの有効期間を特定の日付に設定する例
EXECUTE DBMS_WM.SetValidTime(TO_DATE('01-01-2003', 'MM-DD-YYYY'), TO_DATE('01-02-2003', 'MM-DD-YYYY'));
例3-3では、2003年1月1日から変更時まで有効な1行を挿入しています。
例3-3 期間の範囲に有効な1行を挿入する例
INSERT INTO employees VALUES( 'Baxter', 40000, WMSYS.WM_PERIOD(TO_DATE('01-01-2003', 'MM-DD-YYYY'), DBMS_WM.UNTIL_CHANGED) );
有効期間サポートを伴う表に作成されたビューに、WM_VALID
型の1列のかわりにTIMEZONE WITH TIMESTAMP
型の2列を使用して有効期間範囲を格納する場合、Workspace Managerシステム・パラメータUSE_SCALAR_TYPES_FOR_VALIDTIME
をON
に設定します。第1.5項を参照してください。
表3-1 に、WM_PERIOD
指定のvalidFrom
およびvalidTill
タイムスタンプに使用できる定数を示します。(Workspace Managerではこれらは定数として使用されますが、関数として実装されます。)
表3-2に、有効期間のサポート専用、または有効期間のサポートに関連するパラメータを持つDBMS_WMサブプログラムを示します。
表3-2 有効期間のサポート用のAPI機能
サブプログラム | 有効期間のサポート |
---|---|
|
|
|
|
|
セッションの有効期間の |
|
セッションの有効期間の |
|
セッションの有効期間を指定の範囲に設定します。このプロシージャは、パラメータを指定せずに(有効期間の範囲を現在の時刻から変更時までに設定して)実行するか、 |
|
現行セッションの有効期間フィルタを削除します。 |
|
現行セッションの有効期間フィルタ(バージョン対応表に適用される時間)を設定します。 |
|
有効期間サポートがある表で、順序付きと順序なしの更新操作、および順序付き削除操作を無効にします。 |
|
有効期間のサポートがある表で、順序付きと順序なしの更新操作、および順序付き削除操作を有効にします。 |
Workspace Managerには、2つの期間パラメータを受け入れる関係チェック演算子と関係集合演算子が用意されており、問合せで有効期間フィルタを適用するために使用できます。
関係チェック演算子は、2つの期間に関係がある場合は整数値1を、関係がない場合は0(ゼロ)を戻します。有効期間のサポート用に次の関係チェック演算子が用意されています。
WM_OVERLAPSは、2つの期間がオーバーラップしているかどうかをチェックします。
WM_CONTAINSは、第1期間に第2期間が含まれているかどうかをチェックします。
WM_MEETSは、第1期間の終了時が第2期間の開始時と一致するかどうかチェックします。
WM_EQUALSは、2つの期間が等しい(開始時と終了時が同じ)かどうかチェックします。
WM_LESSTHANは、第1期間の終了時が第2期間の開始時より前かどうかチェックします。
WM_GREATERTHANは、第1期間の開始時が第2期間の終了時より後かどうかチェックします。
集合演算子は、2つの期間の関係を反映する期間を戻すか、2つの期間に指定の関係がない場合はNULL値を戻します。有効期間のサポート用に次の関係集合演算子が用意されています。
WM_INTERSECTIONは、2つの期間の交差部、すなわち両方の期間に共通する時間の範囲を戻します。
WM_LDIFFは、2つの期間の差異のうち左側(早い方)の部分を戻します。
WM_RDIFFは、2つの期間の差異のうち右側(遅い方)の部分を戻します。
関係チェック演算子は、行のwm_valid.validFrom属性とwm_valid.validTill属性のかわりに使用できます。たとえば、次の2つの問合せは等価で、どちらも1991年1月1日に有効なデータが選択されます。
SELECT * FROM employees e WHERE WM_CONTAINS (e.wm_valid, WMSYS.WM_PERIOD(TO_DATE('01-01-1991', 'MM-DD-YYYY'), TO_DATE('01-02-1991', 'MM-DD-YYYY')) = 1; SELECT * from employees e WHERE e.wm_valid.validFrom <= TO_DATE('01-01-1991', 'MM-DD-YYYY') AND e.wm_valid.validTill > TO_DATE('01-03-1991', 'MM-DD-YYYY');
これ以降は、各演算子の追加情報を説明します。各演算子は、アルファベット順に示します。
WM_CONTAINS演算子は、第1期間に第2期間が含まれているかどうかをチェックします。WM_CONTAINS(p1, p2)
は、期間p1
に期間p2
が含まれている場合にのみ1
を戻し、それ以外の場合は0
(ゼロ)を戻します。
次に例を示します。
WM_CONTAINS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1988', 'MM-DD-YYYY'))) = 1 WM_CONTAINS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY'))) = 0
例3-4では、EMPLOYEES
表のうち1995年1月1日に有効だった行(つまり、WM_VALID
列の値に1995年1月1日の期間が含まれている行)がすべて戻されます。
例3-4 WM_CONTAINS演算子
SELECT * FROM employees e WHERE WM_CONTAINS(e.wm_valid, wm_period(TO_DATE('01-01-1995', 'MM-DD-YYYY'), TO_DATE('01-02-1995', 'MM-DD-YYYY'))) = 1; NAME SALARY ---------------- ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- Adams 30000 WM_PERIOD('01-JAN-1990 12:00:00 -04:00', '01-JAN-2005 12:00:00 -04:00')
WM_EQUALS演算子は、第1期間が第2期間と同じかどうかをチェックします。WM_CONTAINS(p1, p2)
は、期間p1
が期間p2
と等しい場合にのみ1
を戻し、それ以外の場合は0
(ゼロ)を戻します。
次に例を示します。
WM_EQUALS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY'))) = 1 WM_EQUALS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY'))) = 0
例3-5では、EMPLOYEES
表のうち1990年1月1日〜2005年1月1日に有効である行(つまり、WM_VALID
列の値がこの期間と一致する行)がすべて戻されます。
例3-5 WM_EQUALS演算子
SELECT * FROM employees e WHERE WM_EQUALS(e.wm_valid, wm_period(TO_DATE('01-01-1990', 'MM-DD-YYYY'), TO_DATE('01-01-2005', 'MM-DD-YYYY'))) = 1; NAME SALARY ---------------- ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- Adams 30000 WM_PERIOD('01-JAN-1990 12:00:00 -04:00', '01-JAN-2005 12:00:00 -04:00')
WM_GREATERTHAN演算子は、第1期間が第2期間より後に発生するかどうかをチェックします。WM_CONTAINS(p1, p2)
は、期間p1
全体が期間p2
より後の場合にのみ1
を戻し、それ以外の場合は0
(ゼロ)を戻します。
次に例を示します。
WM_GREATERTHAN( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1970', 'MM-DD-YYYY'), TO_DATE('01-01-1980', 'MM-DD-YYYY'))) = 1 WM_GREATERTHAN( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1970', 'MM-DD-YYYY'), TO_DATE('01-01-1981', 'MM-DD-YYYY'))) = 0
例3-6では、EMPLOYEES
表のうち2001年1月1日より後にのみ有効な行(つまり、WM_VALID
列のタイムスタンプがどちらも2001年1月1日より後の行)がすべて戻されます。
例3-6 WM_GREATERTHAN演算子
SELECT * FROM employees e WHERE WM_GREATERTHAN(e.wm_valid, wm_period(TO_DATE('01-01-2001', 'MM-DD-YYYY'), TO_DATE('01-02-2001', 'MM-DD-YYYY'))) = 1; NAME SALARY ---------------- ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- Coleman 50000 WM_PERIOD('01-JAN-2003 12:00:00 -04:00', '31-DEC-9999 12:00:00 -04:00')
WM_INTERSECTION演算子は、2つの期間の交差部、すなわち両方の指定された期間に共通する期間を戻します。WM_INTERSECTION(p1, p2)
は、期間p1
と期間p2
の交差部の期間を戻します。
次の例では、1985年1月1日〜1988年1月1日の期間が戻されます。
WM_INTERSECTION( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1988', 'MM-DD-YYYY')))
次の例では、1985年1月1日〜1990年1月1日の期間が戻されます。
WM_INTERSECTION( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY')))
次の例では、2つの期間の交差部がないためNULL値が戻されます。
WM_INTERSECTION( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1992', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY')))
例3-7では、EMPLOYEES
表の行ごとに、WM_PERIOD
列の値が1995年1月1日の期間と交差する従業員名と期間が戻されます。
例3-7 WM_INTERSECTION演算子
SELECT e.name, WM_INTERSECTION(e.wm_valid, wm_period(TO_DATE('01-01-1995', 'MM-DD-YYYY'), TO_DATE('01-02-1995', 'MM-DD-YYYY'))) FROM employees e; NAME ---------------- WM_INTERSECTION(E.WM_VALID,WM_PERIOD(TO_DATE('01-01-1995','MM-DD- -------------------------------------------------------------------------------- Adams WM_PERIOD('01-JAN-1995 12:00:00 -04:00', '02-JAN-1995 12:00:00 -04:00') Baxter Coleman
例3-7の出力が示すように、1995年1月1日に有効な行を持つのはAdamsのみです。
WM_LDIFF演算子は、2つの期間の差異のうち左側(早い方)の部分を戻します。WM_LDIFF(p1, p2)
は、期間p1
と期間p1
の差異のうち左側の期間を戻します。
次の例では、1980年1月1日〜1985年1月1日の期間が戻されます。
WM_LDIFF( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1988', 'MM-DD-YYYY')))
次の例では、p1.validFrom
がp2.validFrom
より後のため、NULL値が戻されます。
WM_LDIFF( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1975', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY')))
次の例では、p2
がp1
とまったく重複しない(この場合は後である)ためNULL値が戻されます。
WM_LDIFF( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1992', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY')))
例3-8では、EMPLOYEES
表の行ごとに、WM_PERIOD
列の値が1995年1月1日の左側と異なる従業員名と期間が戻されます。
例3-8 WM_LDIFF演算子
SELECT e.name, WM_LDIFF(e.wm_valid, wm_period(TO_DATE('01-01-1995', 'MM-DD-YYYY'), TO_DATE('01-02-1995', 'MM-DD-YYYY'))) FROM employees e; NAME ---------------- WM_LDIFF(E.WM_VALID,WM_PERIOD(TO_DATE('01-01-1995','MM-DD-YYYY'), -------------------------------------------------------------------------------- Adams WM_PERIOD('01-JAN-1990 12:00:00 -04:00', '01-JAN-1995 12:00:00 -04:00') Baxter Coleman
例3-8の出力が示すように、左側の差異期間中に有効な行を持つのはAdamsのみです。
WM_LESSTHAN演算子は、第1期間が第2期間より前に発生するかどうかをチェックします。WM_CONTAINS(p1, p2)
は、期間p1
全体が期間p2
より前の場合にのみ1
を戻し、それ以外の場合は0
(ゼロ)を戻します。
次に例を示します。
WM_LESSTHAN( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1991', 'MM-DD-YYYY'), TO_DATE('01-01-1992', 'MM-DD-YYYY'))) = 1 WM_LESSTHAN( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1989', 'MM-DD-YYYY'), TO_DATE('01-01-1992', 'MM-DD-YYYY'))) = 0
例3-9では、EMPLOYEES
表のうち2010年1月1日より前にのみ有効な行(つまり、WM_VALID
列のタイムスタンプがどちらも2010年1月1日より前の行)がすべて戻されます。
例3-9 WM_LESSTHAN演算子
SELECT * FROM employees e WHERE WM_LESSTHAN(e.wm_valid, wm_period(TO_DATE('01-01-2010', 'MM-DD-YYYY'), TO_DATE('01-02-2010', 'MM-DD-YYYY'))) = 1; NAME SALARY ---------------- ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- Adams 30000 WM_PERIOD('01-JAN-1990 12:00:00 -04:00', '01-JAN-2005 12:00:00 -04:00')
WM_MEETS演算子は、第1期間の終了時が第2期間の開始時かどうかをチェックします。WM_MEETS(p1, p2)
は、p1.validTill = p2.validFrom
の場合にのみ1
を、それ以外の場合は0
(ゼロ)を戻します。
次に例を示します。
WM_MEETS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1990', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY'))) = 1 WM_MEETS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1992', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY'))) = 0
例3-10では、EMPLOYEES
表のうち、有効日付期間の終了タイムスタンプが2005年1月1日〜2006年1月1日の期間開始日と同じである場合(つまり、WM_VALID
.validTillが指定期間の開始日と等しい場合)にのみ有効な行がすべて戻されます。
例3-10 WM_MEETS演算子
SELECT * FROM employees e WHERE WM_MEETS(e.wm_valid, wm_period(TO_DATE('01-01-2005', 'MM-DD-YYYY'), TO_DATE('01-01-2006', 'MM-DD-YYYY'))) = 1; NAME SALARY ---------------- ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- Adams 30000 WM_PERIOD('01-JAN-1990 12:00:00 -04:00', '01-JAN-2005 12:00:00 -04:00')
WM_OVERLAPS演算子は、2つの期間がオーバーラップしているかどうかをチェックします。WM_OVERLAPS(p1, p2)
は、期間p1
と期間p2
がオーバーラップしている場合は1
を戻し、それ以外の場合は0
(ゼロ)を戻します。
次に例を示します。
WM_OVERLAPS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY'))) = 1 WM_OVERLAPS( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1970', 'MM-DD-YYYY'), TO_DATE('01-01-1980', 'MM-DD-YYYY'))) = 0
例3-11では、EMPLOYEES
表のうち、有効日付の範囲が1990年1月1日〜2000年1月1日の期間とオーバーラップしている行がすべて戻されます。
例3-11 WM_OVERLAPS演算子
SELECT * FROM employees e WHERE WM_OVERLAPS(e.wm_valid, wm_period(TO_DATE('01-01-1990', 'MM-DD-YYYY'), TO_DATE('01-01-2000', 'MM-DD-YYYY'))) = 1; NAME SALARY ---------------- ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- Adams 30000 WM_PERIOD('01-JAN-1990 12:00:00 -04:00', '01-JAN-2005 12:00:00 -04:00')
WM_RDIFF演算子は、2つの期間の差異のうち右側(遅い方)の部分を戻します。WM_RDIFF(p1, p2)
は、期間p1
と期間p2
の差異のうち右側の期間を戻します。
次の例では、1988年1月1日〜1990年1月1日の期間が戻されます。
WM_RDIFF( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1988', 'MM-DD-YYYY')))
次の例では、p1.validTill
がp2.validTill
より前のため、NULL値が戻されます。
WM_RDIFF( WM_PERIOD( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DD-YYYY')), WM_PERIOD( TO_DATE('01-01-1975', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DD-YYYY')))
例3-12では、EMPLOYEES
表の行ごとに、WM_PERIOD
列の値が1995年1月1日より後の異なる従業員名と期間が戻されます。
例3-12 WM_RDIFF演算子
SELECT e.name, WM_RDIFF(e.wm_valid, wm_period(TO_DATE('01-01-1995', 'MM-DD-YYYY'), TO_DATE('01-02-1995', 'MM-DD-YYYY'))) FROM employees e; NAME ---------------- WM_RDIFF(E.WM_VALID,WM_PERIOD(TO_DATE('01-01-1995','MM-DD-YYYY'), -------------------------------------------------------------------------------- Adams WM_PERIOD('02-JAN-1995 12:00:00 -04:00', '01-JAN-2005 12:00:00 -04:00') Baxter Coleman WM_PERIOD('01-JAN-2003 12:00:00 -04:00', '31-DEC-9999 12:00:00 -04:00')
例3-12の出力が示すように、右側の差異期間中に有効な行を持つのはAdamsとColemanのみです。
この項では、有効期間サポートに関連する問合せおよびデータ操作言語(挿入、更新および削除)操作の動作と考慮事項について説明します。
有効期間サポートを伴うバージョン対応表に対して発行される問合せすべてで、現行のセッションの有効期間設定(SetValidTimeプロシージャまたはSetValidTimeFilterONプロシージャを使用して設定)が考慮されます。問合せで別に指定(たとえば、第3.5項で説明した有効期間サポート演算子の1つを使用して)しないかぎり、各問合せでは、基礎となる表のうち有効期間の範囲がセッションの有効期間または有効期間フィルタとオーバーラップしている行と、問合せのその他の条件を満たす行がすべて表示されます。
デフォルトでは(つまり、セッションでSetValidTimeプロシージャをコールしていない場合、またはパラメータを指定せずにコールした場合)、現時点で有効なすべての行が有効であるとみなされ、現時点から後が制限なしで有効期間とみなされます。
有効期間サポートを伴うバージョン対応表に対して発行されたDML文(INSERT、UPDATEおよびDELETE)では、いずれも現行のセッションの有効期間設定および更新モードが考慮されます。(更新モードは、SetWMValidUpdateModeONプロシージャおよびSetWMValidUpdateModeOFFプロシージャによって制御されます。)DML文は、有効期間中に有効な行すべてに影響を与えることができます。
デフォルトでは(つまり、セッションでSetValidTimeプロシージャをコールしていない場合、またはパラメータを指定せずにコールした場合)、現時点で有効なすべての行をDML文で操作でき、変更後のすべての行では有効期間範囲のタイムスタンプが現時点から変更時までとして設定されます。
以降の各項では、特定タイプのDML操作に適用される付加的な考慮事項について説明します。
有効期間サポートを伴うバージョン対応表の更新操作は、順序付けしても順序付けしなくてもかまいません。
順序付き更新操作が発生するのは、UPDATE文でWM_VALID
列の変更を指定しない場合です。順序付き更新操作の場合、行のWM_VALID.ValidTill
値は現行セッションの有効期間範囲のValidFrom
タイムスタンプに変更され、新規の行が作成されて、そのWM_VALID
期間に現行セッションの有効期間範囲が反映されます。順序付き更新では、WM_VALID
列の値が異なるため、UPDATE文により重複レコードが作成されないことが保証されます。
例3-13に、順序付き更新操作を示します。この操作では、従業員Baxterが昇給しています。更新前には、Baxterに関して給与40000、2000年1月1日〜変更時までの有効期間に設定された1行があります。
例3-13 順序付き更新操作
-- Update the salary for an existing employee. Perform "sequenced" update, so -- that existing time-related information is preserved. This results in two rows -- for Baxter. -- First, set valid time to the intended range for Baxter's raise. EXECUTE DBMS_WM.SetValidTime(TO_DATE('01-01-2003', 'MM-DD-YYYY'), DBMS_WM.UNTIL_CHANGED); -- Give Baxter a raise, effective 01-Jan-2003 until changed. UPDATE employees SET salary = 45000 WHERE name = 'Baxter';
例3-13の更新操作では、次の文に示すように、既存の行のWM_VALID
値が変更され、新規の給与値とセッションの有効期間範囲を反映するWM_VALID
値を使用して新規の行が作成されます。
-- Set valid time to encompass virtually all time. EXECUTE DBMS_WM.SetValidTime(TO_DATE('01-01-1900', 'MM-DD-YYYY'), TO_DATE('01-02-9999', 'MM-DD-YYYY')); -- See what data exists for Baxter. SELECT * FROM employees WHERE name = 'Baxter'; NAME SALARY ---------------- ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- Baxter 45000 WM_PERIOD('01-JAN-2003 12:00:00 -04:00', NULL) Baxter 40000 WM_PERIOD('01-JAN-2000 12:00:00 -04:00', '01-JAN-2003 12:00:00 -04:00')
順序付き削除操作では、セッションの有効期間範囲内にある行の一部が削除されます。つまり、現行セッションの有効期間範囲が反映されたWM_VALID
期間に新しい行が作成され、その後でその行が削除されます。例3-13で、UPDATE文がDELETE FROM employees WHERE name = 'Baxter';
である場合、2003年1月1日から変更時まで有効なBaxterの新しい行は削除されますが、2003年1月1日以前に有効なBaxterのすべての行は影響を受けません。順序なし削除操作の用途は自由です。たとえば、例3-13で有効期間が設定されていない場合、削除操作WHERE name = 'Baxter'
によってBaxterのすべての行が削除されます。
有効期間サポートを伴うバージョン対応表の場合、またはバージョン対応表に有効期間サポートが追加された場合、順序付き更新および削除操作が有効になります。ただし、SetWMValidUpdateModeOFFプロシージャを使用すると、順序付きと順序なしの更新操作、および順序付き削除操作のサポートを無効にできます。また、SetWMValidUpdateModeONプロシージャを使用すると、これらのサポートを再度有効にできます。(これらのプロシージャについては、第4章を参照してください。)
順序なし更新操作が発生するのは、UPDATE文でWM_VALID
列の変更を指定した場合です。順序なし更新操作では、行は追加作成されず、更新後の行のWM_VALID
列の値にはUPDATE文に指定した値が反映されます。順序なし更新操作の結果、同じ主キー値を持つ複数の行がUPDATE文に指定した期間中に有効にならないことを確認する必要があります。これを確認しないと、主キー制約違反のため更新に失敗します。
例3-13のUPDATE文は順序なし更新操作だったため、実行結果はBaxterに関する行が1行のみとなっています。既存の行の給与は45000に設定され、WM_VALID
列はUPDATE文に指定した期間に設定されます。
有効期間サポートを伴うバージョン対応表に1行を挿入する場合に、その行の有効期間を指定できます。期間にNULLのタイムスタンプを指定すると、セッションの有効期間が使用されます。
有効期間サポートを伴うバージョン対応表に1行が挿入されると、Workspace Managerでは、同じ主キー値を持つ既存の行の有効期間範囲が、新規に挿入された行の有効期間範囲とオーバーラップしていないことが確認されます。このような行が検出されると、例外が発生します。例3-14に、有効期間がオーバーラップしているために主キー制約違反となる挿入操作を示します。
例3-14 期間のオーバーラップが原因で失敗する挿入操作
-- Insert. Should violate primary key constraint, because of overlapping times: -- existing Coleman row is valid from 01-Jan-2003 until 31-Dec-9999. INSERT INTO employees VALUES( 'Coleman', 55000, WMSYS.WM_PERIOD(TO_DATE('01-01-2004', 'MM-DD-YYYY'), TO_DATE('12-31-9999', 'MM-DD-YYYY')) ); ) * ERROR at line 6: ORA-20010: unique key violation ORA-06512: at "WM_DEVELOPER.OVM_INSERT_10", line 1 ORA-04088: error during execution of trigger 'WM_DEVELOPER.OVM_INSERT_10'
例3-14に示した文を正常に実行するには、最初にColemanの行のWM_VALID.ValidTill属性を、2004年1月1日以前の日付を反映するタイムスタンプに変更します。
この項では、参照整合性制約と一意制約に影響する有効期間サポートに関連した考慮事項について説明します。
有効期間サポートを伴う2つのバージョン対応表の間に参照整合性制約が存在する場合は、制約の規定時に各行の有効期間が考慮されます。たとえば、DEPARTMENTS
表に、EMPLOYEES
表のEMPLOYEE_ID
列を参照する外部キーであるMANAGER_ID
列が含まれている(つまり、部門マネージャは既存の従業員である必要がある)とします。両方の表が有効期間サポートを伴うバージョン対応表であり、挿入または更新操作により新規のDEPARTMENTS.MANAGER_ID
値が作成されるとします。この場合、DEPARTMENTS.WM_VALID
値が部門マネージャとなる従業員のEMPLOYEES.WM_VALID
値の範囲内になければ、操作は失敗します。(つまり、新規の部門マネージャが挿入または更新操作に対して指定される期間またはデフォルト設定される期間に有効な従業員でなければ、操作は失敗します。)
参照整合性制約に含まれる表の一方または両方が、有効期間サポートを伴うバージョン対応表でない場合、制約の規定時には有効期間が無視されます。
有効期間サポートを伴うバージョン対応表に一意制約が存在する場合は、制約の規定時に各行の有効期間が考慮されます。たとえば、EMPLOYEES
表に一意制約を持つEMPLOYEE_ID
列があるとします。挿入または更新操作の結果、新規のEMPLOYEE_ID
値が既存のEMPLOYEE_ID
値と同じになるとします。この場合、既存の行と挿入される行のWM_VALID
値がオーバーラップしていると、操作は失敗します。(つまり、新規従業員と既存の従業員のID番号が同じで、それぞれの行がどちらも特定時点で有効な場合、操作は失敗します。ただし、2人の従業員の有効期間がオーバーラップしていなければ、操作は成功します。)
有効期間サポートを伴うバージョン対応表の1行がロックされる場合、その行は自動的に有効期間全体を通じてロックされます。指定した期間だけ行をロックする方法はありません。
即時ロックされた作業領域内で更新操作を実行すると、その実行と同時に祖先作業領域から表示されている行がロックされます。祖先作業領域内でロックされている行は、ロックされているかぎり、有効期間中はそれ以上更新できなくなります。
Workspace Managerのロック操作の詳細は、第1.3項を参照してください。
この項では、Workspace Managerの静的データ・ディクショナリ・ビューに対する有効期間サポートの影響について説明します。これらのビューについては、第5章を参照してください。
有効期間サポートを伴うバージョン対応表の場合、xxx_CONFビュー(第5.45項を参照)には、一時的な競合が含まれます。このような競合が発生するのは、親作業領域内で、子作業領域にある行と同じキーを含む行の有効期間が、子作業領域内のその行の有効期間とオーバーラップする場合です。セッション・コンテキストの有効期間を設定しても、時間ディメンション全体について該当する競合がすべて表示されるため、xxx_CONFビューの結果には影響しません。
有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_CONFビューにWM_PERIOD
型のWM_VALID
列が追加されます。このビューには、WM_PERIOD
型のWM_CONFLICTPERIOD
列も追加されます。この列は、競合が検出された行のオーバーラップしている期間を示します。
有効期間サポートを伴うバージョン対応表の場合、xxx_DIFFビュー(第5.46項を参照)には、2つの異なる作業領域またはセーブポイント間の主キーの一時的な差異が含まれます。このような差異が発生するのは、親作業領域または子作業領域内で行が変更(挿入、更新または削除)される場合です。同じ主キー値を持つ2つの行が親作業領域と子作業領域の両方で変更される場合に、各行の有効期間範囲がオーバーラップしていると、2つの行の相関関係はxxx_DIFFビューにのみ表示されます。セッション・コンテキストの有効期間を設定しても、時間ディメンション全体について該当する差異がすべて表示されるため、xxx_DIFFビューの結果には影響しません。
有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_DIFFビューにWM_PERIOD
型のWM_VALID
列が追加されます。このビューには、WM_PERIOD
型のWM_DIFFPERIOD
列も追加されます。この列は、差異が検出された行のオーバーラップしている期間を示します。
xxx_HISTビュー(第5.47項を参照)には、有効期間とトランザクション時間の両方に関する情報が含まれています。また、行を作成したユーザーの名前などの監査情報も含まれます。有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_HISTビューにWM_PERIOD
型のWM_VALID
列が追加されます。
有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_LOCKビュー(第5.48項を参照)にWM_PERIOD
型のWM_VALID
列が追加されます。行は有効期間全体を通じてロックされるため、有効期間がロック期間となります。
有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_MWビュー(第5.49項を参照)にWM_PERIOD
型のWM_VALID
列が追加されます。指定した期間中に有効な行のみを表示するには、WM_OVERLAPS演算子を使用します。
SQL*Loaderユーティリティを使用すると、有効期間サポートを伴うバージョン対応表へのバルク・ロードを実行できます。各行の有効期間を含めることができます。SQL*Loaderデータ・ファイル内で1行の有効期間を指定しなければ、その行がロードされ、WM_VALID
期間は現在の時刻から変更時までの期間に設定されます。
SQL*Loaderユーティリティの使用方法およびリファレンス情報は、『Oracle Databaseユーティリティ』を参照してください。
CommitBulkLoadingプロシージャのvalid_time_update_mode
パラメータを使用すると、ロードする行の有効期間範囲が同じ主キーを持つ既存の行の有効期間範囲とオーバーラップしている場合の処理を指定できます。valid_time_update_mode
パラメータに可能な値は、次のとおりです。
SEQUENCED
: バルク・ロードされる行は、期間範囲がオーバーラップしている既存の行の順序付き更新として扱われます。
NON-SEQENCED
: バルク・ロードされる行は、期間範囲がオーバーラップしている既存の行の順序なし更新として扱われます。
DISCARD
(デフォルト): バルク・ロードされる行は、廃棄表に移動します。
AlterVersionedTableプロシージャを使用すると、既存のバージョン対応表に有効期間サポートを追加できます。既存のすべての行のWM_VALID列に設定する有効期間を指定するか、現在のタイムスタンプから変更時までというデフォルトの期間を受け入れることができます。
例3-15では、MY_TABLE
表を作成し、有効期間サポートなしでバージョン対応にしてから、有効期間サポートを追加しています。有効期間サポートを追加した後のWM_VALID
列には、デフォルトの有効期間が含まれます。
例3-15 既存のバージョン対応表に対する有効期間サポートの追加
CREATE TABLE my_table (id NUMBER PRIMARY KEY); EXECUTE DBMS_WM.EnableVersioning ('my_table'); INSERT INTO my_table VALUES (1); SELECT * FROM my_table; ID ---------- 1 EXECUTE DBMS_WM.AlterVersionedTable('my_table', 'ADD_VALID_TIME'); SELECT * FROM my_table; ID ---------- WM_VALID(VALIDFROM, VALIDTILL) -------------------------------------------------------------------------------- 1 WM_PERIOD('09-JUN-2003 10:04:13 -04:00', NULL)