sql_variant 数据类型的运行过程与 Microsoft® Visual Basic® 中的 variant 数据类型相似。它允许单一的列、参数或变量存储不同数据类型的数据值。例如,一个单一的 sql_variant 列能保存 int、decimal、char、binary 和 nchar 值。sql_variant 列的每个实例记录数据值和元数据信息,其中包括基本数据类型、最大大小、小数位数、精度和排序规则。
sql_variant 数据类型遵循以下规则:
- 常规赋值
- 表中的 sql_variant
- 只要键列中的数据长度不超过 900 字节,在索引和唯一键中就可以使用 sql_variant 列。
- sql_variant 列不支持 IDENTITY 属性,但是 sql_variant 列允许作为主键和外键的一部分。
- 在计算列中不能用 sql_variant 列。
- 使用 ALTER TABLE 将除了 text、ntext、image、timestamp 或 sql_variant 之外的任何数据类型的列更改为 sql_variant。所有现有的值都被转换成 sql_variant 值,这些值的基本数据类型与执行 ALTER TABLE 语句之前列的数据类型相同。由于不存在支持从 sql_variant 到其它数据类型的隐性转换,因此不能使用 ALTER TABLE 将 sql_variant 列的数据类型更改为任何其它数据类型。
- 排序规则
- COLLATE 子句不能用于将列排序规则指派给 sql_variant 列。sql_variant 列中基于字符的值(char、nchar、varchar 和 nvarchar)可以具有任何排序规则,而且单个 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 |
Datetime |
| smalldatetime |
Datetime |
| float |
近似数 |
| real |
近似数 |
| decimal |
精确数 |
| money |
精确数 |
| smallmoney |
精确数 |
| bigint |
精确数 |
| int |
精确数 |
| smallint |
精确数 |
| tinyint |
精确数 |
| bit |
精确数 |
| nvarchar |
Unicode |
| nchar |
Unicode |
| varchar |
Unicode |
| char |
Unicode |
| varbinary |
Binary |
| binary |
Binary |
| uniqueidentifier |
Uniqueidentifier |
适用于 sql_variant 比较的规则如下:
- 当具有不同基本数据类型的 sql_variant 值进行比较,而且基本数据类型属于不同的数据类型系列时,在层次结构图中数据类型系列较高的值,被认为在二者中值较大。
- 当具有不同基本数据类型的 sql_variant 值进行比较,而且基本数据类型属于相同的数据类型系列,在层次结构图中基本数据类型比较低的值先隐性转换成其它数据类型,然后再进行比较。
- 当比较具有 char、varchar、nchar 或 varchar 数据类型的 sql_variant 值时,将基于以下准则对它们进行比较:LCID、LCID 版本、比较标志和排序 ID。这些准则中的每一个都作为整型值并按列出的顺序进行比较。
在 sql_variant 值之间用这些规则进行比较,与用同样的规则在具有相同的基本数据类型的值之间进行比较相比,会产生不同的结果。
操作数 A |
操作数 B |
Non-variant 比较结果 |
sql_variant 比较结果 |
| '123' char |
111t |
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 数据
当指定 sql_variant 参数时,下面的 Transact-SQL 函数支持 sql_variant 参数并返回 sql_variant 值:
这些函数支持引用 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 数据
在 LIKE 谓词中不支持sql_variant 列。
在全文本索引中不支持 sql_variant 列。它们不能在全文本函数(例如 CONTAINSTABLE 和 FREETEXTTABLE)中指定。
这些 Transact-SQL 语句支持在指定其它整型数据类型相同的语法位置上指定 sql_variant:
- ALTER PROCEDURE
- ALTER TABLE
- CREATE PROCEDURE
- CREATE TABLE
- DECLARE variable
Microsoft® SQL Server™ 2000 目录组件报告有关 sql_variant 列的信息。
如果任何输入和结果表达式的值是 sql_variant,则 CASE 表达式的结果就是 sql_variant。结果的基础数据类型是运行时所求得的表达式的基础数据类型。
数字或字符串串联的运算符不能是 sql_variant:
-- Generates an error:
SELECT VariantCol + @CharacterVar
FROM MyTable
转换 sql_variant 操作数可以执行下面的操作:
-- Does not generates an error:
SELECT CAST(VariantCol AS varchar(25)) + @CharacterVar
FROM MyTable
应用程序和 sql_variant 数据
如果应用程序要求一个结果集,其中一个给定列返回具有单一的基本数据类型的 sql_variant 数据,则该应用程序可以在 Transact-SQL 语句中用 CAST 或 CONVERT 函数通过使用基本数据类型返回 sql_variant 数据。在这种情况下,应用程序处理数据的方式与它处理基本数据类型的结果的方式相同。本主题描述 Microsoft® SQL Server™ 如何返回尚未投影或未转换为特定基本数据类型的 sql_variant 数据。
用于 SQL Server 的 OLE DB 提供程序引入了一个提供程序专用的 OLE DB 类型 DBTYPE_SQLVARIANT,用于 sql_variant 列和参数。
SQL Server ODBC 驱动程序引入了一个提供程序专用的 ODBC 数据库数据类型 SQL_SS_VARIANT,用于 sql_variant 列和参数。
当与连接到下列接口的应用程序一起工作时,SQL Server 将 sql_variant 数据转换成 nvarchar(4000):
- 用于 SQL Server 7.0 版的 OLE DB 提供程序。
- SQL Server 7.0 版的 SQL Server ODBC 驱动程序。
如果所得到的字符串超过 4000 个字符,则 SQL Server 返回前 4000 个字符。
当与连接到下列接口的应用程序一起工作时,SQL Server 将 sql_variant 值转换成 varchar(255):
- SQL Server 6.5 或更低版本提供的 SQL Server ODBC 驱动程序。
- 任何版本的 DB-Library dll。
如果所得到的字符串超过 255 个字符,则 SQL Server 返回前 255 个字符。