SqlServer强制转换函数TRY_CONVERT和TRY_CAST

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 语法:

sql 复制代码
CAST ( expression AS data_type [ ( length ) ] )

CONVERT 语法:

sql 复制代码
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )

2.2、参数

sql 复制代码
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:

sql 复制代码
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:

sql 复制代码
USE AdventureWorks2022;
GO

SELECT SUBSTRING(Name, 1, 30) AS ProductName,ListPrice
FROM Production.Product
WHERE CONVERT(INT, ListPrice) LIKE '33%';
GO

结果集如下。 CAST 和 CONVERT 的示例结果集相同。

sql 复制代码
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 数据类型。

sql 复制代码
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 数据库。

sql 复制代码
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 数据库。

sql 复制代码
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 格式显示日期和时间。

sql 复制代码
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) 的变量,将整数值赋给该变量,然后选择该变量与字符串的串联。

sql 复制代码
DECLARE @string VARCHAR(10);
SET @string = 1;
SELECT @string + ' is a string.' AS Result
-- 执行返回结果
Result
-----------------------
1 is a string.

int 值 1 已转换为 varchar。

此示例显示了一个类似的查询,但它使用的是 int 变量:

sql 复制代码
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 会尝试将字符串转换为整数,但是会失败,因为此字符串无法转换为整数。

如果我们提供可转换的字符串,则该语句将成功,如以下示例中所示:

sql 复制代码
DECLARE @notastring INT;
SET @notastring = '1';
SELECT @notastring + '1'

在此例中,字符串 '1' 可以转换为整数值 1,因而此 SELECT 语句会返回值 2。 当提供的数据类型为整数时,+ 运算符会成为加法运算符而不是字符串串联。

3、TRY_CAST

返回转换为指定数据类型的值(如果转换成功);否则返回 Null。

3.1、语法

sql 复制代码
TRY_CAST ( expression AS data_type [ ( length ) ] )

3.2、参数

sql 复制代码
expression
指定要强制转换的任何有效表达式。

data_type
要将 expression 强制转换为的数据类型。

length
指定目标数据类型长度的可选整数。

可接受值的范围由 data_type 的值确定。

3.3、返回类型

sql 复制代码
返回转换为指定数据类型的值(如果转换成功);否则返回 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。

sql 复制代码
SELECT
CASE WHEN TRY_CAST('test' AS FLOAT) IS NULL
     THEN 'Cast failed'
     ELSE 'Cast succeeded'
END AS Result;
GO
-- 返回执行结果如下
Result
-----------
Cast failed

(1 行受影响)

示例演示表达式

sql 复制代码
SELECT TRY_CAST('10.88cm' AS DECIMAL(18,3)) AS Result;
GO
-- 返回执行结果如下
Result
---------------------------------------
NULL

(1 行受影响)

3.4.2、TRY_CAST 失败并显示错误

下面的示例演示显式不允许强制转换时 TRY_CAST 返回错误。

sql 复制代码
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 成功

此示例演示表达式必须采用所需的格式。

sql 复制代码
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、语法

sql 复制代码
TRY_CONVERT ( data_type [ ( length ) ] , expression [ , style ] )

4.2、参数

sql 复制代码
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 的内容。

sql 复制代码
SELECT
    CASE WHEN TRY_CONVERT(FLOAT, 'test') IS NULL
    THEN 'Cast failed'
    ELSE 'Cast succeeded'
END AS Result;
GO

以下示例演示表达式必须采用所需的格式。

sql 复制代码
SET DATEFORMAT DMY; -- 设置错误的格式返回NULL
SELECT TRY_CONVERT(DATETIME2, '11/28/2024') AS Result;
GO
-- 返回执行结果
Result
---------------------------
NULL

(1 行受影响)

4.5.2、TRY_CONVERT 将失败,并出现错误

下面的示例演示显式不允许强制转换时 TRY_CONVERT 返回错误。

sql 复制代码
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 成功

此示例演示表达式必须采用所需的格式。

sql 复制代码
SET DATEFORMAT MDY;
SELECT TRY_CONVERT(DATETIME2, '12/31/2024') AS Result;
GO
-- 返回执行结果
Result
---------------------------
2024-12-31 00:00:00.0000000

(1 行受影响)
相关推荐
amao99882 分钟前
数据库--dataset design
数据库
山沐与山42 分钟前
【数据库】PostgreSQL架构与索引深度剖析
数据库·postgresql·架构
不穿格子的程序员1 小时前
Redis篇6——Redis深度剖析:从单机到集群,Redis高可用进化史
数据库·redis·集群·主从·高可用·哨兵
阿坤带你走近大数据1 小时前
什么是元数据管理?(附具体实施方案供参考)
数据库·金融
俊男无期1 小时前
超效率工作法
java·前端·数据库
2301_823438021 小时前
【无标题】解析《采用非对称自玩实现强健多机器人群集的深度强化学习方法》
数据库·人工智能·算法
中国胖子风清扬2 小时前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
Elastic 中国社区官方博客2 小时前
Elasticsearch:你是说,用于混合搜索(hybrid search)
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
czlczl200209252 小时前
高并发下的 Token 存储策略: Redis 与 MySQL 的一致性
数据库·redis·mysql
虹科网络安全2 小时前
艾体宝产品 | 基准测试:ArangoDB性能碾压Neo4j,速度最高提升8倍!
数据库·neo4j