sql_variant 型のデータの使用

sql_variant データ型の用法は、Microsoft Visual Basic の variant データ型と似ています。sql_variant 型を使用すると、1 つの列、パラメータ、または変数に異なるデータ型のデータ値を格納できるようになります。たとえば、1 つの sql_variant 型の列に、int、decimal、char、binary、および nchar の各型の値を格納できます。sql_variant 型の列の各インスタンスにより、データ値とメタデータ情報が記録されます。この情報には、基本データ型、最大サイズ、小数点以下桁数、有効桁数、および照合順序が含まれます。

sql_variant 型の使用に関する規則

sql_variant データ型を使用するときは、次の規則が適用されます。

通常の値の代入

  • sql_variant 型のオブジェクトには、任意の SQL Server データ型のデータを格納できます。ただし、text、ntext、image、varchar(max)、nvarchar(max)、varbinary(max)、xml、timestamp の各型、および Microsoft .NET Framework 共通言語ランタイム (CLR) ユーザー定義型は除きます。また、sql_variant データのインスタンスが、sql_variant 型を基本データ型にすることはできません。

  • すべての型の定数を、sql_variant 型の列を参照する述語または代入で指定できます。

  • sql_variant 型の値が NULL の場合は、基本データ型がないものと見なされます。この規則は、NULL 値が特定のデータ型を持つ変数または列の値である場合にも適用されます。

    次の例では、NULL 値が int 型の変数の値であっても、VariantCol の値はデータ型を関連付けられていない NULL に設定されます。

    DECLARE @IntVar int

    SET @IntVar = NULL

    UPDATE SomeTable SET VariantCol = @IntVar WHERE PriKey = 123

  • sql_variant 型のオブジェクトから他のデータ型のオブジェクトへの代入では、sql_variant 型の値が代入先のデータ型に明示的にキャストされる必要があります。sql_variant 型の値を別のデータ型のオブジェクトに代入する場合、暗黙的な変換はサポートされません。

  • 他のデータ型との互換性を維持するために、sql_variant 型のオブジェクトの長さを報告するカタログ オブジェクト (DATALENGTH 関数など) により、データの長さが報告されます。sql_variant 型のオブジェクトに格納されたメタデータの長さは返されません。

  • sql_variant 型の列は、常に ANSI_PADDING が ON の状態で動作します。代入元の ANSI_PADDING が OFF の場合に char、nchar、varchar、nvarchar、または varbinary のいずれかの型の値が代入されると、値への埋め込みは行われません。

  • サブスクライバ側で 1 つの列を更新すると、別の sql_variant 列で基本データ型が変更されます。次の手順は、この概念を示しています。

    1. マージされたパブリケーションとサブスクリプションを作成します。パブリッシュされたテーブルに sql_variant 列および c1 列を含める必要があります。sql_variant 列にデータを追加します。データの基本データ型は datetime です。

    2. 初期同期後も、サブスクライバ側の基本データ型は datetime のままです。

    3. サブスクライバで列 c1 を更新します。

    4. パブリッシャ側の sql_variant 列のデータが datetime2 に変更されます。

テーブル内の sql_variant 型

  • sql_variant 型の列は、キー列のデータの長さが 900 バイトを超えない限り、インデックスと一意キーで使用できます。

  • sql_variant 型の列では IDENTITY プロパティがサポートされませんが、主キーまたは外部キーの一部として sql_variant 型の列を使用できます。

  • sql_variant 型の列は、計算列では使用できません。

  • ALTER TABLE を使用して、text、ntext、image、timestamp、sql_variant の各型を除く任意のデータ型の列を sql_variant 型に変更します。既存のすべての値が、ALTER TABLE ステートメントを実行する前の列のデータ型と同じ基本データ型を持つ sql_variant 型の値に変換されます。ALTER TABLE を使用して、sql_variant 型の列のデータ型を他のデータ型に変更することはできません。これは、sql_variant 型から他のデータ型への暗黙的な変換がサポートされていないためです。

照合順序

  • COLLATE 句を使用して、列の照合順序を sql_variant 型の列に割り当てることはできません。sql_variant 型の列の文字ベースの値 (char、nchar、varchar、および nvarchar の各型) の照合順序には、任意の照合順序を指定できます。また、1 つの sql_variant 型の列には、照合順序の異なる文字ベースの値を保持できます。

  • ある値が sql_variant 型のインスタンスに代入されるときは、代入元のデータ値と基本データ型の両方が代入されます。代入元の値に照合順序がある場合は、その照合順序も代入されます。代入元の値にユーザー定義データ型がある場合は、ユーザー定義データ型ではなく、ユーザー定義データ型の基本データ型が代入されます。sql_variant 型のインスタンスでは、ユーザー定義データ型にバインドされた規則または既定値は継承されません。IDENTITY プロパティを持つ列の値が sql_variant 型のインスタンスに代入された場合、sql_variant 型の基本データ型は代入元の列の基本データ型になりますが、IDENTITY プロパティは継承されません。これは、text、ntext、または image のいずれかの型の値を sql_variant 型のインスタンスに代入するときのエラーです。他のデータ型のオブジェクトの値を sql_variant 型のオブジェクトに代入する場合は、暗黙的な変換がサポートされます。

sql_variant 型の比較

sql_variant 型の列には複数の基本データ型と照合順序の値を格納できるため、sql_variant 型のオペランドを比較するときには、特別な規則が適用されます。これらの規則は、次のような比較を行う場合に適用されます。

  • Transact-SQL 比較演算子

  • ORDER BY、GROUP BY

  • インデックス

  • 集約関数 MAX と MIN

  • UNION (ALL 以外)

  • CASE 式

sql_variant 型の比較のために、SQL Server のデータ型階層の順序は、データ型ファミリにグループ化されます。ファミリの優先順位が最も高いのは、sql_variant ファミリです。

データ型階層

データ型ファミリ

sql_variant

sql_variant

datetime

日付と時刻

smalldatetime

日付と時刻

Float

概数値

Real

概数値

decimal

正確な数値

money

正確な数値

smallmoney

正確な数値

bigint

正確な数値

int

正確な数値

smallint

正確な数値

tinyint

正確な数値

bit

正確な数値

nvarchar

Unicode

nchar

Unicode

varchar

Unicode

char

Unicode

varbinary

バイナリ

binary

バイナリ

uniqueidentifier

一意識別子

sql_variant 型の比較には、次の規則が適用されます。

  • 基本データ型の異なる sql_variant 型の値どうしを比較するときに、両者の基本データ型が異なるデータ型ファミリに属する場合は、階層表内で上位にあるデータ型ファミリの値の方が、両者間ではより高い値であると見なされます。

  • 基本データ型が異なる sql_variant 型の値どうしを比較するときに、両者の基本データ型が同じデータ型ファミリに属する場合は、階層表内で下位にある基本データ型の値の方が、暗黙的に他方のデータ型に変換され、その後比較が行われます。

  • char、varchar、nchar、または varchar のいずれかのデータ型の sql_variant 型の値どうしを比較する場合、それらの値は、LCID、LCID のバージョン、比較フラグ、および並べ替え ID という基準に基づいて評価されます。これらの基準は、ここで列挙した順番に従って、それぞれ整数値として比較されます。

上記の規則により、sql_variant 型どうしの値を比較する場合に、同じ基本データ型の値どうしの比較とは異なる結果が生じる場合があります。

オペランド A

オペランド B

バリアント型以外の比較結果

sql_variant 型の比較結果

'123' char

111 int

A > B

B > A

50000 int

5E1 float

A > B

B > A

データ型ファミリが異なる値を比較の述語で参照する場合は、あらかじめ明示的にキャストする必要があり、この規則が反映されるのは sql_variant 型の列で結果セットを順序付ける場合のみになります。次の表の値は、データ型の優先順位に関する規則の例です。

PriKey

VariantCol

1

50.0 (基本データ型 float)

2

5000 (基本データ型 int)

3

'124000' (基本データ型 char(6))

次の表に、SELECT * FROM VariantTest ORDER BY VariantCol ASC ステートメントの結果を示します。

PriKey

VariantCol

3

'124000' (基本データ型 char(6))

2

5000 (基本データ型 int)

1

50.0 (基本データ型 float)

次の表の値は、照合順序の優先順位に関する規則の例です。

IntKey

VariantCol

1

qrs (varchar SQL_Latin1_General_Pref_Cp1_CI_AS)

2

abc (varchar SQL_Latin1_General_Pref_Cp1_CI_AS)

3

qrs (varchar SQL_Latin1_General_CP1_CS_AS)

4

17.5 (decimal)

5

abc (varchar SQL_Latin1_General_CP1_CS_AS)

6

klm (varchar SQL_Latin1_General_CP1_CS_AS)

7

1.2 (decimal)

次の表に、SELECT * FROM CollateTest ORDER BY VariantCol ステートメントの結果を示します。この表は、グループ化された "正確な数値" データ型ファミリの値と、それぞれの照合順序に従ってグループ化された varchar 型の値を示しています。

IntKey

VariantCol

5

abc (varchar SQL_Latin1_General_CP1_CS_AS)

6

klm (varchar SQL_Latin1_General_CP1_CS_AS)

3

qrs (varchar SQL_Latin1_General_CP1_CS_AS)

2

abc (varchar SQL_Latin1_General_Pref_Cp1_CI_AS)

1

qrs (varchar SQL_Latin1_General_Pref_Cp1_CI_AS)

7

1.2 (decimal)

4

17.5 (decimal)

関数と sql_variant 型のデータ

次の Transact-SQL 関数では、sql_variant 型のパラメータがサポートされます。sql_variant 型のパラメータを指定すると、sql_variant 型の値が返されます。

COALESCE

MIN

MAX

NULLIF

次の関数では、sql_variant 型の列または変数への参照がサポートされますが、sql_variant 型は戻り値のデータ型としては使用されません。

COL_LENGTH

DATALENGTH

TYPEPROPERTY

COLUMNPROPERTY

ISNULL

 

次の Transact-SQL 関数では、sql_variant 型のパラメータがサポートされません。

AVG

RADIANS

STDEV[P]

IDENTITY

ROUND

SUM

ISNUMERIC

SIGN

VAR[P]

POWER

 

 

CAST 関数と CONVERT 関数では、sql_variant 型がサポートされます。

新しい SQL_VARIANT_PROPERTY() 関数を使用して、データ型、有効桁数、小数点以下桁数など、sql_variant 型の値に関するプロパティ情報を取得できます。

その他の Transact-SQL 要素と sql_variant 型のデータ

sql_variant 型の列は、LIKE 述語ではサポートされません。

sql_variant 型の列は、フルテキスト インデックスではサポートされません。CONTAINSTABLE や FREETEXTTABLE などのフルテキスト関数では、sql_variant 型の列を指定できません。

次の Transact-SQL ステートメントでは、構文中の他の整数データ型を指定した位置と同じ位置に sql_variant 型を指定することがサポートされます。

  • ALTER PROCEDURE

  • ALTER TABLE

  • CREATE PROCEDURE

  • CREATE TABLE

  • DECLARE variable

SQL Server のカタログ コンポーネントにより、sql_variant 型の列に関する情報が報告されます。

CASE 式の結果は、入力式または結果式のいずれかの評価結果が sql_variant 型である場合、sql_variant 型になります。結果の基本データ型は、実行時に結果として評価された式の型になります。

数値または文字列の連結演算子のオペランドを sql_variant 型にすることはできません。たとえば、次のコードを実行するとエラーが発生します。

SELECT VariantCol + @CharacterVar

FROM MyTable

ただし、次のように sql_variant 型のオペランドをキャストすることにより、この演算を実行できます。

SELECT CAST(VariantCol AS varchar(25)) + @CharacterVar

FROM MyTable

アプリケーションと sql_variant 型のデータ

単一の基本データ型を持つ sql_variant 型のデータを特定の列が返すような結果セットをアプリケーションが要求する場合、このアプリケーションは Transact-SQL ステートメントで CAST 関数または CONVERT 関数を使用し、その基本データ型を使用して sql_variant 型のデータを返すことができます。この場合、基本データ型の結果セット列と同様の方法でデータが扱われます。

SQL Server Native Client OLE DB Provider for SQL Server により、sql_variant 型の列とパラメータで使用できるプロバイダ固有の OLE DB 型である DBTYPE_SQLVARIANT が導入されています。

SQL Server の SQL Server Native Client ODBC ドライバにより、sql_variant 型の列とパラメータで使用できるプロバイダ固有の ODBC データベースのデータ型である SQL_SS_VARIANT が導入されています。

次のインターフェイスを使用して接続したアプリケーションで作業する場合は、SQL Server により、sql_variant 型の値が nvarchar(4000) 型に変換されます。

  • SQL Server 7.0 の OLE DB プロバイダ。

  • SQL Server 7.0 の SQL Server ODBC ドライバ。

結果の文字列が 4,000 文字を超える場合は、最初の 4,000 文字が SQL Server によって返されます。

次のインターフェイスを使用して接続したアプリケーションで作業する場合は、SQL Server により、sql_variant 型の値が varchar(255) 型に変換されます。

  • SQL Server 6.5 以前の SQL Server ODBC ドライバ。

結果の文字列が 255 文字を超える場合は、最初の 255 文字が SQL Server によって返されます。