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 行受影响)
相关推荐
阑梦清川19 分钟前
JavaEE进阶-----mybatis操作数据库(新手教程)
数据库·java-ee·mybatis
NLP的小Y22 分钟前
Neo4j图形数据库-Cypher中常用指令
数据库·neo4j
Mar_mxs28 分钟前
Linux环境下配置neo4j图数据库
linux·数据库·neo4j
小狮子安度因32 分钟前
Qt数据库操作-QSqlQueryModel 的使用
数据库·qt·oracle
ABILI .35 分钟前
Oracle对比表与表之间的结构
数据库·oracle
小登ai学习36 分钟前
Mybatis
数据库·oracle·mybatis
施嘉伟38 分钟前
PostgreSQL WAL日志膨胀处理
运维·数据库·postgresql
Loongnoy1 小时前
MySQL乐观锁
数据库·mysql
无敌岩雀1 小时前
【MySQL】事务详解
数据库·mysql
问道飞鱼1 小时前
【数据库知识】数据库关系代数表达式
数据库·关系代数