PL/SQLの定数、変数、パラメータ、ファンクションの戻り値はすべて、記憶形式および有効な値と演算を決定するデータ型を持っています。
この章では、スカラー・データ型という、内部コンポーネントのない値を格納するデータ型について説明します。コンポジット・データ型の詳細は、第5章「PL/SQLのコレクションおよびレコード」を参照してください。
スカラー・データ型にはサブタイプを持たせることができます。サブタイプとは、別のデータ型のサブセットとなるデータ型のことで、その別のデータ型は、そのサブタイプのベース型となります。サブタイプには、そのベース型で有効な演算と同じ演算が含まれています。データ型とそのサブタイプでデータ型ファミリが構成されます。
PL/SQLには、多くの型やサブタイプがパッケージSTANDARDに事前定義されています。また、PL/SQLを使用して、独自のサブタイプを定義することもできます。
PL/SQLのスカラー・データ型は次のとおりです。
SQLデータ型
BOOLEAN
PLS_INTEGER
BINARY_INTEGER
REF CURSOR(「カーソル変数」を参照)
ユーザー定義のサブタイプ
ここでのトピック
|
関連項目:
|
PL/SQLデータ型にはSQLデータ型が含まれます。SQLデータ型の詳細は、『Oracle Database SQL言語リファレンス』を参照してください(記載されているデータ型およびサブタイプ、データ型の比較のルール、データ変換、リテラル、および書式モデルに関する情報はすべて、次の項目を除き、SQLとPL/SQLの両方に適用されます)。
SQLとは異なり、PL/SQLでは変数を宣言できます。変数には次のトピックが適用されます。
表3-1にリストしたSQLのデータ型は、PL/SQLとSQLで最大サイズが異なります。
表3-1 PL/SQLとSQLで最大サイズが異なるデータ型
| データ型 | PL/SQLでの最大サイズ | SQLでの最大サイズ |
|---|---|---|
|
|
32,767バイト |
2000バイト |
|
|
32,767バイト |
2000バイト |
|
|
32,767バイト |
2000バイト |
|
|
32,767バイト |
4000バイト |
|
|
32,767バイト |
4000バイト |
|
|
32,760バイト |
2ギガバイト(GB)- 1 |
|
|
32,760バイト |
2GB |
|
|
128テラバイト(TB) |
(4GB - 1) * |
|
|
128TB |
(4GB - 1) * |
|
|
128TB |
(4GB - 1) * |
1 このデータ型の値の最大サイズをPL/SQLで指定する場合は、定数または変数ではなく、1から32,767の間の値を持つ整数リテラルを使用します。
2既存のアプリケーションとの下位互換性のためにのみサポートされています。
SQLデータ型のBINARY_FLOATおよびBINARY_DOUBLEは、それぞれ単精度および倍精度のIEEE 754形式の浮動小数点数を表します。
BINARY_FLOATおよびBINARY_DOUBLEの計算では、例外は発生しないため、これらの計算によって生成された値がオーバーフローやアンダーフローなどの状態になっていないかどうか、事前定義の定数と比較して確認する必要があります(例は、『Oracle Database SQL言語リファレンス』を参照してください)。PL/SQLには、この型の定数がSQLよりも多数あります。
表3-2に、BINARY_FLOATおよびBINARY_DOUBLEとして事前定義されているPL/SQL定数を示します。SQLでも定義されているものには注を付けてあります。
表3-2 事前定義のPL/SQLのBINARY_FLOATおよびBINARY_DOUBLEの定数 1
| 定数 | 説明 |
|---|---|
|
|
条件 |
|
|
単精度の正の無限大。 |
|
|
最大正規 |
|
|
最小正規 |
|
|
最大非正規 |
|
|
最小非正規 |
|
|
条件 |
|
|
倍精度の正の無限大。 |
|
|
最大正規 |
|
|
最小正規 |
|
|
最大非正規 |
|
|
最小非正規 |
1 この定数はSQLでも事前定義されています。
PL/SQLでは、次のサブタイプが事前定義されています。
各サブタイプはそのベース型と同じ範囲を取り、NOT NULL制約(「NOT NULL制約」を参照)を含んでいます。
値NULLを取らないとわかっている変数は、BINARY_FLOATまたはBINARY_DOUBLEではなく、SIMPLE_FLOATまたはSIMPLE_DOUBLEとして宣言します。これらのサブタイプを使用すると、NULLかどうかのチェックのためのオーバーヘッドが発生せず、そのベース型を使用するよりパフォーマンスが大幅に向上します。PLSQL_CODE_TYPE='INTERPRETED'よりもPLSQL_CODE_TYPE='NATIVE'を使用する方が、パフォーマンスの向上幅が大きくなります(詳細は、「ハードウェア算術を使用するデータ型の使用」を参照してください)。
文字変数に変数の最大サイズより長い値を代入すると、エラーが発生します。次に例を示します。
DECLARE c VARCHAR2(3 CHAR); BEGIN c := 'abc '; END; /
結果:
DECLARE * ERROR at line 1: ORA-06502: PL/SQL: numeric or value error: character string buffer too small ORA-06512: at line 4
同様に、列に挿入した文字変数の値が、定義されている列幅より長い場合も、エラーが発生します。次に例を示します。
DROP TABLE t; CREATE TABLE t (c CHAR(3 CHAR)); DECLARE s VARCHAR2(5 CHAR) := 'abc '; BEGIN INSERT INTO t(c) VALUES(s); END; /
結果:
BEGIN * ERROR at line 1: ORA-12899: value too large for column "HR"."T"."C" (actual: 5, maximum: 3) ORA-06512: at line 4
文字値を変数に代入したり、列に挿入する前に、その文字値から後続する空白を削除するには、RTRIMファンクション(『Oracle Database SQL言語リファレンス』を参照)を使用します。次に例を示します。
DECLARE c VARCHAR2(3 CHAR); BEGIN c := RTRIM('abc '); INSERT INTO t(c) VALUES(RTRIM('abc ')); END; /
結果:
PL/SQL procedure successfully completed.
CHARまたはVARCHAR2変数の最大サイズは、最大サイズを文字数で指定するかバイト数で指定するかに関係なく、32,767バイトです。変数の最大文字数は、キャラクタ・セットのタイプによって、場合によっては文字自体によって異なります。
| キャラクタ・セットのタイプ | 最大文字数 |
|---|---|
| シングルバイト・キャラクタ・セット | 32,767 |
| nバイトの固定幅マルチバイト・キャラクタ・セット(AL16UTF16など) | FLOOR(32,767/n) |
| 文字幅が1とnバイトの間である、nバイトの可変幅マルチバイト・キャラクタ・セット(JA16SJISやAL32UTF8など) | 文字自体によって異なり、32,767(1バイト文字のみを含む文字列の場合)からFLOOR(32,767/n)(nバイト文字のみを含む文字列の場合)を指定できます。 |
任意のマルチバイト・キャラクタ・セットでn個の文字を常に保持できるように、CHARまたはVARCHAR2変数を宣言する場合は、CHAR(n CHAR)またはVARCHAR2(n CHAR)を使用して、文字数の長さを宣言します(nはFLOOR(32767/4) = 8191を超えることはできません)。
|
関連項目: Oracle Databaseのキャラクタ・セットのサポートの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。 |
CHARとVARCHAR2のデータ型は、次の点で異なっています。
CHARデータ型には、PL/SQLとSQLの両方にCHARACTERというサブタイプが1つ事前定義されています。
VARCHAR2データ型には、PL/SQLとSQLの両方にVARCHARというサブタイプが1つ事前定義されており、PL/SQLには、STRINGというサブタイプがもう1つ事前定義されています。
各サブタイプの値の範囲はそのベース型と同じです。
|
注意: PL/SQLの今後のリリースでのVARCHARは、新しいSQL標準に従うために別のデータ型になり、VARCHAR2と同義ではなくなる可能性があります。 |
変数に代入した値がこの変数の最大サイズより短い。
列に挿入した値が、定義されている列幅より短い。
列から取り出して変数に入れた値が、この変数の最大サイズより短い。
受信者のデータ型がCHARの場合、PL/SQLは最大サイズになるまで値を空白で埋めます。元の値の後続する空白に関する情報は失われます。
受信者のデータ型がVARCHAR2の場合、PL/SQLは値の空白埋めも、後続する空白の削除もしません。文字値はそのまま代入され、情報は失われません。
例3-1のCHAR変数とVARCHAR2変数は、どちらも最大サイズが10文字です。それぞれの変数に、1つの空白が後続している5文字の値を代入します。CHAR変数に代入した値は空白が埋められて10文字になり、結果の値に含まれる後続の空白6つのうち、1つは元の値に含まれていたものだとは見分けられません。VARCHAR2変数に代入された値は変化しないため、後続の空白が1つあることを確認できます。
例3-1 CHARおよびVARCHAR2の空白埋めの相違点
DECLARE
first_name CHAR(10 CHAR);
last_name VARCHAR2(10 CHAR);
BEGIN
first_name := 'John ';
last_name := 'Chen ';
DBMS_OUTPUT.PUT_LINE('*' || first_name || '*');
DBMS_OUTPUT.PUT_LINE('*' || last_name || '*');
END;
/
結果:
*John * *Chen *
LONG列には、任意のLONG値を挿入できます。LONG RAW列には、任意のLONG RAW値を挿入できます。LONGまたはLONG RAW列からは、32760バイトを超える長さの値を取り出して、LONGまたはLONG RAW変数に入れることはできません。
LONG列には、任意のCHARまたはVARCHAR2値を挿入できます。LONG列からは、32767バイトを超える長さの値を取り出してCHAR変数またはVARCHAR2変数に入れることはできません。
LONG RAW列には、任意のRAW値を挿入できます。LONG RAW列からは、32767バイトを超える長さの値を取り出してRAW変数に入れることはできません。
ROWIDを取り出してROWID変数に入れる場合は、バイナリ値を文字値に変換するROWIDTOCHARファンクションを使用します。このファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
ROWID変数の値をROWIDに変換するには、CHARTOROWIDファンクション(『Oracle Database SQL言語リファレンス』を参照)を使用します。値が有効なROWIDを表していない場合は、PL/SQLにより事前定義の例外SYS_INVALID_ROWIDが呼び出されます。
ROWIDを取り出してUROWID変数に入れる場合、またはUROWID変数の値をROWIDに変換する場合は、代入文を使用します。変換は暗黙的に実行されます。
|
注意:
|
|
関連項目: DBMS_ROWIDパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。このパッケージのサブプログラムを使用すると、ROWID値に関する情報を作成したり戻すことができます(ただし、UROWID値に関してはできません)。 |
PL/SQLのデータ型BOOLEANには、論理値(ブール値のTRUEとFALSE、およびNULL値)が格納されます。NULLは、不明な値を表します。
BOOLEAN変数を宣言するための構文は、次のとおりです。
variable_name BOOLEAN
BOOLEAN変数に代入できる値はBOOLEAN式のみです。詳細は、「BOOLEAN式」を参照してください。
SQLにはBOOLEANに相当するデータ型がないため、次の操作は実行できません。
データベース表の列にBOOLEAN値を割り当てる操作
データベース表の列の値を選択またはフェッチしてBOOLEAN変数に入れる操作
SQL文、SQLファンクションまたはSQL文から起動されたPL/SQLファンクションでBOOLEAN値を使用する操作
BOOLEAN値は、DBMS_OUTPUT.PUTサブプログラムまたはDBMS_OUTPUT.PUTLINEサブプログラムに渡せません。BOOLEAN値を出力するには、IF文またはCASE文を使用して値を文字値に変換します(これらの文の詳細は、「条件付き選択文」を参照してください)。
例3-2のプロシージャは、BOOLEANパラメータを受け取り、CASE文を使用して、値がNULLならUnknownを、TRUEならYesを、FALSEならNoを出力します。
例3-2 BOOLEAN値の出力
CREATE PROCEDURE print_boolean (b BOOLEAN) AUTHID DEFINER
AS
BEGIN
DBMS_OUTPUT.put_line (
CASE
WHEN b IS NULL THEN 'Unknown'
WHEN b THEN 'Yes'
WHEN NOT b THEN 'No'
END
);
END;
/
BEGIN
print_boolean(TRUE);
print_boolean(FALSE);
print_boolean(NULL);
END;
/
結果:
Yes No Unknown
PL/SQLのデータ型であるPLS_INTEGERとBINARY_INTEGERは同じです。わかりやすくするために、このマニュアルでは、PLS_INTEGERとBINARY_INTEGERの両方を表すためにPLS_INTEGERを使用します。
PLS_INTEGERデータ型は、32ビットで表される-2147483648から2147483647の範囲の符号付き整数を格納します。
PLS_INTEGERデータ型には、NUMBERデータ型およびNUMBERサブタイプと比べて、次のようなメリットがあります。
PLS_INTEGER値の方が、必要な記憶域が少なくなります。
PLS_INTEGER演算はハードウェア算術計算を使用するため、ライブラリ算術計算を使用するNUMBER演算より処理速度が速くなります。
効率のために、PLS_INTEGERの範囲内でのすべての計算にPLS_INTEGER値を使用してください。
ここでのトピック
2つのPLS_INTEGER値を使用する計算がPLS_INTEGERの範囲をオーバーフローした場合は、結果をNUMBERデータ型に代入しても、オーバーフロー例外が発生します(例3-3を参照)。PLS_INTEGERの範囲外の計算には、NUMBERデータ型の事前定義のサブタイプであるINTEGERを使用します(例3-4を参照)。
例3-3 オーバーフロー例外が発生するPLS_INTEGERの計算
DECLARE p1 PLS_INTEGER := 2147483647; p2 PLS_INTEGER := 1; n NUMBER; BEGIN n := p1 + p2; END; /
結果:
DECLARE
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at line 6
例3-4 例3-3のオーバーフローの回避
DECLARE
p1 PLS_INTEGER := 2147483647;
p2 INTEGER := 1;
n NUMBER;
BEGIN
n := p1 + p2;
END;
/
結果:
PL/SQL procedure successfully completed.
表3-3に、PLS_INTEGERデータ型の事前定義のサブタイプ、およびそれらが格納するデータを示します。
表3-3 PLS_INTEGERデータ型の事前定義のサブタイプ
| データ型 | データの説明 |
|---|---|
|
負でない |
|
|
|
|
|
正の |
|
|
|
|
|
-1、0または1の |
|
|
|
|
1 NOT NULL制約の詳細は、「NOT NULL制約」を参照してください。
PLS_INTEGERおよびそのサブタイプは、次のデータ型に暗黙的に変換できます。
CHAR
VARCHAR2
NUMBER
LONG
LONGを除く前述のすべてのデータ型、およびすべてのPLS_INTEGERサブタイプは、PLS_INTEGERに暗黙的に変換できます。
PLS_INTEGER値は、サブタイプの制約に違反していない場合のみ、PLS_INTEGERサブタイプに暗黙的に変換できます。たとえば、PLS_INTEGER値のNULLをSIMPLE_INTEGERサブタイプにキャストすると例外が発生します(例3-5を参照)。
SIMPLE_INTEGERは、PLS_INTEGERデータ型の事前定義されたサブタイプであり、PLS_INTEGERと同じ範囲を取り、NOT NULL制約を含んでいます(「NOT NULL制約」を参照)。PLS_INTEGERとの大きな違いはオーバーフローの方法です。
変数の値がNULLになることがなく、オーバーフロー・チェックも不要であるとわかっている場合は、PLS_INTEGERではなくSIMPLE_INTEGERとして値を宣言します。SIMPLE_INTEGERの場合は、NULLかどうかのチェックおよびオーバーフロー・チェックのためのオーバーヘッドが発生しないため、PLS_INTEGERよりもパフォーマンスが大幅に向上します。
ここでのトピック
式に含まれるすべてのオペランドのデータ型がSIMPLE_INTEGERの場合にのみ、PL/SQLで2の補数算術が使用され、オーバーフローが無視されます。オーバーフローが無視されるため、値を正から負、または負から正にラップできます。次に例を示します。
230 + 230 = 0x40000000 + 0x40000000 = 0x80000000 = -231
-231 + -231 = 0x80000000 + 0x80000000 = 0x00000000 = 0
たとえば、次のブロックはエラーなしで実行されます。
DECLARE
n SIMPLE_INTEGER := 2147483645;
BEGIN
FOR j IN 1..4 LOOP
n := n + 1;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(n, 'S9999999999'));
END LOOP;
FOR j IN 1..4 LOOP
n := n - 1;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(n, 'S9999999999'));
END LOOP;
END;
/
結果:
+2147483646 +2147483647 -2147483648 -2147483647 -2147483648 +2147483647 +2147483646 +2147483645 PL/SQL procedure successfully completed.
SIMPLE_INTEGERと他のオペランドの両方が式に含まれている場合は、PL/SQLによりSIMPLE_INTEGER値がPLS_INTEGER NOT NULLに暗黙的に変換されます。
一部の最適化が抑制されてパフォーマンスに悪影響を与えるような状態でSIMPLE_INTEGER値と他の値が混在している場合は、PL/SQLコンパイラから警告が発行されます。
SIMPLE_INTEGERの範囲内の整数リテラルのデータ型はSIMPLE_INTEGERになります。ただし、算術式内のすべてのオペランドが整数リテラルである場合、PL/SQLでは、下位互換性を確保するために、PLS_INTEGERにキャストされた場合と同様にその整数リテラルが処理されます。
PL/SQLではユーザー独自のサブタイプを定義できます。ベース型は、CHAR、DATEまたはRECORDなどのスカラーまたはユーザー定義のPL/SQLデータ型指定子です(事前に定義したユーザー定義のサブタイプが含まれます)。
サブタイプの役割は次のとおりです。
ANSI/ISOデータ型との互換性の提供
その型のデータ項目の使用意図の提示
範囲外の値の検出
ここでのトピック
無制約のサブタイプには、そのベース型と同じ値セットが含まれているため、ベース型の別名にすぎません。したがって、同じベース型の無制約のサブタイプは互換性があり、そのベース型との互換性もあります。データ型の変換は発生しません。
無制約のサブタイプを定義するには、次の構文を使用します。
SUBTYPE subtype_name IS base_type
subtype_nameおよびbase_typeの詳細は、「subtype_definition」を参照してください。
無制約のサブタイプの例を示します。これは、ANSIとの互換性のためにPL/SQLで事前定義されているものです。
SUBTYPE "DOUBLE PRECISION" IS FLOAT
例3-6の無制約のサブタイプであるBalanceとCounterは、それぞれのタイプのデータ項目の使用意図を示しています。
例3-6 使用意図を示すユーザー定義の無制約のサブタイプ
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制約(「NOT NULL制約」を参照)のみです。
SUBTYPE subtype_name IS base_type [ NOT NULL ]
|
注意: 値の範囲を指定できるベース型は、PLS_INTEGERとそのサブタイム(事前定義とユーザー定義の両方)のみです。 |
例3-7では、制約付きサブタイプBalanceを使用して範囲外の値を検出します。
例3-7 範囲外の値を検出するユーザー定義の制約付きサブタイプ
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: numeric or value error: number precision too large
ORA-06512: at line 9
制約付きサブタイプは暗黙的にベース型に変換されますが、ベース型を制約付きサブタイプに暗黙的に変換できるのは、値がサブタイプの制約に違反していない場合のみです(例3-5を参照)。
制約付きサブタイプは、変換元の値が変換先のサブタイプの制約に違反していない場合のみ、同じベース型を使用する別の制約付きサブタイプに暗黙的に変換できます。
例3-8では、3つの制約付きサブタイプに同じベース型が使用されています。最初の2つのサブタイプは、3番目のサブタイプに暗黙的に変換できますが、相互には変換できません。
例3-8 同じベース型を使用する制約付きサブタイプ間の暗黙的な変換
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: numeric or value error ORA-06512: at line 12
同じデータ型ファミリ内の異なるベース型が2つのサブタイプに使用されている場合は、変換元の値が変換先のサブタイプの制約に違反していない場合のみ、一方から他方へ暗黙的に変換できます。(データ型ファミリでグループ化された事前定義のPL/SQLのデータ型およびサブタイプは、付録E「PL/SQLの事前定義のデータ型」を参照してください。)
例3-9では、サブタイプのWordとTextに、同じデータ型ファミリ内の異なるベース型が使用されています。最初の代入文では、Wordの値が暗黙的にTextに変換されます。2番目の代入文では、Textの値が暗黙的にWordに変換されます。3番目の代入文では、Textの値が長すぎるため、値を暗黙的にWordに変換することができません。
例3-9 同じファミリ内のベース型を使用するサブタイプ間の暗黙的な変換
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; -- 5-character value, 6-character limit verb := sentence3; -- 12-character value, 6-character limit END; /
結果:
DECLARE * ERROR at line 1: ORA-06502: PL/SQL: numeric or value error: character string buffer too small ORA-06512: at line 13