MySQL 8.0 リファレンスマニュアル


12.3 式評価での型変換

演算子が別の型のオペランドとともに使用されると、オペランドの互換性を保つために型変換が発生します。 一部の変換は暗黙的に発生します。 たとえば、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.2.7「日付と時間型間での変換」を参照してください。

JSON 値の比較は 2 つのレベルで行われます。 最初のレベルの比較は、比較された値の JSON 型に基づきます。 タイプが異なる場合、比較結果は優先順位の高いタイプによってのみ決定されます。 2 つの値が同じ JSON 型である場合、2 つ目のレベルの比較は型固有のルールを使用して行われます。 JSON 値と非 JSON 値を比較するために、非 JSON 値は JSON に変換され、値は JSON 値として比較されます。 詳細は、JSON 値の比較および順序付けを参照してください。

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

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 に変換できるさまざまな文字列があるためです。

整数は比較前に倍精度浮動小数点に変換されるため、浮動小数点数と INTEGER 型の大きい値との比較は概算されます。これは、すべての 64 ビット整数を正確に表現できないためです。 たとえば、整数値 2 53+ 1 は float として表現できず、プラットフォームに応じて float 比較の前に 2 53 または 2 53+ 2 に丸められます。

説明するために、次の比較のうち最初の比較では等しい値のみが比較されますが、両方の比較で true (1) が返されます:

mysql> SELECT '9223372036854775807' = 9223372036854775807;
        -> 1
mysql> SELECT '9223372036854775807' = 9223372036854775806;
        -> 1

文字列から浮動小数点への変換および整数から浮動小数点への変換が行われる場合、必ずしも同じように行われるとはかぎりません。 整数は、CPU によって浮動小数点に変換される可能性があります。一方、文字列は、浮動小数点の乗算を伴う演算で 1 桁ずつ変換されます。 また、結果は、コンピュータアーキテクチャ、コンパイラのバージョン、最適化レベルなどの要因の影響を受ける可能性があります。 このような問題を回避する方法の 1 つは、値が暗黙的に浮動小数点値に変換されないように、CAST() を使用することです。

mysql> SELECT CAST('9223372036854775807' AS UNSIGNED) = 9223372036854775806;
        -> 0

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

サーバーには、文字列または DECIMAL の値と概算値 (FLOAT/DOUBLE) の数値との間の変換を改善するための基準を提供する変換ライブラリである dtoa が含まれています:

  • 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 桁よりも大きい場合でも、変換が可逆であるケースもありますが、常に該当するとはかぎりません。

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

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

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

CREATE TABLE t SELECT integer_expr;

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

CREATE TABLE t SELECT 000000000000000000000;

関連キーワード:  関数, 変換, 比較, 整数, 空間, 浮動, 小数点, リファレンス, 精度, 評価