ユーザー定義のPL/SQLサブタイプ

PL/SQLではユーザー独自のサブタイプを定義できます。

ベース型は、CHARDATEまたはRECORDなどのスカラーまたはユーザー定義のPL/SQLデータ型指定子です(事前に定義したユーザー定義のサブタイプが含まれます)。

ノート:

このトピック内の情報は、ユーザー定義のサブタイプおよび「PL/SQLの事前定義のデータ型」にリストされている事前定義のサブタイプの両方に適用されます。

サブタイプの役割は次のとおりです:

  • ANSI/ISOデータ型との互換性の提供

  • その型のデータ項目の使用意図の提示

  • 範囲外の値の検出

ここでのトピック

無制約のサブタイプ

無制約のサブタイプには、そのベース型と同じ値セットが含まれているため、ベース型の別名にすぎません。

したがって、同じベース型の無制約のサブタイプは互換性があり、そのベース型との互換性もあります。データ型の変換は発生しません。

無制約のサブタイプを定義するには、次の構文を使用します。

SUBTYPE subtype_name IS base_type

subtype_nameおよびbase_typeの詳細は、subtypeを参照してください。

無制約のサブタイプの例を示します。これは、ANSIとの互換性のためにPL/SQLで事前定義されているものです。

SUBTYPE "DOUBLE PRECISION" IS FLOAT

例4-24 使用意図を示すユーザー定義の無制約のサブタイプ

この例では、制約なしのサブタイプであるBalanceおよびCounter型それぞれのデータ項目の使用意図を示しています。

DECLARE
  SUBTYPE Balance IS NUMBER;

  checking_account        Balance(6,2);
  savings_account         Balance(8,2);
  certificate_of_deposit  Balance(8,2);
  max_insured  CONSTANT   Balance(8,2) := 250000.00;

  SUBTYPE Counter IS NATURAL;

  accounts     Counter := 1;
  deposits     Counter := 0;
  withdrawals  Counter := 0;
  overdrafts   Counter := 0;

  PROCEDURE deposit (
    account  IN OUT Balance,
    amount   IN     Balance
  ) IS
  BEGIN
    account  := account + amount;
    deposits := deposits + 1;
  END;
  
BEGIN
  NULL;
END;
/

制約付きサブタイプ

制約付きサブタイプには、そのベース型の値のサブセットのみが含まれています。

サイズ、精度と位取り、または値の範囲を指定できるベース型の場合は、そのサブタイプにもこれらを指定できます。次に、サブタイプを定義する構文を示します。

SUBTYPE subtype_name IS base_type
  { precision [, scale ] | RANGE low_value .. high_value } [ NOT NULL ]

この構文を使用しない場合、サブタイプに指定されるのはNOT NULL制約のみです。

SUBTYPE subtype_name IS base_type [ NOT NULL ]

ノート:

値の範囲を指定できるベース型は、PLS_INTEGERとそのサブタイプ(事前定義とユーザー定義の両方)のみです。

制約付きサブタイプは暗黙的にベース型に変換されますが、ベース型を制約付きサブタイプに暗黙的に変換できるのは、値がサブタイプの制約に違反していない場合のみです。

制約付きサブタイプは、変換元の値が変換先のサブタイプの制約に違反していない場合のみ、同じベース型を使用する別の制約付きサブタイプに暗黙的に変換できます。

関連項目:

例4-25 範囲外の値を検出するユーザー定義の制約付きサブタイプ

この例では、制約付きサブタイプBalanceを使用して範囲外の値を検出します。

DECLARE
  SUBTYPE Balance IS NUMBER(8,2);
 
  checking_account  Balance;
  savings_account   Balance;
 
BEGIN
  checking_account := 2000.00;
  savings_account  := 1000000.00;
END;
/

結果:

DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: value or conversion error: number precision too large
ORA-06512: at line 9

例4-26 同じベース型を使用する制約付きサブタイプ間の暗黙的な変換

この例では、3つの制約付きサブタイプに同じベース型が使用されています。最初の2つのサブタイプは、3番目のサブタイプに暗黙的に変換できますが、相互には変換できません。

DECLARE
  SUBTYPE Digit        IS PLS_INTEGER RANGE 0..9;
  SUBTYPE Double_digit IS PLS_INTEGER RANGE 10..99;
  SUBTYPE Under_100    IS PLS_INTEGER RANGE 0..99;
 
  d   Digit        :=  4;
  dd  Double_digit := 35;
  u   Under_100;
BEGIN
  u := d;   -- Succeeds; Under_100 range includes Digit range
  u := dd;  -- Succeeds; Under_100 range includes Double_digit range
  dd := d;  -- Raises error; Double_digit range does not include Digit range
END;
/

結果:

DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: value or conversion error
ORA-06512: at line 12

同じデータ型ファミリ内のベース型を使用したサブタイプ

同じデータ型ファミリ内の異なるベース型が2つのサブタイプに使用されている場合は、変換元の値が変換先のサブタイプの制約に違反していない場合のみ、一方から他方へ暗黙的に変換できます。

データ型ファミリでグループ化された事前定義のPL/SQLのデータ型およびサブタイプは、「PL/SQLの事前定義のデータ型」を参照してください。

例4-27 同じファミリ内のベース型を使用するサブタイプ間の暗黙的な変換

この例では、サブタイプのWordTextに、同じデータ型ファミリ内の異なるベース型が使用されています。最初の代入文では、Wordの値が暗黙的にTextに変換されます。2番目の代入文では、Textの値が暗黙的にWordに変換されます。3番目の代入文では、Textの値が長すぎるため、値を暗黙的にWordに変換することができません。

DECLARE
  SUBTYPE Word IS CHAR(6);
  SUBTYPE Text IS VARCHAR2(15);
 
  verb       Word := 'run';
  sentence1  Text;
  sentence2  Text := 'Hurry!';
  sentence3  Text := 'See Tom run.';
 
BEGIN
  sentence1 := verb;  -- 3-character value, 15-character limit
  verb := sentence2;  -- 6-character value, 6-character limit
  verb := sentence3;  -- 12-character value, 6-character limit
END;
/

結果:

DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: value or conversion error: character string buffer too small
ORA-06512: at line 13