为什么尝试将 VARCHAR 转换为 UNIQUEIDENTIFIER 时 TRY_CAST 会抛出错误?

Joe*_*ish 7 sql-server type-conversion

我的表中有一个 VARCHAR(MAX) 列,可以存储多种不同格式的数据,包括 GUID 格式。在加入另一个表中的 UNIQUEIDENTIFIER 列时,我尝试了以下代码:

TRY_CAST(b.val AS uniqueidentifier) = a.guid_col
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

消息 8152,第 16 级,状态 10,第 73 行

字符串或二进制数据将被截断。

TRY_CAST的文档确实指出在某些情况下可能会引发错误:

但是,如果您请求明确不允许的转换,则 TRY_CAST 会失败并出现错误。

但是,SQL Server 允许从 VARCHAR 到 UNIQUEIDENTIFIER 的转换:

在此输入图像描述

我能够找到引发错误的示例值。该值很长,因此我在其中包含了fiddle。有用的评论者提供了该问题的更简单的再现:

DECLARE @s VARCHAR(MAX) = REPLICATE(CAST('A' AS VARCHAR(MAX)), 8001);

SELECT TRY_CAST(@s AS UNIQUEIDENTIFIER);
Run Code Online (Sandbox Code Playgroud)

当尝试将某些 VARCHAR 值转换为 UNIQUEIDENTIFIER 时,为什么 TRY_CAST 会抛出错误而不是返回 NULL 值?

Pau*_*ite 10

文档中的转换表不区分 和varcharvarchar(max)尽管和文档的另一部分说:CASTCONVERT

大值数据类型

大值数据类型与其较小的对应数据类型具有相同的隐式和显式转换行为 - 具体来说, nvarchar varbinaryvarchar数据类型。但是,请考虑以下准则:

  • 从大值数据类型(例如varchar(max) )到较小的对应数据类型(例如varchar )的转换是隐式转换,但如果大值的大小超过较小数据类型的指定长度,则会发生截断。

同样相关,来自char 和 varchar

当字符表达式转换为不同大小的字符数据类型时,对于新数据类型来说太长的值将被截断。为了从字符表达式进行转换,uniqueidentifier类型被视为字符类型,因此要遵守转换为字符类型的截断规则。

当您varchar(max)TRY_*具有非最大值类型的函数提供 a 作为目标时,系统会尝试将大值转换为非最大值字符串。如果成功的话,一切都好。如果没有,您会收到“字符串或二进制数据将被截断”。错误,因为最大字符串不适合。这与上面的文档相反,上面指出发生了截断。

我自己的经验是,max数据类型有时确实有不遵循转换图表或详细文档的行为。

此行为并非特定于uniqueidentifier,问题中的演示将因其他类型(例如bigint或 )而失败date

我的记忆是,对于兼容的类型(不包括大型类型),TRY_*它将可靠地工作。sql_variant您还可以使用 try 函数在 max 类型之间进行转换,但并不总是从 max 类型转换为非 max 类型。

从用户体验的角度来看,这并不理想。我不知道这是文档错误还是意外行为。

作为解决方法,您可以在尝试转换之前将 LOB 文本转换为 GUID 字符串表示形式的长度:

DECLARE @s varchar(max) = REPLICATE(CONVERT(varchar(max), 'A'), 8001);

-- No error
SELECT TRY_CONVERT(uniqueidentifier, CONVERT(char(36), @s));
Run Code Online (Sandbox Code Playgroud)

现有的Microsoft 反馈项目

相关问答: