ここでは、Oracle Databaseが各データ型の値を比較する方法について説明します。
大きい値は小さい値よりも大きいとみなされます。すべての負の数は、0(ゼロ)およびすべての正の数より小さいとみなされます。したがって、-1は100より小さく、-100は-1より小さいとみなされます。
浮動小数点値NaN
(非数値)は、その他の数値よりも大きく、NaNとは等しいとみなされます。
後の日付は前の日付よりも大きいとみなされます。たとえば、29-MAR-2005(2005年3月29日)に相当する日付は05-JAN-2006(2006年1月5日)に相当する日付よりも小さく、05-JAN-2006 1:35pm(2006年1月5日午後1時35分)に相当する日付は05-JAN-2005 10:09am(2005年1月5日午前10時9分)に相当する日付よりも大きいとみなされます。
文字値は、2つのメジャーに基づいて比較されます。
バイナリ・ソートまたは言語ソート
空白埋め比較セマンティクスまたは非空白埋め比較セマンティクス
次の項で、2つのメジャーについて説明します。
バイナリ比較または言語比較
デフォルトのバイナリ比較では、Oracleは、データベース・キャラクタ・セット内の文字の数値コードを連結した値に従って文字列を比較します。第1の文字の数値が第2の文字の数値よりも大きい場合、第1の文字は第2の文字よりも大きいとみなされます。Oracleは、空白はどの文字よりも小さいとみなします。これは、ほぼすべてのキャラクタ・セットでいえることです。
7ビットASCII(情報交換用米国標準コード)
EBCDICコード(拡張2進化10進コード)
ISO 8859/1(国際標準化機構)
JEUC日本語拡張UNIX
数値コードのバイナリ順序と、比較する文字の言語順序が一致していない場合は、言語比較が有効です。NLS_SORT
パラメータにBINARY
以外の設定があり、NLS_COMP
パラメータがLINGUISTIC
に設定されている場合は言語比較が使用されます。言語ソートでは、すべてのSQLのソートおよび比較がNLS_SORT
によって指定された言語規則に基づいて行われます。
関連項目: 言語ソートについては、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。 |
空白埋め比較セマンティクスおよび非空白埋め比較セマンティクス
空白埋め比較セマンティクスでは、2つの値の長さが異なる場合、Oracleはまず短い方の値の最後に空白を追加して、2つの値が同じ長さになるようにします。次に、その2つの値を、最初に異なる文字まで1文字ずつ比較します。最初に異なる文字の位置で、大きい方の文字を持つ値の方が大きいとみなされます。2つの値に異なる文字がない場合、その2つの値は等しいとみなされます。この規則では、2つの値の後続空白数のみが異なる場合、その2つの値は等しいとみなされます。Oracleでは、比較する両方の値が、CHAR
データ型、NCHAR
データ型、テキスト・リテラルのいずれかの式の場合、またはUSER
ファンクションの戻り値の場合のみ空白埋め比較セマンティクスを使用します。
非空白埋め比較セマンティクスでは、Oracleは、2つの値を、最初に異なる文字まで1文字ずつ比較します。最初に異なる文字の位置で、大きい方の文字を持つ値の方が大きいとみなされます。長さが異なる2つの値を短い方の値の最後まで比較して、すべて同じ文字だった場合、長い方の値が大きいとみなされます。同じ長さの2つの値に異なる文字がない場合、その2つの値は等しいとみなされます。Oracleでは、比較する片方または両方の値がVARCHAR2
データ型またはNVARCHAR2
データ型の場合、非空白埋め比較セマンティクスを使用します。
これらの異なる比較セマンティクスを使用して2つの文字値を比較した場合、その結果が異なることもあります。次の表に、それぞれの比較セマンティクスを使用して5組の文字を比較した結果を示します。通常、空白埋め比較と非空白埋め比較の結果は同じです。表に示されている最後の比較では、空白埋め比較と非空白埋め比較の違いが明確になっています。
空白埋め比較 | 非空白埋め比較 |
---|---|
'ac' > 'ab' |
'ac' > 'ab' |
'ab' > 'a ' |
'ab' > 'a ' |
'ab' > 'a' |
'ab' > 'a' |
'ab' = 'ab' |
'ab' = 'ab' |
'a ' = 'a' |
'a ' > 'a' |
ASCIIとEBCDICのキャラクタ・セットの一部を表3-8と表3-9に示します。大文字と小文字は同じではありません。キャラクタ・セットの照合順番は、特定の言語の言語順序と一致しない場合があります。
オブジェクト値は、MAP
とORDER
の2つの比較ファンクションのいずれかを使用して比較されます。どちらのファンクションでもオブジェクト型インスタンスは比較されますが、両者は別のものです。これらのファンクションは、他のオブジェクト型と比較するオブジェクト型の一部として指定される必要があります。
Oracleでは、データ型の優先順位によって、暗黙的にデータ型を変換するかどうかを判断します(次の項を参照)。Oracleデータ型の優先順位は、次のとおりです。
日時および期間データ型
BINARY_DOUBLE
BINARY_FLOAT
NUMBER
文字データ型
その他のすべての組込みデータ型
一般に、式には異なるデータ型の値を含めることができません。たとえば、式では10に5を掛けた値に'JAMES'を加えることはできません。ただし、Oracleでは値をあるデータ型から別のデータ型へ変換する場合の、暗黙的な変換と明示的な変換をサポートしています。
次の理由から、暗黙的な変換または自動変換ではなく、明示的な変換を指定することをお薦めします。
明示的なデータ型変換ファンクションを使用すると、SQL文がわかりやすくなります。
暗黙的なデータ型変換(特に列値のデータ型が定数に変換される場合)は、パフォーマンスに悪影響を及ぼす可能性があります。
暗黙的な変換はその変換が行われるコンテキストに依存し、どんな場合でも同様に機能するとはかぎりません。たとえば、日時値からVARCHAR2
型へ値を暗黙的に変換すると、NLS_DATE_FORMAT
パラメータに指定されている値によっては、予期しない年が戻される場合があります。
暗黙的な変換のアルゴリズムは、ソフトウェア・リリースやOracle製品の変更によって変更されることがあります。明示的な変換を指定しておくと、その動作は将来的にも確実になります。
索引式で暗黙的なデータ型変換が発生した場合、その索引が変換前のデータ型に対して定義されているために、Oracle Databaseがその索引を使用しないことがあります。これは、パフォーマンスに悪影響を与えるおそれがあります。
あるデータ型から別のデータ型への変換が意味を持つ場合、Oracle Databaseは値を自動的に変換します。
表3-10に、Oracleの暗黙的な変換のマトリックスについて示します。この表は、変換の方向または変換されるコンテキストにかかわらず、すべての可能な変換を示します。詳細は、表の後の説明を参照してください。
表3-10 暗黙的な型変換のマトリックス
CHAR | VARCHAR2 | NCHAR | NVARCHAR2 | DATE | DATETIME/INTERVAL | NUMBER | BINARY_FLOAT | BINARY_DOUBLE | LONG | RAW | ROWID | CLOB | BLOB | NCLOB | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CHAR |
-- |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
-- |
X |
X |
X |
VARCHAR2 |
X |
-- |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
-- |
X |
NCHAR |
X |
X |
-- |
X |
X |
X |
X |
X |
X |
X |
X |
X |
X |
-- |
X |
NVARCHAR2 |
X |
X |
X |
-- |
X |
X |
X |
X |
X |
X |
X |
X |
X |
-- |
X |
DATE |
X |
X |
X |
X |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
DATETIME/ INTERVAL |
X |
X |
X |
X |
-- |
-- |
-- |
-- |
-- |
X |
-- |
-- |
-- |
-- |
-- |
NUMBER |
X |
X |
X |
X |
-- |
-- |
-- |
X |
X |
-- |
-- |
-- |
-- |
-- |
-- |
BINARY_FLOAT |
X |
X |
X |
X |
-- |
-- |
X |
-- |
X |
-- |
-- |
-- |
-- |
-- |
-- |
BINARY_DOUBLE |
X |
X |
X |
X |
-- |
-- |
X |
X |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
LONG |
X |
X |
X |
X |
-- |
X脚注 1 |
-- |
-- |
-- |
-- |
X |
-- |
X |
-- |
X |
RAW |
X |
X |
X |
X |
-- |
-- |
-- |
-- |
-- |
X |
-- |
-- |
-- |
X |
-- |
ROWID |
-- |
X |
X |
X |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
CLOB |
X |
X |
X |
X |
-- |
-- |
-- |
-- |
-- |
X |
-- |
-- |
-- |
-- |
X |
BLOB |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
X |
-- |
-- |
-- |
-- |
NCLOB |
X |
X |
X |
X |
-- |
-- |
-- |
-- |
-- |
X |
-- |
-- |
X |
-- |
-- |
脚注 1 LONG
をINTERVAL
に直接変換することはできませんが、TO_CHAR
(interval
)を使用して
LONGをVARCHAR2
に変換し、そのVARCHAR2
の値をINTERVAL
に変換できます。
暗黙的なデータ型変換は、次に示す規則によって決まります。
INSERT
およびUPDATE
操作中に、Oracleは変更する列のデータ型に値を変換します。
SELECT
FROM
操作中に、Oracleは列からターゲット変数の型にデータを変換します。
数値を操作する際、Oracleは、通常、最大容量を確保するために精度および位取りを調整します。この場合、このような操作によって変換された数値データ型は、基礎となる表に含まれる数値データ型と異なることがあります。
数値と文字値を比較する場合、Oracleは文字データを数値に変換します。
文字値またはNUMBER
の値と浮動小数点数の値の間では、変換が正確に行われない場合があります。これは、文字型およびNUMBER
では10進精度で数値が示されるのに対し、浮動小数点数では2進精度が使用されているためです。
CLOB
値をVARCHAR2
などの文字データ型に変換する場合、またはBLOB
をRAW
データに変換する場合、変換するデータがターゲットのデータ型より大きいと、データベースはエラーを戻します。
タイムスタンプ値からDATE
値への変換では、タイムスタンプ値の秒の小数部は切り捨てられます。この動作は、タイムスタンプ値の秒の小数部が丸められていた、以前のリリースのOracle Databaseの動作とは異なります。
BINARY_FLOAT
からBINARY_DOUBLE
への変換は正確に行われます。
BINARY_DOUBLE
の値がBINARY_FLOAT
でサポートされている精度のビット数よりも多いビット数を使用している場合、BINARY_DOUBLE
からBINARY_FLOAT
への変換は正確に行われません。
DATE
の値と文字の値を比較する場合、Oracleは文字データをDATE
に変換します。
SQLファンクションまたは演算子に不当なデータ型の引数を指定して使用する場合、Oracleはその引数を正当なデータ型に変換します。
代入を実行する場合、Oracleは等号(=)の右側の値を左側の代入ターゲットのデータ型に変換します。
連結中に、Oracleは非文字データ型をCHAR
またはNCHAR
に変換します。
文字データ型と非文字データ型に対する演算処理および比較中に、Oracleはすべての文字データ型を数値、日付またはROWIDのいずれかの適切なデータ型に変換します。CHAR
/VARCHAR2
とNCHAR
/NVARCHAR2
の演算処理では、OracleはNUMBER
に変換します。
ほとんどのSQL文字ファンクションは、CLOB
をパラメータとして指定できます。また、OracleはCLOB
と文字型間で暗黙的な変換を実行します。このため、CLOB
を使用できないファンクションは、暗黙的な変換を使用してCLOB
を受け入れます。このような場合、Oracleはファンクションが起動される前にCLOB
をCHAR
またはVARCHAR2
に変換します。CLOB
が4000バイトより大きい場合、Oracleは最初の4000バイトのみをCHAR
に変換します。
RAW
またはLONG
RAW
データを文字データとの間で変換する場合、バイナリ・データは16進形式で表され、16進文字1文字ごとに4ビットのRAW
データを表します。詳細は、「RAWデータ型とLONG RAWデータ型」を参照してください。
CHAR
とVARCHAR2
、NCHAR
とNVARCHAR2
の比較では、異なるキャラクタ・セットが必要な場合があります。このような場合のデフォルトの変換の方向は、データベース・キャラクタ・セットから各国語キャラクタ・セットです。表3-11に、異なるキャラクタ・タイプ間での暗黙的な変換の方向を示します。
表3-11 異なるキャラクタ・タイプの変換方向
CHARへ | VARCHAR2へ | NCHARへ | NVARCHAR2へ | |
---|---|---|---|---|
CHARから |
-- |
|
|
|
VARCHAR2から |
|
-- |
|
|
NCHARから |
|
|
-- |
|
NVARCHAR2から |
|
|
|
-- |
コレクションなどのユーザー定義型は暗黙的に変換できないため、CAST
... MULTISET
を使用して明示的に変換する必要があります。
テキスト・リテラルの例 テキスト・リテラル'10'はCHAR
データ型です。次の文のように数式で使用すると暗黙的にNUMBER
データ型に変換されます。
SELECT salary + '10' FROM employees;
文字値および数値の例 条件で文字値とNUMBER
型の値を比較する場合、NUMBER
型の値は文字値に変換されず、文字値が暗黙的にNUMBER
型の値に変換されます。次の文では、'200'が暗黙的に200に変換されます。
SELECT last_name FROM employees WHERE employee_id = '200';
日付の例 次の文では、Oracleがデフォルトの日付書式'DD-MON-YY
'を使用して、'24-JUN-06
'をDATE
値に暗黙的に変換します。
SELECT last_name FROM employees WHERE hire_date = '24-JUN-06';
SQL変換ファンクションを使用すると、データ型の変換を明示的に指定できます。表3-12に、値をあるデータ型から別のデータ型に明示的に変換するSQLファンクションを示します。
Oracleが暗黙的なデータ型変換を行うことができる場合には、LONG
およびLONG
RAW
の値を指定できません。たとえば、ファンクションや演算子を含む式では、LONG
とLONG
RAW
の値を使用できません。LONGデータ型およびLONG
RAW
データ型の制限については、「LONGデータ型」
を参照してください。
表3-12 明示的な型の変換
CHAR、VARCHAR2、NCHAR、NVARCHAR2へ | NUMBERへ | Datetime/Intervalへ | RAWへ | ROWIDへ | LONG、LONG RAWへ | CLOB、NCLOB、BLOBへ | BINARY_FLOATへ | BINARY_DOUBLEへ | |
---|---|---|---|---|---|---|---|---|---|
CHAR、VARCHAR2、NCHAR、NVARCHAR2から |
|
|
|
|
|
|
|
|
|
NUMBERから |
|
|
|
|
|
|
|
|
|
Datetime Intervalから |
|
|
|
|
|
|
|
|
|
RAWから |
|
|
|
|
|
|
|
|
|
ROWIDから |
|
|
|
|
|
|
|
|
|
LONG/LONG RAWから |
|
|
|
|
|
|
|
|
|
CLOB、NCLOB、BLOBから |
|
|
|
|
|
|
|
|
|
CLOB、NCLOB、BLOBから |
|
|
|
|
|
|
|
|
|
BINARY_FLOATから |
|
|
|
|
|
|
|
|
|
BINARY_DOUBLEから |
|
|
|
|
|
|
|
|
|
暗黙的な変換、または書式モデルを指定しない明示的な変換のいずれかによって日時値がテキストに変換される場合、書式モデルはグローバリゼーション・セッション・パラメータの1つによって定義されます。ソースのデータ型に応じて、パラメータ名はNLS_DATE_FORMAT
、NLS_TIMESTAMP_FORMAT
またはNLS_TIMESTAMP_TZ_FORMAT
です。これらのパラメータの値は、クライアント環境で、またはALTER
SESSION
文で指定できます。
書式モデルがセッション・パラメータに依存している場合、明示的な書式モデルが指定されていない変換が動的SQL文のテキストに連結される日時値に適用されると、データベースのセキュリティに悪影響を及ぼす可能性があります。動的SQL文は、実行のためにデータベースに渡される前にそのテキストがフラグメントから連結される文です。動的SQLは、組込みPL/SQLパッケージDBMS_SQL
またはPL/SQL文EXECUTE
IMMEDIATE
に関連付けられる場合が多いですが、動的に構成されたSQLテキストを引数として渡すことができる場所はこれらのみではありません。次に例を示します。
EXECUTE IMMEDIATE
'SELECT last_name FROM employees WHERE hire_date > ''' || start_date || '''';
start_date
のデータ型はDATE
です。
前述の例では、start_date
の値はセッション・パラメータNLS_DATE_FORMAT
で指定された書式モデルを使用してテキストに変換されます。結果は、連結されてSQLテキストになります。日時書式モデルは、単純に二重引用符で囲んだリテラル・テキストで構成できます。したがって、セッションのグローバリゼーション・パラメータを明示的に設定できるすべてのユーザーが、前述の変換で生成されるテキストを決定できます。SQL文がPL/SQLプロシージャによって実行される場合、そのプロシージャはセッション・パラメータによるSQLインジェクションに対して脆弱になります。セッション自体より強い権限である定義者の権限でプロシージャが実行されると、ユーザーは機密データに不正にアクセスすることができます。
関連項目: 他の例およびこのセキュリティ・リスクを回避する場合の推奨事項については、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
注意: このセキュリティ・リスクは、データベースまたはOCI日時ファンクションによってテキストに変換された日時値からSQLテキストを構成する中間層アプリケーションにも該当します。セッションのグローバリゼーション・パラメータがユーザー・プリファレンスから取得される場合、それらのアプリケーションは脆弱になります。 |
数値の暗黙的および明示的な変換でも、変換結果がセッション・パラメータNLS_NUMERIC_CHARACTERS
に依存する場合があるため、類似した問題が発生する可能性があります。このパラメータは、小数点区切り文字および桁区切り文字を定義します。小数点区切りを一重引用符または二重引用符と定義すると、SQLインジェクションが発生する可能性があります。
関連項目:
|