sql - 当没有 INSERT 语句时,为什么我得到 "String or Binary Data would be Truncated Error"?

标签 sql sql-server tsql sql-server-2012 truncation

我有这个问题:

USE [SomeDatabase];
GO

DECLARE @percentageValue decimal(15,4) = 1.50; 

SELECT a.ID, a.Amount, a.Status 
FROM [dbo].ATable as a          
INNER JOIN [dbo].BTable as b 
  ON a.LinkToB = b.ID
INNER JOIN [OtherDatabase].[dbo].CTable as value 
  ON value.[Key] = CONCAT(N'APrefixAboutThisLongThatsNecessaryBecauseDontAsk',b.AltID)
WHERE a.Status = N'SomeStatus'
AND a.Amount > (COALESCE(TRY_CONVERT(DECIMAL(15,2), value.Value), 0)*@percentageValue);
GO

(为保密起见,实际列名已编辑)

我得到的是传统的: “消息 8152,第 16 级,状态 10,第 3 行 字符串或二进制数据将被截断。” 错误。 Google 告诉我,我正在尝试在一个太小的列中插入一些内容,这是有道理的。

但是,这不是 INSERT 操作(这实际上是我查询的所有 SQL),所以我无法终生检测截断发生的位置或为什么。我认为这是 Transact-SQL 的核心内容,但最奇怪的问题是,尽管出现错误,我还是从查询中获得了结果。

根据要求,这是表架构的相关部分。

USE [SomeDatabase]

CREATE TABLE [dbo].[ATable](
    [ID] [uniqueidentifier] NOT NULL,
    [Amount] [decimal](15, 2) NOT NULL,
    [Status] [nvarchar](32) NOT NULL,
    [LinkToB] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
))
GO

CREATE TABLE [dbo].[BTable](
    [ID] [uniqueidentifier] NOT NULL,
    [AltID]  [uniqueidentifier] NOT NULL
 CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
))
GO

USE [OtherDatabase]
GO

CREATE TABLE [dbo].[CTable](
    [ID] [uniqueidentifier] NOT NULL,
    [Key] [nvarchar](100) NOT NULL,
    [Value] [nvarchar](max) NOT NULL)
CONSTRAINT [PK_TableC] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)

最佳答案

好的,一旦你知道了这个 secret ,这个就很有趣了。

正如评论(和架构)中所述,value.Value 是一个 nvarchar(max)。这是传统的键值反模式,用于存储您不想存储在特定位置的数据。现在,我们在此列上运行 try_convert(nvarchar(max)),但这很好,因为

 ON Key = N'SomethingSpecific'

子句意味着它只在 Key=N'SomethingSpecific' 行上运行 try_convert,对吗?

对吗?

没有。

根据表中的数据,执行计划可以选择try_convert列中的每一个值。而nvarchar(max)中的一行是超出 try_convert 参数的容量。因此崩溃。这也解释了为什么我得到了我期望的所有结果,它正在评估这些结果,然后在我期望它忽略的数据行上崩溃。

更好的是,不相关的数据或结构更改可以改变执行计划的行为,所以这个错误可以很容易地“海森错误”并消失给更多/更少的数据,对结构的微小更改,并且在一次调试过程中,我很确定 空格

那么最简单的解决方案是什么?将配置值放入变量中,分别用于 try_convert,并使用它来代替。

对于任何设计数据库或编写数据库代码的人:

  • 不要在 SQL where 子句中操作数据类型
  • 不要使用一列来存储截然不同的数据类型并编写复杂的转换例程来处理问题
  • 请为您的数据使用正确的数据类型,并将具有正确数据类型的其他表视为良好
  • 请记住,SQL 函数通常在后台执行类似 INSERT 的操作

关于sql - 当没有 INSERT 语句时,为什么我得到 "String or Binary Data would be Truncated Error"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25813425/

相关文章:

mysql - 从 sql server 表创建 mysql View

sql-server - 如何使用 T-SQL 从过程中返回空结果集?

php - 当INSERT语句包含引号时如何导入sql文件

mysql - 使用 JOIN 和 HABTM 关联连接三个表

mysql - SQL中2个选择之间的区别

mysql - MySql 中的@@DBTS

mysql - 获取每个ID的最新记录

sql - 在存储过程中,是简单地查询数据还是构造一个查询然后执行它更好?为什么?

sql - 一次运行 1000 个查询的大量更新查询的最佳方法

sql - 将结果动态透视到临时表