3 Workspace Managerの有効期間のサポート

この章では、バージョン対応表を使用した有効期間(有効日付)のサポートについて説明します。

この章の内容は次のとおりです。

3.1 有効期間のサポート: 概要と例

一部のアプリケーションでは、データにその妥当性を示す時間範囲を関連付けて格納する必要があります。つまり、各レコードは、そのレコードに関連付けられている時間範囲内でのみ有効です。

表をバージョン対応表にする場合は、有効期間のサポートを有効にできます。(「既存の表に対する有効期間サポートの追加」の説明に従って、既存のバージョン対応表に有効期間のサポートを追加することもできます。)有効期間のサポートを有効にすると、各行にはその行に関連付けられている有効期間を保持する列が追加されます。セッションに対して有効期間の範囲を指定することができます。Workspace Managerでは、有効期間の範囲が問合せや挿入、更新および削除操作で適切に反映され適応されます。有効期間の範囲には、過去または将来を指定できます。過去、現在、将来を含めることもできます。

例3-1に、有効期間のサポートの簡単な例を示します。この例では、次の操作を実行しています。

  1. 従業員とその給与の表を作成します。

  2. 有効期間のサポートを指定して表をバージョン対応にします。これにより、表にWM_VALID列が自動的に追加されます。

  3. この表に行を挿入します。行ごとに、従業員名、給与および有効期間のサポートを指定します。

  4. セッションの有効期間の範囲を設定します。

  5. 従業員1人の新規の給与と有効期間を指定して1行を更新します。

  6. 表のバージョニングを無効化します。

例3-1:

例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');

3.2 WM_PERIODデータ型

WM_PERIODデータ型は、セッションまたは作業領域およびバージョン対応表の行について有効期間の範囲を指定するために使用されます。

WM_PERIOD型の定義は、次のとおりです。

CREATE TYPE WM_PERIOD AS OBJECT  (
  validFrom  TIMESTAMP WITH TIME ZONE,
  validTill  TIMESTAMP WITH TIME ZONE,
MAP member function wm_period_map return varchar2);

validFromは範囲の開始日で、validTill期間は指定した日付の前日までとなります。つまり、有効日付の範囲はvalidFromの日付からvalidTillの日付の前日までとなります。

wm_period_mapメンバー・ファンクションにより、WM_PERIOD型の列で順序付け(ソート)とDISTINCTの使用が有効になります。

例3-2 セッションの有効期間を特定の日付に設定する例

例3-2では、セッションの有効期間の範囲を2003年1月1日に設定しています。

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_VALIDTIMEONに設定します。「Workspace Managerのシステム・パラメータ」を参照してください。

3.3 有効期間の定数

次の表に、WM_PERIOD指定のvalidFromタイムスタンプおよびvalidTillタイムスタンプに使用できる定数を示します。

(Workspace Managerではこれらは定数として使用されますが、関数として実装されます。)

表3-1 有効期間のサポートの定数

定数 説明

DBMS_WM.MIN_TIME

Workspace Managerでサポートされる最小(最も古い)タイムスタンプ値。現在は、-4712年(紀元前4712年)1月1日が開始時です。

DBMS_WM.MAX_TIME

Workspace Managerでサポートされる最大(最も新しい)タイムスタンプ値。現在は、9999年12月31日(11:59.999999000 pm)が終了時です。

DBMS_WM.UNTIL_CHANGED

後続の変更により値がオーバーライドされるまでDBMS_WM.MAX_TIMEとして扱われるタイムスタンプ。

3.4 有効期間のサポート用のAPI機能

次の表に、有効期間のサポート専用、または有効期間のサポートに関連するパラメータを持つDBMS_WMサブプログラムを示します。

表3-2 有効期間のサポート用のAPI機能

サブプログラム 有効期間のサポート

EnableVersioning

validTimeパラメータ値がTRUEの場合、表は有効期間のサポートを伴うバージョン対応になります。表にはWM_PERIOD型のWM_VALID列が追加されます。既存の行の場合は、validFromタイムスタンプにSYSTIMESTAMP、validTillタイムスタンプにDBMS_WM.UNTIL_CHANGEDを使用してWM_VALID列が設定されます。

DisableVersioning

keepWMValidパラメータは、表がバージョン非対応の場合に、WM_VALID列とそのデータを保存するか(デフォルト)削除するかを決定します。

GetValidFrom

セッションの有効期間のvalidFromタイムスタンプを戻します。

GetValidTill

セッションの有効期間のvalidTillタイムスタンプを戻します。

SetValidTime

セッションの有効期間を指定の範囲に設定します。このプロシージャは、パラメータを指定せずに(有効期間の範囲を現在の時刻から変更時までに設定して)実行するか、validFromパラメータのみを指定して実行するか、またはvalidFromパラメータおよびvalidTillパラメータの両方を指定して実行できます。

SetValidTimeFilterOFF

現行セッションの有効期間フィルタを削除します。

SetValidTimeFilterON

現行セッションの有効期間フィルタ(バージョン対応表に適用される時間)を設定します。

SetWMValidUpdateModeOFF

有効期間サポートがある表で、順序付きと順序なしの更新操作、および順序付き削除操作を無効にします。

SetWMValidUpdateModeON

有効期間のサポートがある表で、順序付きと順序なしの更新操作、および順序付き削除操作を有効にします。

3.5 有効期間サポートの演算子

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');

これ以降は、各演算子の追加情報を説明します。各演算子は、アルファベット順に示します。

3.5.1 WM_CONTAINS

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')

3.5.2 WM_EQUALS

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') 

3.5.3 WM_GREATERTHAN

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')

3.5.4 WM_INTERSECTION

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のみです。

3.5.5 WM_LDIFF

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.validFromp2.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')))

次の例では、p2p1とまったく重複しない(この場合は後である)ため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のみです。

3.5.6 WM_LESSTHAN

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列のタイムスタンプがどちらも2001年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')

3.5.7 WM_MEETS

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')

3.5.8 WM_OVERLAPS

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') 

3.5.9 WM_RDIFF

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.validTillp2.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のみです。

3.6 有効期間サポートを使用した問合せおよびDML操作

この項では、有効期間サポートに関連する問合せおよびデータ操作言語(挿入、更新および削除)操作の動作と考慮事項について説明します。

3.6.1 問合せ

有効期間サポートを伴うバージョン対応表に対して発行される問合せすべてで、現行のセッションの有効期間設定(SetValidTimeプロシージャまたはSetValidTimeFilterONプロシージャを使用して設定)が考慮されます。問合せで別に指定(たとえば、「有効期間サポートの演算子」で説明した有効期間サポート演算子の1つを使用)しないかぎり、各問合せでは、基礎となる表のうち有効期間の範囲がセッションの有効期間または有効期間フィルタとオーバーラップしている行と、問合せのその他の条件を満たす行がすべて表示されます。

デフォルトでは(つまり、セッションでSetValidTimeプロシージャをコールしていない場合、またはパラメータを指定せずにコールした場合)、現時点で有効なすべての行が有効であるとみなされ、現時点から後が制限なしで有効期間とみなされます。

3.6.2 データ操作言語(DML)操作

有効期間サポートを伴うバージョン対応表に対して発行されるすべてのDML文(INSERT、UPDATEおよびDELETE)では、現行のセッションの有効期間設定および更新モードが考慮されます。(更新モードはSetWMValidUpdateModeONプロシージャおよびSetWMValidUpdateModeOFFプロシージャによって制御されます。)DML文は、有効期間において有効な行すべてに影響する可能性があります。

デフォルトでは(つまり、セッションでSetValidTimeプロシージャをコールしていない場合、またはパラメータを指定せずにコールした場合)、現時点で有効なすべての行をDML文で操作でき、変更後のすべての行では有効期間範囲のタイムスタンプが現時点から変更時までとして設定されます。

以降の各項では、特定タイプのDML操作に適用される付加的な考慮事項について説明します。

3.6.2.1 更新操作

有効期間サポートを伴うバージョン対応表の更新操作は、順序付けしても順序付けしなくてもかまいません。

順序付き更新操作が発生するのは、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プロシージャを使用します。(これらのプロシージャの詳細は、「DBMS_WMパッケージ: リファレンス」を参照してください。)

順序なし更新操作が発生するのは、UPDATE文でWM_VALID列の変更を指定する場合です。順序なし更新操作では、行は追加作成されず、更新後の行のWM_VALID列の値には、UPDATE文に指定した値が反映されます。順序なし更新操作の結果、同じ主キー値を持つ複数の行が、UPDATE文に指定した期間中に有効にならないことを確認する必要があります。これを確認しないと、主キー制約違反が原因で更新に失敗します。

例3-13のUPDATE文は順序なし更新操作だったため、実行結果はBaxterに関する行が1行のみとなっています。既存の行の給与は45000に設定され、WM_VALID列はUPDATE文に指定した期間に設定されます。

3.6.2.2 挿入操作

有効期間サポートを伴うバージョン対応表に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日以前の日付を反映するタイムスタンプに変更します。

3.7 有効期間サポートのための制約管理

この項では、参照整合性制約と一意制約に影響する有効期間サポートに関連した考慮事項について説明します。

3.7.1 参照整合性制約

有効期間サポートを伴う2つのバージョン対応表の間に参照整合性制約が存在する場合は、制約の規定時に各行の有効期間が考慮されます。たとえば、DEPARTMENTS表に、EMPLOYEES表のEMPLOYEE_ID列を参照する外部キーであるMANAGER_ID列が含まれている(つまり、部門マネージャは既存の従業員である必要がある)とします。両方の表が有効期間サポートを伴うバージョン対応表であり、挿入操作または更新操作により新規のDEPARTMENTS.MANAGER_ID値が作成されるとします。この場合、DEPARTMENTS.WM_VALID値が部門マネージャとなる従業員のEMPLOYEES.WM_VALID値の範囲内になければ、操作は失敗します。(つまり、新規の部門マネージャが挿入または更新操作に対して指定される期間またはデフォルト設定される期間に有効な従業員でなければ、操作は失敗します。)

参照整合性制約に含まれる表の一方または両方が、有効期間サポートを伴うバージョン対応表でない場合、制約の規定時には有効期間が無視されます。

3.7.2 一意制約

有効期間サポートを伴うバージョン対応表に一意制約が存在する場合は、制約の適用時に各行の有効期間が考慮されます。たとえば、EMPLOYEES表に一意制約を持つEMPLOYEE_ID列があるとします。挿入または更新操作の結果、新規のEMPLOYEE_ID値が既存のEMPLOYEE_ID値と同じになるとします。この場合、既存の行と挿入される行のWM_VALID値がオーバーラップしていると、操作は失敗します。(つまり、新規従業員と既存の従業員のIDが同じ番号であり、これらの従業員の行が特定時点で有効である場合、操作が失敗します。ただし、2人の従業員の有効期間がオーバーラップしていなければ、操作は成功します。)

3.8 有効期間サポートを使用したロック

有効期間サポートを伴うバージョン対応表の1行がロックされる場合、その行は自動的に有効期間全体を通じてロックされます。指定した期間だけ行をロックする方法はありません。

即時ロックされた作業領域内で更新操作を実行すると、その実行と同時に祖先作業領域から表示されている行がロックされます。祖先作業領域内でロックされている行は、ロックされているかぎり、有効期間中はそれ以上更新できなくなります。

Workspace Managerのロックの詳細は、「Workspace Managerでのロック管理」を参照してください。

3.9 有効期間サポートの影響を受ける静的データ・ディクショナリ・ビュー

この項では、Workspace Managerの静的データ・ディクショナリ・ビューに対する有効期間サポートの影響について説明します。

これらのビューの詳細は、「Workspace Managerの静的データ・ディクショナリ・ビュー」を参照してください。

3.9.1 xxx_CONFビューと有効期間サポート

有効期間サポートを伴うバージョン対応表の場合、xxx_CONFビュー(「xxx_CONFビュー」を参照)には、一時的な競合が含まれます。このような競合が発生するのは、親作業領域内で、子作業領域にある行と同じキーを含む行の有効期間が、子作業領域内のその行の有効期間とオーバーラップする場合です。セッション・コンテキストの有効期間を設定しても、時間ディメンション全体について該当する競合がすべて表示されるため、xxx_CONFビューの結果には影響しません。

有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_CONFビューにWM_PERIOD型のWM_VALID列が追加されます。このビューには、WM_PERIOD型のWM_CONFLICTPERIOD列も追加されます。この列は、競合が検出された行のオーバーラップする期間を示します。

3.9.2 xxx_DIFFビューと有効期間サポート

有効期間サポートを伴うバージョン対応表の場合、xxx_DIFFビュー(「xxx_DIFFビュー」を参照)には、2つの異なる作業領域またはセーブポイント間の主キーの一時的な差異が含まれます。このような差異が発生するのは、親作業領域または子作業領域内で行が変更(挿入、更新または削除)される場合です。同じ主キー値を持つ2つの行が親作業領域と子作業領域の両方で変更される場合に、各行の有効期間範囲がオーバーラップしていると、2つの行の相関関係はxxx_DIFFビューにのみ表示されます。セッション・コンテキストの有効期間を設定しても、時間ディメンション全体について該当する差異がすべて表示されるため、xxx_DIFFビューの結果には影響しません。

有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_DIFFビューにWM_PERIOD型のWM_VALID列が追加されます。このビューには、WM_PERIOD型のWM_DIFFPERIOD列も追加されます。この列は、差異が検出された行のオーバーラップする期間を示します。

3.9.3 xxx_HISTビューと有効期間サポート

xxx_HISTビュー(「xxx_HISTビュー」を参照)には、有効期間とトランザクション時間の両方に関する情報が含まれています。また、行を作成したユーザーの名前などの監査情報も含まれます。有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_HISTビューにWM_PERIOD型のWM_VALID列が追加されます。

3.9.4 xxx_LOCKビューと有効期間サポート

有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_LOCKビュー(「xxx_LOCKビュー」を参照)にWM_PERIOD型のWM_VALID列が追加されます。行は有効期間全体を通じてロックされるため、有効期間がロック期間となります。

3.9.5 xxx_MWビューと有効期間サポート

有効期間サポートを伴うバージョン対応表の場合は、行の有効期間を示すためにxxx_MWビュー(「xxx_MWビュー」を参照)にWM_PERIOD型のWM_VALID列が追加されます。指定した期間中に有効な行のみを表示するには、WM_OVERLAPS演算子を使用します。

3.10 既存の表に対する有効期間サポートの追加

既存のバージョン対応表に有効期間サポートを追加できます。

そのためには、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)

3.11 有効時間のサポートを伴う表の作業領域のマージおよびリフレッシュ

有効期間のサポートを伴う表をマージまたはリフレッシュする場合、同一主キー値を持つ行に交差部分が存在する具体的なケースを検討することで、結果の行を判断できます。

2つの行が交差するかどうかを判断するには、WM_OVERLAPS演算子を使用できます。

表3-3に示すvalidTillのケースでは次のようになります。

  • マージ操作の場合、ターゲット作業領域は親作業領域です。

  • リフレッシュ操作の場合、ターゲット作業領域は、指定された作業領域の子作業領域です。

  • 行の交差の性質上、マージ操作またはリフレッシュ操作の前に競合の解消が行われています。(1つのソース行が複数のターゲット行と競合するか、1つのターゲット行が複数のソース行と競合する可能性があります。)

表3-3 validTillの値とマージ操作またはリフレッシュ操作による交差部分の処理結果

validTill値 交差部分の処理結果

ソース行とターゲット行の両方でvalidTill値がDBMS_WM.UNTIL_CHANGED以外である。

ターゲット作業領域で行の交差部分がソース行の交差部分と同一になるように変更される。

ソース行のvalidTill値がDBMS_WM.UNTIL_CHANGED以外であり、ターゲットの値がDBMS_WM.UNTIL_CHANGEDである。

行の交差部分が変更され、その結果、行のvalidTill値がソース行の値と等しくなる。

ソース行のvalidTill値がDBMS_WM.UNTIL_CHANGEDであり、ターゲット行の値がDBMS_WM.UNTIL_CHANGED以外である。

行の交差部分が変更され、その結果、行のvalidTill値がターゲット行の値と等しくなる。

ソース行とターゲット行の両方のvalidTill値がいずれもDBMS_WM.UNTIL_CHANGEDである。

交差部分が変更され、その結果、行のvalidTill値がDBMS_WM.UNTIL_CHANGEDになる。

表3-3では、いずれのケースでもターゲット行の非交差部分は変更されません。ターゲット作業領域にオーバーラップする行がない場合は、特別な考慮事項はありません。追加の変更は行われず、行がそのままマージまたはリフレッシュされます。