SQL Server のデータ型の優先順位と注意点
SQL Server のデータ型の優先順位と注意点について
SQL Server のデータ型には「優先順位」というものがあります。
そして、それを知っていないとエラーになってしまうような場面もたまにあります。
この記事では、SQL Server のデータ型の優先順位と注意点などをご紹介します。
SQL Server のデータ型の優先順位
SQL Server では、違うデータ型の値を比較したり、演算したりする際には、データ型を暗黙的に変換してそろえてから処理を行います。
暗黙的にデータ変換をする際には、データ型の優先順位に従って、一番優先順位の高いデータ型に変換されます。
SQL Server では、次のデータ型の優先順位が使用されます。
| 優先順位 | データ型 | 
|---|---|
| 1 | ユーザー定義データ型 | 
| 2 | json | 
| 3 | sql_variant | 
| 4 | xml | 
| 5 | datetimeoffset | 
| 6 | datetime2 | 
| 7 | datetime | 
| 8 | smalldatetime | 
| 9 | date | 
| 10 | time | 
| 11 | float | 
| 12 | real | 
| 13 | decimal | 
| 14 | money | 
| 15 | smallmoney | 
| 16 | bigint | 
| 17 | int | 
| 18 | smallint | 
| 19 | tinyint | 
| 20 | bit | 
| 21 | ntext | 
| 22 | text | 
| 23 | image | 
| 24 | timestamp | 
| 25 | uniqueidentifier | 
| 26 | nvarchar | 
| 27 | nchar | 
| 28 | varchar | 
| 29 | char | 
| 30 | varbinary | 
| 31 | binary | 
優先順位の数字が低いほど優先順位が高いという意味で、下のデータ型は自動的に上のデータ型に変換されます。
例えば、INT 型と VARCHAR 型のデータの値を比較する場合は、INT 型の 優先順位が 17 で、VARCHAR 型の優先順位は 28 なので、VARCHAR 型の値が INT 型に変換されます。
それでは、実際に動きを確認してみましょう。
VARCHAR 型と INT 型と DECIMAL 型のデータを LEAST 関数に渡して、一番小さい値を取得してみます。
DECLARE @Value1 VARCHAR(1) = '1',
        @Value2 INT = 2,
        @Value3 DECIMAL(8,2) = 3.0;
SELECT  LEAST(@Value1, @Value2, @Value3) AS LeastValue,
        SQL_VARIANT_PROPERTY(LEAST(@Value1, @Value2, @Value3), 'BaseType') AS ReturnDataType;
[実行結果]
VARCHAR 型と INT 型と DECIMAL 型の中で一番優先順位が高いのは DECIMAL 型です。
VARCHAR 型と INT 型は DECIMAL 型に暗黙的に変換されて比較され、一番小さい 1.0 が戻り値として返っています。
念の為、LEAST 関数の戻り値を LEASTSQL_VARIANT_PROPERTY
関数を使って確認したところ decimal になっているのがわかります。データ型の優先順位に関連する注意点
データ型の優先順位に関連して注意が必要なことがあります。
まずは、暗黙的に一番優先順位の高いデータ型に変換されるような状況で、変換できない値が存在した場合、データ変換でエラーになってしまうという点です。
例えば、最初に NULL ではない値を返す、COALESCE 関数に、次のようなデータ型の違う引数を渡してみます。
COALESCE 関数の戻り値は、入力引数のデータ型の中で一番優先順位が高いデータ型になります。
DECLARE @Value1 BIT,
        @Value2 VARCHAR(1) = 'x',
        @Value3 INT = 3;
SELECT COALESCE(@Value1, @Value2, @Value3);
[実行結果]
入力引数のデータ型は BIT 型、VARCHAR 型、INT 型で、一番優先順位が高いデータ型は INT 型です。
最初に NULL ではない値は VARCHAR 型の @Value2 の 'x' で、'x' が INT 型に変換できないため、エラーになっています。
違ったデータ型を指定できる状況でも、入力引数のデータ型をできる限り同じにすることでエラーになる可能性を回避できます。
また、テーブルのカラム側に暗黙のデータ型変換が行われるようなクエリーを書くと、インデックスが有効に使われない場合があり、パフォーマンスに影響が出る可能性があります。
[例] ... WHERE [INT 型のカラム] > @DecimalValue
その他、DECIMAL 型と FLOAT 型の計算では、FLOAT 型のほうが優先順位が高いため、DECIMAL 型が FLOAT 型に変換されて計算されるので、誤差が発生する可能性があります。
データ型の優先順位と暗黙のデータ型変換に注意して、可能な限り暗黙のデータ変換が行われないようなクエリーを書くことをおすすめします。
以上、SQL Server のデータ型の優先順位と注意点などをご紹介しました。