12.2 式評価での型変換

演算子が別の型のオペランドとともに使用されると、オペランドの互換性を保つために型変換が発生します。一部の変換は暗黙的に発生します。たとえば、MySQL では必要に応じて数字が文字列 (またはその逆) に自動的に変換されます。

mysql> SELECT 1+'1';
        -> 2
mysql> SELECT CONCAT(2,' test');
        -> '2 test'

また、CAST() 関数を明示的に使用して、数字を文字列に変換することもできます。CONCAT() 関数では文字列の引数が要求されるため、使用すると暗黙的に変換が発生します。

mysql> SELECT 38.8, CAST(38.8 AS CHAR);
        -> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
        -> 38.8, '38.8'

文字セットの数字から文字列への暗黙的な変換について、および CREATE TABLE ... SELECT ステートメントに適用される変更済みのルールについては、このセクションの後半を参照してください。

次のルールでは、比較演算の際にどのように変換が発生するのかについて説明します。

  • NULL-safe <=> 等価比較演算子の場合を除いて、一方または両方の引数が NULL の場合は、比較の結果も NULL になります。NULL <=> NULL の場合は、結果が true になります。変換は必要ありません。

  • 比較演算の両方の引数が文字列の場合は、文字列として比較されます。

  • 両方の引数が整数の場合は、整数として比較されます。

  • 16 進値が数字と比較されない場合は、バイナリ文字列として処理されます。

  • 引数の一方が TIMESTAMP または DATETIME カラムで他方が定数の場合は、比較が実行される前に定数がタイムスタンプに変換されます。これは、ODBC により適合させるために実行されます。これは、IN() への引数には実行されません。念のため、比較を行う際は、常に完全な日付時間、日付、または時間文字列を使用してください。たとえば、日付または時間の値とともに BETWEEN を使用したときの結果を最適にするには、CAST() を使用して、明示的に値を目的のデータ型に変換します。

    テーブル (複数可) からの単一行のサブクエリーは、定数とみなされません。たとえば、サブクエリーで DATETIME 値と比較される整数が返される場合は、比較が 2 つの整数として実行されます。整数は時間値には変換されません。オペランドを DATETIME 値として比較するには、CAST() を使用して、明示的にサブクエリーの値を DATETIME に変換します。

  • 引数のいずれかが 10 進値の場合、比較はその他の引数に依存します。その他の引数が 10 進値または整数値の場合、引数は 10 進値として比較され、その他の引数が浮動小数点値の場合、引数は浮動小数点値として比較されます。

  • ほかのすべてのケースでは、引数は浮動小数点 (実) 数として比較されます。

別の時間型への値の変換については、セクション11.3.7「日付と時間型間での変換」を参照してください。

次の例は、比較演算での文字列から数字への変換を示しています。

mysql> SELECT 1 > '6x';
        -> 0
mysql> SELECT 7 > '6x';
        -> 1
mysql> SELECT 0 > 'x6';
        -> 0
mysql> SELECT 0 = 'x6';
        -> 1

文字列カラムと数字との比較では、MySQL はカラム上のインデックスを使用して、値をすばやく検索できません。str_col がインデックスの付いた文字列カラムである場合は、次のステートメントで検索を実行するときに、そのインデックスを使用できません。

SELECT * FROM tbl_name WHERE str_col=1;

その理由は、'1'' 1''1a' のように、値 1 に変換できるさまざまな文字列があるためです。

このような数字は不正確であるため、浮動小数点数 (または浮動小数点数に変換される値) を使用する比較は概算になります。これにより、整合性のない結果が表示される可能性があります。

mysql> SELECT '18015376320243458' = 18015376320243458;
        -> 1
mysql> SELECT '18015376320243459' = 18015376320243459;
        -> 0

このような結果は、53 ビットの精度しか持たない浮動小数点数に値が変換され、丸めの対象になるために発生する可能性があります。

mysql> SELECT '18015376320243459'+0.0;
        -> 1.8015376320243e+16

さらに、文字列から浮動小数点への変換および整数から浮動小数点への変換は、必ずしも同様に発生するとはかぎりません。整数は、CPU によって浮動小数点に変換される可能性があります。一方、文字列は、浮動小数点の乗算を伴う演算で 1 桁ずつ変換されます。

表示される結果はシステムによって異なり、コンピュータのアーキテクチャーやコンパイラのバージョンなどの要因、または最適化レベルの影響を受ける可能性があります。このような問題を回避する方法の 1 つは、値が暗黙的に浮動小数点値に変換されないように、CAST() を使用することです。

mysql> SELECT CAST('18015376320243459' AS UNSIGNED) = 18015376320243459;
        -> 1

浮動小数点の比較についての詳細は、セクションB.5.5.8「浮動小数点値に関する問題」を参照してください。

MySQL 5.6 では、サーバーに dtoa が含まれています。これは、文字列または DECIMAL 値と近似値 (FLOAT/DOUBLE) の数値間の変換を改善するための基礎を提供する変換ライブラリです。

  • Unix と Windows 間の変換の相違などが除去された、プラットフォーム間で整合性のある変換結果。

  • 以前の結果に十分な精度がなかった場合 (IEEE の制限に近い値など) の正確な値の表示。

  • 最大限の精度を持つ文字列書式への数字の変換。dtoa の精度は、常に標準の C ライブラリ関数の精度と同じか、それ以上です。

このライブラリで生成された変換は、dtoa 以外の結果とは異なる場合があるため、以前の結果に依存するアプリケーションとの互換性が保たれない可能性があります。たとえば、以前の変換からの特定の正確な結果に依存するアプリケーションでは、追加の精度に対応するように調整が必要となる場合があります。

dtoa ライブラリでは、次のプロパティーを使用した変換が提供されます。DDECIMAL または文字列表現を含む値を表し、F はネイティブバイナリ (IEEE) 書式の浮動小数点数を表します。

  • F -> D の変換は、最大限の精度で実行され、読み取り時に F が生成されるもっとも短い文字列として D が返され、IEEE で指定されているネイティブバイナリ形式でもっとも近い値に丸められます。

  • D -> F の変換は、F が入力された 10 進文字列 D にもっとも近いネイティブバイナリの数字になるように実行されます。

F-inf+inf、または NaN の場合を除いて、これらのプロパティーは、F -> D -> F の変換が可逆であることを暗黙的に示しています。後者の値は、SQL 標準では FLOAT または DOUBLE の無効な値として定義されているため、サポートされていません。

D -> F -> D の変換では、D が 15 桁以下の精度を使用し、非正規値 (-inf+inf、または NaN) でないことが可逆のための十分な条件となります。D の精度が 15 桁よりも大きい場合でも、変換が可逆であるケースもありますが、常に該当するとはかぎりません。

MySQL 5.6 では、暗黙的に数値または時間値を文字列に変換すると、character_set_connection および collation_connection システム変数で決定された文字セットおよび照合順序を含む値が生成されます。(一般に、これらの変数は SET NAMES を使用して設定されます。接続文字セットについては、セクション10.1.4「接続文字セットおよび照合順序」を参照してください。)

つまり、接続文字セットが binary に設定されている場合を除いて、このような変換では、(非バイナリ) 文字列 (CHARVARCHAR、または LONGTEXT 値) が生成されます。この場合、変換の結果はバイナリ文字列 (BINARYVARBINARY、または LONGBLOB 値) になります。

整数式では、式の評価に関する上記の備考は、式の割り当てには多少異なる方法で適用されます。次のようなステートメントでの例を示します。

CREATE TABLE t SELECT integer_expr;

この場合、式の結果として生成されるカラム内のテーブルの型は、整数式の長さに応じて、INT または BIGINT になります。式の最大長が INT に収まらない場合は、代わりに BIGINT が使用されます。長さは、SELECT 結果セットメタデータの max_length 値から取得されます (セクション23.8.5「C API データ構造」を参照してください)。つまり、十分に長い式を使用することで、INT ではなく、BIGINT を強制的に適用できます。

CREATE TABLE t SELECT 000000000000000000000;

User Comments
Sign Up Login You must be logged in to post a comment.