SELECT CAST(CAST(0x41 AS nvarchar) AS varbinary);
有关详细信息,请参阅 排序规则和 Unicode 支持。
大值数据类型
大值数据类型具有与小值数据类型相同的隐式和显式转换行为 - 特别是 nvarchar、varbinary 和 varchar 数据类型 。 但是,请考虑以下原则:
从 image 转换到 varbinary(max) 以及从 varbinary(max) 转换到 image 属于隐式转换操作,同样的还有 text 与 varchar(max) 之间的转换和 ntext 与 nvarchar(max) 之间的转换 。
从大值数据类型(如 varchar(max))到小值数据类型(如 varchar)的转换是隐式转换,但如果大值的大小超过小值数据类型的指定长度,则产生截断 。
从 nvarchar、varbinary 或 varchar 到其相应的大值数据类型的转换都是隐式转换 。
从 sql_variant 数据类型到大值数据类型的转换是显式转换。
大值数据类型不能转换为 sql_variant 数据类型。
有关从 xml 数据类型进行转换的详细信息,请参阅创建 XML 数据的实例。
XML 数据类型
将 xml 数据类型显式或隐式转换为字符串或二进制数据类型时,xml 数据类型的内容将根据一组确定的规则进行序列化 。 有关这些规则的信息,请参阅定义 XML 数据的序列化。 有关从其他数据类型转换到 xml 数据类型对的信息,请参阅创建 XML 数据的实例。
text 和 image 数据类型
text 和 image 数据类型不支持自动进行数据类型转换。 可以显式将 text 数据转换为字符数据,将 image 数据转换为 binary 或 varbinary,但是最大长度为 8000 字节 。 如果试图进行不正确的转换(如将包含字母的字符表达式转换为 int),则 SQL Server 将返回错误消息。
输出排序规则
如果 CAST
或 CONVERT
函数输出字符串,并且接收字符串输入,则输出将与输入具有相同的排序规则和排序规则标签。 如果输入不是字符串,则输出采用数据库的默认排序规则以及强制默认的排序规则标签。 有关详细信息,请参阅 排序规则优先顺序 (Transact-SQL)。
若要为输出分配不同的排序规则,请将 COLLATE 子句应用于 CAST
或 CONVERT
函数的结果表达式。 例如:
SELECT CAST('abc' AS varchar(5)) COLLATE French_CS_AS;
截断结果和舍入结果
将字符或二进制表达式(binary、char、nchar、nvarchar、varbinary 或 varchar)转换为不同数据类型的表达式时,转换操作可能会截断输出数据,仅显示部分输出数据,或返回错误 。 如果结果太短而无法显示,则会发生这种情况。 会截断到 binary、char、nchar、nvarchar、varbinary 或 varchar 的转换,除了下表中显示的转换 。
被转换的数据类型
转换为的数据类型
1 因为结果长度太短无法显示而返回错误。
SQL Server 仅保证往返转换(也就是从原始数据类型进行转换后又返回原始数据类型的转换)在各版本间产生相同值。 以下示例显示的即是这样的往返转换:
DECLARE @myval DECIMAL(5, 2);
SET @myval = 193.57;
SELECT CAST(CAST(@myval AS VARBINARY(20)) AS DECIMAL(10, 5));
-- Or, using CONVERT
SELECT CONVERT(DECIMAL(10, 5), CONVERT(VARBINARY(20), @myval));
请勿构造 binary 值然后将其转换为数值数据类型类别的一种数据类型。 SQL Server 不能保证 decimal 或 numeric 数据类型到 binary 的转换结果在 SQL Server 的各个版本中都相同 。
以下示例显示了由于太小而无法显示的结果表达式。
USE AdventureWorks2019;
SELECT p.FirstName,
p.LastName,
SUBSTRING(p.Title, 1, 25) AS Title,
CAST(e.SickLeaveHours AS CHAR(1)) AS [Sick Leave]
FROM HumanResources.Employee e
INNER JOIN Person.Person p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE NOT e.BusinessEntityID > 5;
下面是结果集。
FirstName LastName Title Sick Leave
--------- ------------- ------- --------`
Ken Sanchez NULL *
Terri Duffy NULL *
Roberto Tamburello NULL *
Rob Walters NULL *
Gail Erickson Ms. *
(5 row(s) affected)
转换小数位数不同的数据类型时,SQL Server 有时会返回截断后的结果值,有时会返回舍入值。 此表显示了此行为。
1 如果将使用科学记数法的 float 值转换为 decimal 或 numeric 时,转换会限制为只有 17 位精度的值。 精度高于 17 的任何值都将舍入为零。
例如,10.6496 和 -10.6496 可能会被截断或者在转换到 int 或 numeric 类型期间被舍入 :
SELECT CAST(10.6496 AS INT) AS trunc1,
CAST(-10.6496 AS INT) AS trunc2,
CAST(10.6496 AS NUMERIC) AS round1,
CAST(-10.6496 AS NUMERIC) AS round2;
查询结果显示在下表中:
trunc1
trunc2
round1
round2
在进行数据类型转换时,若目标数据类型的小数位数小于源数据类型的小数位数,则该值将进行舍入。 例如,此转换返回 $10.3497
:
SELECT CAST(10.3496847 AS money);
将非数字 char、nchar、nvarchar 或 varchar 数据转换为 decimal、float、int、numeric 时,SQL Server 返回错误消息 。 当空字符串 (" ") 转换为 numeric 或 decimal 时,SQL Server 也返回错误 。
某些日期时间的转换具有不确定性
从 string 到 datetime 的转换为不确定性转换的样式如下所示:
低于 100 的所有样式 1
1 样式 20 和 21 除外
有关详细信息,请参阅文字日期字符串转换为日期值的不确定性转换。
补充字符(代理项对)
从 SQL Server 2012 (11.x) 开始,使用增补字符 (SC) 排序规则时,从 nchar 或 nvarchar 到更小长度的 nchar 或 nvarchar 类型的 CAST
操作将不会在代理项对内截断。 相反,该操作会在增补字符前面截断。 例如,以下代码段导致 @x
仅保留 'ab'
。 没有足够的空间来保留增补字符。
DECLARE @x NVARCHAR(10) = 'ab' + NCHAR(0x10000);
SELECT CAST(@x AS NVARCHAR(3));
在使用 SC 排序规则时,CONVERT
行为类似于 CAST
。 有关详细信息,请参阅排序规则和 Unicode 支持 - 补充字符。
兼容性支持
在 SQL Server 的早期版本中,对 time 或 datetime2 数据类型的 CAST
和 CONVERT
操作的默认样式为 121,当在计算列表达式中使用这些类型时除外。 对于计算列,默认样式为 0。 当创建用于涉及自动参数化的查询中或约束定义中的计算列时,此行为会影响计算列。
兼容性级别为 110 或更高时,对 time 和 datetime2 数据类型的 CAST
和 CONVERT
操作的默认样式始终为 121。 如果查询依赖旧行为,请使用低于 110 的兼容性级别或在受影响的查询中显式指定 0 样式。
兼容性级别值
CAST
和 CONVERT
的默认风格1
计算列的默认样式
1 计算列除外
将数据库升级到兼容级别 110 或更高将不更改已存储到磁盘的用户数据。 您必须相应手动更正此数据。 例如,如果使用了 SELECT INTO 来从包含上述计算列表达式的源创建表,将存储数据(使用样式 0)而非存储计算列定义本身。 必须手动更新此数据,以匹配样式 121。
A. 同时使用 CAST 和 CONVERT
每个示例检索标价的第一位是 3
的产品的名称,并将其 ListPrice
值转换为 int。
使用 CAST
:
USE AdventureWorks2019;
SELECT SUBSTRING(Name, 1, 30) AS ProductName,
ListPrice
FROM Production.Product
WHERE CAST(ListPrice AS INT) LIKE '33%';
使用 CONVERT
:
USE AdventureWorks2019;
SELECT SUBSTRING(Name, 1, 30) AS ProductName,
ListPrice
FROM Production.Product
WHERE CONVERT(INT, ListPrice) LIKE '33%';
下面是结果集。 CAST
和 CONVERT
的示例结果集相同。
ProductName ListPrice
------------------------------ ---------------------
LL Road Frame - Black, 58 337.22
LL Road Frame - Black, 60 337.22
LL Road Frame - Black, 62 337.22
LL Road Frame - Red, 44 337.22
LL Road Frame - Red, 48 337.22
LL Road Frame - Red, 52 337.22
LL Road Frame - Red, 58 337.22
LL Road Frame - Red, 60 337.22
LL Road Frame - Red, 62 337.22
LL Road Frame - Black, 44 337.22
LL Road Frame - Black, 48 337.22
LL Road Frame - Black, 52 337.22
Mountain-100 Black, 38 3374.99
Mountain-100 Black, 42 3374.99
Mountain-100 Black, 44 3374.99
Mountain-100 Black, 48 3374.99
HL Road Front Wheel 330.06
LL Touring Frame - Yellow, 62 333.42
LL Touring Frame - Blue, 50 333.42
LL Touring Frame - Blue, 54 333.42
LL Touring Frame - Blue, 58 333.42
LL Touring Frame - Blue, 62 333.42
LL Touring Frame - Yellow, 44 333.42
LL Touring Frame - Yellow, 50 333.42
LL Touring Frame - Yellow, 54 333.42
LL Touring Frame - Yellow, 58 333.42
LL Touring Frame - Blue, 44 333.42
HL Road Tire 32.60
(28 rows affected)
B. 将 CAST 与算术运算符结合使用
此示例将本年度截止到现在的全部销售额 (Computed
) 除以佣金百分比 (SalesYTD
),从而得出单列计算结果 (CommissionPCT
)。 此值舍入为最接近的整数,然后 CAST
为 int 数据类型。
USE AdventureWorks2019;
SELECT CAST(ROUND(SalesYTD / CommissionPCT, 0) AS INT) AS Computed
FROM Sales.SalesPerson
WHERE CommissionPCT != 0;
下面是结果集。
Computed
------
379753754
346698349
257144242
176493899
281101272
301872549
212623750
298948202
250784119
239246890
101664220
124511336
97688107
(14 row(s) affected)
C. 使用 CAST 进行连接
此示例使用 CAST
连接非字符型表达式。 它使用 AdventureWorksDW2019
数据库。
SELECT 'The list price is ' + CAST(ListPrice AS VARCHAR(12)) AS ListPrice
FROM dbo.DimProduct
WHERE ListPrice BETWEEN 350.00 AND 400.00;
下面是结果集。
ListPrice
------------------------
The list price is 357.06
The list price is 364.09
The list price is 364.09
The list price is 364.09
The list price is 364.09
D. 使用 CAST 生成可读性更高的文本
此示例使用 SELECT 列表中的 CAST
将 Name
列转换为 char(10) 列。 它使用 AdventureWorksDW2019
数据库。
SELECT DISTINCT CAST(EnglishProductName AS CHAR(10)) AS Name,
ListPrice
FROM dbo.DimProduct
WHERE EnglishProductName LIKE 'Long-Sleeve Logo Jersey, M';
下面是结果集。
Name ListPrice
---------- ---------
Long-Sleev 31.2437
Long-Sleev 32.4935
Long-Sleev 49.99
E. 将 CAST 与 LIKE 子句结合使用
此示例将 money
列 SalesYTD
值转换为数据类型 int,然后转换为数据类型 char(20),以便 LIKE
子句可以使用。
USE AdventureWorks2019;
SELECT p.FirstName,
p.LastName,
s.SalesYTD,
s.BusinessEntityID
FROM Person.Person AS p
INNER JOIN Sales.SalesPerson AS s
ON p.BusinessEntityID = s.BusinessEntityID
WHERE CAST(CAST(s.SalesYTD AS INT) AS CHAR(20)) LIKE '2%';
下面是结果集。
FirstName LastName SalesYTD BusinessEntityID
---------------- ------------------- ---------------- -------------
Tsvi Reiter 2811012.7151 279
Syed Abbas 219088.8836 288
Rachel Valdez 2241204.0424 289
(3 row(s) affected)
F. 使用 CONVERT 或 CAST 转换为类型化的 XML
这些示例说明如何通过 XML 数据类型和列 (SQL Server) 使用 CONVERT
将数据转换为类型化的 XML。
此示例将包含空格、文本和标记的字符串转换为类型化的 XML,并删除所有无用空格(节点之间的边界空格):
SELECT CONVERT(XML, '<root><child/></root>')
此示例将包含空格、文本和标记的类似字符串转换为类型化的 XML,并保留无用空格(节点之间的边界空格):
SELECT CONVERT(XML, '<root> <child/> </root>', 1)
此示例将包含空格、文本和标记的字符串转换为类型化的 XML:
SELECT CAST('<Name><FName>Carol</FName><LName>Elliot</LName></Name>' AS XML)
有关更多示例,请参阅创建 XML 数据的实例。
G. 对 datetime 数据使用 CAST 和 CONVERT
从 GETDATE()
值开始,此示例显示当前日期和时间,使用 CAST
将当前日期和时间更改为字符数据类型,然后使用 CONVERT
以 ISO 8601
格式显示日期和时间。
SELECT GETDATE() AS UnconvertedDateTime,
CAST(GETDATE() AS NVARCHAR(30)) AS UsingCast,
CONVERT(NVARCHAR(30), GETDATE(), 126) AS UsingConvertTo_ISO8601;
下面是结果集。
UnconvertedDateTime UsingCast UsingConvertTo_ISO8601
----------------------- ---------------------- ------------------------------
2022-04-18 09:58:04.570 Apr 18 2022 9:58AM 2022-04-18T09:58:04.570
(1 row(s) affected)
此示例与上述示例几乎完全相反。 该示例将日期和时间显示为字符数据,使用 CAST
将字符数据更改为 datetime 数据类型,然后使用 CONVERT
将字符数据更改为 datetime 数据类型。
SELECT '2006-04-25T15:50:59.997' AS UnconvertedText,
CAST('2006-04-25T15:50:59.997' AS DATETIME) AS UsingCast,
CONVERT(DATETIME, '2006-04-25T15:50:59.997', 126) AS UsingConvertFrom_ISO8601;
下面是结果集。
UnconvertedText UsingCast UsingConvertFrom_ISO8601
----------------------- ----------------------- ------------------------
2006-04-25T15:50:59.997 2006-04-25 15:50:59.997 2006-04-25 15:50:59.997
(1 row(s) affected)
H. 使用 CONVERT 处理二进制和字符数据
这些示例使用不同样式显示二进制和字符数据转换的结果。
--Convert the binary value 0x4E616d65 to a character value.
SELECT CONVERT(CHAR(8), 0x4E616d65, 0) AS [Style 0, binary to character];
下面是结果集。
Style 0, binary to character
----------------------------
(1 row(s) affected)
此示例显示 Style 1 可以强制截断结果。 结果集中的字符 0x 强制实施截断。
SELECT CONVERT(CHAR(8), 0x4E616d65, 1) AS [Style 1, binary to character];
下面是结果集。
Style 1, binary to character
------------------------------
0x4E616D
(1 row(s) affected)
该例显示样式 2 不截断结果,因为结果中不包括字符 0x。
SELECT CONVERT(CHAR(8), 0x4E616d65, 2) AS [Style 2, binary to character];
下面是结果集。
Style 2, binary to character
------------------------------
4E616D65
(1 row(s) affected)
将字符值“Name”转换为二进制值。
SELECT CONVERT(BINARY(8), 'Name', 0) AS [Style 0, character to binary];
下面是结果集。
Style 0, character to binary
----------------------------
0x4E616D6500000000
(1 row(s) affected)
SELECT CONVERT(BINARY(4), '0x4E616D65', 1) AS [Style 1, character to binary];
下面是结果集。
Style 1, character to binary
----------------------------
0x4E616D65
(1 row(s) affected)
SELECT CONVERT(BINARY(4), '4E616D65', 2) AS [Style 2, character to binary];
下面是结果集。
Style 2, character to binary
----------------------------------
0x4E616D65
(1 row(s) affected)
I. 转换日期和时间数据类型
此示例显示了 date、time 及 datetime 数据类型的转换。
DECLARE @d1 DATE,
@t1 TIME,
@dt1 DATETIME;
SET @d1 = GETDATE();
SET @t1 = GETDATE();
SET @dt1 = GETDATE();
SET @d1 = GETDATE();
-- When converting date to datetime the minutes portion becomes zero.
SELECT @d1 AS [DATE],
CAST(@d1 AS DATETIME) AS [date as datetime];
-- When converting time to datetime the date portion becomes zero
-- which converts to January 1, 1900.
SELECT @t1 AS [TIME],
CAST(@t1 AS DATETIME) AS [time as datetime];
-- When converting datetime to date or time non-applicable portion is dropped.
SELECT @dt1 AS [DATETIME],
CAST(@dt1 AS DATE) AS [datetime as date],
CAST(@dt1 AS TIME) AS [datetime as time];
考虑从 date 转换到 datetime 或 datetime2 时,请确保这些值在兼容的范围内。 datetime 的最小年份值为 1753
,而 date 和 datetime2 的最小年份值为 0001
。
DECLARE @d1 DATE, @dt1 DATETIME , @dt2 DATETIME2
SET @d1 = '1492-08-03'
--This is okay; Minimum YYYY for DATE is 0001
SET @dt2 = CAST(@d1 AS DATETIME2)
--This is okay; Minimum YYYY for DATETIME2 IS 0001
SET @dt1 = CAST(@d1 AS DATETIME)
--This will error with (Msg 242) "The conversion of a date data type to a datetime data type resulted in an out-of-range value."
--Minimum YYYY for DATETIME is 1753
从 GETDATE()
值开始,此示例使用CONVERT
显示本文日期和时间样式部分的所有日期和时间样式。
K. 允许的转换中数据类型优先级的影响
以下示例定义一个类型为 varchar(10) 的变量,将整数值赋给该变量,然后选择该变量与字符串的串联。
DECLARE @string VARCHAR(10);
SET @string = 1;
SELECT @string + ' is a string.' AS Result
下面是结果集。
Result
-----------------------
1 is a string.
int 值 1 已转换为 varchar。
此示例显示了一个类似的查询,但它使用的是 int 变量:
DECLARE @notastring INT;
SET @notastring = '1';
SELECT @notastring + ' is not a string.' AS Result
在此例中,SELECT 语句会引发以下错误:
Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the varchar value ' is not a string.' to data type int.
为了计算表达式 @notastring + ' is not a string.'
,SQL Server 需要先遵循数据类型优先级的规则来完成隐式转换,然后才能计算表达式的结果。 由于 int 的优先级高于 varchar,SQL Server 会尝试将字符串转换为整数,但是会失败,因为此字符串无法转换为整数。
如果我们提供可转换的字符串,则该语句将成功,如以下示例中所示:
DECLARE @notastring INT;
SET @notastring = '1';
SELECT @notastring + '1'
在此例中,字符串 '1'
可以转换为整数值 1,因而此 SELECT 语句会返回值 2。 当提供的数据类型为整数时,+ 运算符会成为加法运算符而不是字符串串联。
示例:Azure Synapse Analytics 和 Analytics Platform System (PDW)
L. 使用 CAST 和 CONVERT
此示例检索标价的第一位是 3
的产品的名称,并将这些产品的 ListPrice
转换为 int。它使用 AdventureWorksDW2019
数据库。
SELECT EnglishProductName AS ProductName, ListPrice
FROM dbo.DimProduct
WHERE CAST(ListPrice AS int) LIKE '3%';
此示例显示使用 CONVERT
而不是 CAST
的相同查询。 它使用 AdventureWorksDW2019
数据库。
SELECT EnglishProductName AS ProductName, ListPrice
FROM dbo.DimProduct
WHERE CONVERT(INT, ListPrice) LIKE '3%';
M. 将 CAST 与算术运算符结合使用
此例通过产品单价 (UnitPrice
) 除以折扣率 (UnitPriceDiscountPct
) 计算单列值。 然后,此结果会舍入到最接近的整数,并最终转换为 int 数据类型。 此示例使用 AdventureWorksDW2019
数据库。
SELECT ProductKey, UnitPrice,UnitPriceDiscountPct,
CAST(ROUND (UnitPrice*UnitPriceDiscountPct,0) AS int) AS DiscountPrice
FROM dbo.FactResellerSales
WHERE SalesOrderNumber = 'SO47355'
AND UnitPriceDiscountPct > .02;
下面是结果集。
ProductKey UnitPrice UnitPriceDiscountPct DiscountPrice
---------- --------- -------------------- -------------
323 430.6445 0.05 22
213 18.5043 0.05 1
456 37.4950 0.10 4
456 37.4950 0.10 4
216 18.5043 0.05 1
N. 将 CAST 与 LIKE 子句结合使用
此例将 money 列 ListPrice
转换为 int 类型,然后转换为 char(20) 类型,以便 LIKE 子句可以使用它 。 此示例使用 AdventureWorksDW2019
数据库。
SELECT EnglishProductName AS Name, ListPrice
FROM dbo.DimProduct
WHERE CAST(CAST(ListPrice AS INT) AS CHAR(20)) LIKE '2%';
O. 对 datetime 数据使用 CAST 和 CONVERT
此示例显示当前日期和时间,使用 CAST
将当前日期和时间更改为字符数据类型,最终使用 CONVERT
以 ISO 8601 格式显示日期和时间。 此示例使用 AdventureWorksDW2019
数据库。
SELECT TOP(1)
SYSDATETIME() AS UnconvertedDateTime,
CAST(SYSDATETIME() AS NVARCHAR(30)) AS UsingCast,
CONVERT(NVARCHAR(30), SYSDATETIME(), 126) AS UsingConvertTo_ISO8601
FROM dbo.DimCustomer;
下面是结果集。
UnconvertedDateTime UsingCast UsingConvertTo_ISO8601
--------------------- --------------------------- ---------------------------
07/20/2010 1:44:31 PM 2010-07-20 13:44:31.5879025 2010-07-20T13:44:31.5879025
此示例与上述示例大致相反。 该示例将日期和时间显示为字符数据,使用 CAST
将字符数据更改为 datetime 数据类型,然后使用 CONVERT
将字符数据更改为 datetime 数据类型。 此示例使用 AdventureWorksDW2019
数据库。
SELECT TOP(1)
'2010-07-25T13:50:38.544' AS UnconvertedText,
CAST('2010-07-25T13:50:38.544' AS DATETIME) AS UsingCast,
CONVERT(DATETIME, '2010-07-25T13:50:38.544', 126) AS UsingConvertFrom_ISO8601
FROM dbo.DimCustomer;
下面是结果集。
UnconvertedText UsingCast UsingConvertFrom_ISO8601
----------------------- ----------------------- ------------------------
2010-07-25T13:50:38.544 07/25/2010 1:50:38 PM 07/25/2010 1:50:38 PM
FORMAT (Transact-SQL)
STR (Transact-SQL)
SELECT (Transact-SQL)
系统函数 (Transact-SQL)
排序规则和 Unicode 支持
数据类型优先级 (Transact-SQL)
数据类型转换(数据库引擎)
编写国际化 Transact-SQL 语句