SqlServer强制转换函数TRY_CONVERT和TRY_CAST的介绍和案例分享
1、本节内容
CAST 和 CONVERT
TRY_CAST
TRY_CONVERT
适用于:
- SQL Server
- Azure SQL 数据库
- Azure SQL 托管实例
- Azure Synapse Analytics 分析平台系统 (PDW)
- Microsoft Fabric 中的 SQL 分析端点
- Microsoft Fabric 中的仓库
2、CAST 和 CONVERT
2.1、语法
CAST 语法:
CAST ( expression AS data_type [ ( length ) ] )
CONVERT 语法:
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
2.2、参数
expression
任何有效的表达式。
data_type
目标数据类型。 这包括 xml、bigint 和sql_variant 。 不能使用别名数据类型。
length
指定目标数据类型长度的可选整数,适用于允许用户指定长度的数据类型。 默认值为 30。
style
指定 CONVERT 函数将如何转换表达式的整数表达式。 对于 NULL 的样式值,则返回 NULL。 data_type 确定范围。
返回类型
返回转换为 data_type 的 expression 。
日期和时间样式
对于日期或时间数据类型的 expression,style 可以具有下表所示的某个值。 其他值作为 0 进行处理。 从 SQL Server 2012 (11.x) 开始,在从日期和时间类型转换为 datetimeoffset 时支持的唯一样式是 0 或 1。 所有其他转换样式均返回错误 9809。
2.3、返回类型
返回转换为 data_type 的 expression 。
2.4、日期和时间样式
对于日期或时间数据类型的 expression,style 可以具有下表所示的某个值。 其他值作为 0 进行处理。 从 SQL Server 2012 (11.x) 开始,在从日期和时间类型转换为 datetimeoffset 时支持的唯一样式是 0 或 1。
参考官方文档
https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16
2.5、隐式转换
隐式转换不需要规范 CAST 函数或 CONVERT 函数。 显示转换需要规范 CAST 函数或 CONVERT 函数。 以下图例显示了可对 SQL Server 系统提供的数据类型执行的所有显式和隐式数据类型转换。 这些包括 bigint、sql_variant 和 xml 。 不存在对 sql_variant 数据类型的赋值进行的隐式转换,但是存在转换为 sql_variant 的隐式转换 。
2.6、大值数据类型
大值数据类型具有与小值数据类型相同的隐式和显式转换行为 - 特别是 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 数据类型。
2.7、示例
2.7.1、 同时使用 CAST 和 CONVERT
每个示例检索标价的第一位是 3 的产品的名称,并将其 ListPrice 值转换为 int。
使用 CAST:
USE AdventureWorks2022; -- 示例数据库下载 https://download.csdn.net/download/zxrhhm/89638395?spm=1001.2014.3001.5503
GO
SELECT SUBSTRING(Name, 1, 30) AS ProductName,ListPrice
FROM Production.Product
WHERE CAST(ListPrice AS INT) LIKE '33%';
GO
使用 CONVERT:
USE AdventureWorks2022;
GO
SELECT SUBSTRING(Name, 1, 30) AS ProductName,ListPrice
FROM Production.Product
WHERE CONVERT(INT, ListPrice) LIKE '33%';
GO
结果集如下。 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)
2.7.2、将 CAST 与算术运算符结合使用
此示例将本年度截止到现在的全部销售额 (Computed) 除以佣金百分比 (SalesYTD),从而得出单列计算结果 (CommissionPCT)。 此值舍入为最接近的整数,然后 CAST 为 int 数据类型。
SELECT SalesYTD,CommissionPCT,CAST(ROUND(SalesYTD / CommissionPCT, 0) AS INT) AS Computed
FROM Sales.SalesPerson
WHERE CommissionPCT != 0;
-- 执行返回结果
SalesYTD CommissionPCT Computed
--------------------- --------------------- -----------
3763178.1787 0.012 313598182
4251368.5497 0.015 283424570
3189418.3662 0.015 212627891
1453719.4653 0.01 145371947
2315185.611 0.01 231518561
1352577.1325 0.01 135257713
2458535.6169 0.01 245853562
2604540.7172 0.015 173636048
1573012.9383 0.012 131084412
1576562.1966 0.019 82976958
1421810.9242 0.018 78989496
1827066.7118 0.018 101503706
4116871.2277 0.02 205843561
3121616.3202 0.016 195101020
(14 行受影响)
2.7.3、使用 CAST 进行连接
此示例使用 CAST 连接非字符型表达式。 它使用 AdventureWorksDW2022 数据库。
SELECT CONCAT('The list price is ',CAST(ListPrice AS VARCHAR(12))) AS ListPrice
FROM [Production].[Product]
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
(5 行受影响)
2.7.4、使用 CAST 生成可读性更高的文本
此示例使用 SELECT 列表中的 CAST 将 Name 列转换为 char(10) 列。 它使用 AdventureWorksDW2022 数据库。
SELECT DISTINCT CAST(Name AS CHAR(10)) AS Name,ListPrice
FROM [Production].[Product]
WHERE Name LIKE 'Long-Sleeve Logo Jersey, M';
GO
-- 执行返回结果
Name ListPrice
---------- ---------------------
Long-Sleev 49.99
(1 行受影响)
2.7.5、对 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,
CONVERT(NVARCHAR(30), GETDATE(), 120) AS UsingConvertTo_ISO8601_120;
--
UnconvertedDateTime UsingCast UsingConvertTo_ISO8601 UsingConvertTo_ISO8601_120
----------------------- ------------------------------ ------------------------------ ------------------------------
2024-11-28 14:38:38.067 Nov 28 2024 2:38PM 2024-11-28T14:38:38.067 2024-11-28 14:38:38
(1 行受影响)
使用 CONVERT 处理不同格式的 datetime 数据
从 GETDATE() 值开始,此示例使用CONVERT 显示本文日期和时间样式部分的所有日期和时间样式。
2.7.6、允许的转换中数据类型优先级的影响
以下示例定义一个类型为 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。 当提供的数据类型为整数时,+ 运算符会成为加法运算符而不是字符串串联。
3、TRY_CAST
返回转换为指定数据类型的值(如果转换成功);否则返回 Null。
3.1、语法
TRY_CAST ( expression AS data_type [ ( length ) ] )
3.2、参数
expression
指定要强制转换的任何有效表达式。
data_type
要将 expression 强制转换为的数据类型。
length
指定目标数据类型长度的可选整数。
可接受值的范围由 data_type 的值确定。
3.3、返回类型
返回转换为指定数据类型的值(如果转换成功);否则返回 Null。
3.2、注解
TRY_CONVERT 接收传递给它的值,并尝试将该值转换为指定的 data_typeTRY_CAST。 如果强制转换成功,TRY_CONVERT 按指定的 data_type 返回值;如果发生错误,则返回 NULLTRY_CAST。 但是,如果您请求的转换是显式不允许执行的转换,则 TRY_CAST 失败并显示错误。
TRY_CAST 不是新的保留关键字,且可用于所有兼容级别。 当连接到远程服务器时,TRY_CAST 与 TRY_CONVERT 具有相同的语义。
如果长度超过 8000,则 TRY_CAST 不适用于 varchar(max)。
3.4、示例
3.4.1、TRY_CAST 返回 Null。
下面的示例演示强制转换失败时 TRY_CAST 返回 Null。
SELECT
CASE WHEN TRY_CAST('test' AS FLOAT) IS NULL
THEN 'Cast failed'
ELSE 'Cast succeeded'
END AS Result;
GO
-- 返回执行结果如下
Result
-----------
Cast failed
(1 行受影响)
示例演示表达式
SELECT TRY_CAST('10.88cm' AS DECIMAL(18,3)) AS Result;
GO
-- 返回执行结果如下
Result
---------------------------------------
NULL
(1 行受影响)
3.4.2、TRY_CAST 失败并显示错误
下面的示例演示显式不允许强制转换时 TRY_CAST 返回错误。
SELECT TRY_CAST(4 AS XML) AS Result;
GO
-- 返回此语句的结果是一个错误,因为整数无法强制转换为 xml 数据类型。
Explicit conversion from data type int to xml is not allowed.
3.4.3、TRY_CAST 成功
此示例演示表达式必须采用所需的格式。
SELECT TRY_CAST('11/28/2024' AS DATETIME2) AS Result;
GO
-- 返回执行结果如下
Result
---------------------------
2024-11-28 00:00:00.0000000
(1 行受影响)
4、TRY_CONVERT
如果强制转换成功,则返回转换为指定数据类型的值;否则,返回 NULL。
4.1、语法
TRY_CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
4.2、参数
data_type
要将 expression 强制转换为的数据类型。
length
指定目标数据类型长度的可选整数,适用于允许用户指定长度的数据类型。 长度的最大值为 8,000 字节。
expression
要强制转换的值。
style
指定函数如何转换表达式的TRY_CONVERT可选整数表达式。
style 接受与函数的CONVERT样式参数相同的值。 有关详细信息,请参阅 CAST 和 CONVERT。
data_type的值确定可接受的值范围。 如果 样式 为 NULL,则 TRY_CONVERT 返回 NULL。
4.3、返回类型
如果强制转换成功,则返回转换为指定数据类型的值;否则,返回 NULL。
4.4、注解
TRY_CONVERT 接收传递给它的值,并尝试将该值转换为指定的 data_typeTRY_CONVERT。 如果强制转换成功, TRY_CONVERT 则返回指定的 data_type;如果发生错误, NULL 则返回该值。 但是,如果您请求的转换是显式不允许执行的转换,则 TRY_CONVERT 失败并显示错误。
TRY_CONVERT 是一个保留关键字,从兼容级别 110开始。
此函数能够远程连接到具有 SQL Server 2012 (11.x) 及更高版本的服务器。 它不远程到版本低于 SQL Server 2012(11.x)的服务器。
4.5、示例
4.5.1、TRY_CONVERT返回 NULL
下面的示例演示 TRY_CONVERT 了转换失败时返回 NULL 的内容。
SELECT
CASE WHEN TRY_CONVERT(FLOAT, 'test') IS NULL
THEN 'Cast failed'
ELSE 'Cast succeeded'
END AS Result;
GO
以下示例演示表达式必须采用所需的格式。
SET DATEFORMAT DMY; -- 设置错误的格式返回NULL
SELECT TRY_CONVERT(DATETIME2, '11/28/2024') AS Result;
GO
-- 返回执行结果
Result
---------------------------
NULL
(1 行受影响)
4.5.2、TRY_CONVERT 将失败,并出现错误
下面的示例演示显式不允许强制转换时 TRY_CONVERT 返回错误。
SELECT TRY_CONVERT(XML, 4) AS Result;
GO
-- 此语句的结果是一个错误,因为整数无法强制转换为 xml 数据类型。
Explicit conversion from data type int to xml is not allowed.
4.5.3、TRY_CONVERT 成功
此示例演示表达式必须采用所需的格式。
SET DATEFORMAT MDY;
SELECT TRY_CONVERT(DATETIME2, '12/31/2024') AS Result;
GO
-- 返回执行结果
Result
---------------------------
2024-12-31 00:00:00.0000000
(1 行受影响)