字符串或二进制数据将在表 '******'、列 '******' 中被截断。截断值:'*****'

Hen*_*sen 10 sql-server azure-sql-database errors

我们的应用程序之一报告错误消息 2628:

string or binary data would be truncated in table '******', column '******'. Truncated value: '******'

代替

String or binary data would be truncated in table 'mytable', column 'mycolumn'. Truncated value: 'myvalue'.

我用 SSMS 得到的。

我需要更改什么设置才能获得完整的消息?

我试图搜索这个,但我得到的只是我需要将 VERBOSE_TRUNCATION_WARNINGS 设置为 ON,并将 compatible_level 设置为 150。我很久以前就这样做了。

该应用程序具有以下错误处理程序:

 try
     {
         ES.isWorking = true;
         Worker worker = new Worker(new DBConnection(Settings.ConnectionString));
         worker.DoWork();
         ES.isWorking = false;
     }
 catch (Exception ex)
     {
         ES.isWorking = false;
         this.eventLog.WriteEntry("In OnTimer exception ! message: " + ex.Message.ToString());
         errorHandler.HandleException(ex, "In OnTimer exception !", ErrorSeverities.Error);
     }
Run Code Online (Sandbox Code Playgroud)

errorHandler 看起来像这样

Public Function HandleException(ByVal incommingEx As System.Exception,
                                   ByVal note As String,
                                   ByVal errorSeverity As ErrorSeverities,
                                   Optional ByVal sessionId As String = "",
                                   Optional ByVal applicationSource As String = "",
                                   Optional ByVal ignoreDB As Boolean = False,
                                   Optional ByVal noMail As Boolean = False) As Integer
    Dim stackTraceBuilder As New System.Text.StringBuilder
    Dim targetSite As String = ""
    Dim errorTime As DateTime = Now
    Dim messageBuilder As New System.Text.StringBuilder
    Dim innerEx As Exception = incommingEx.InnerException
    Dim errorId As Integer = 0
    Dim innerCount As Integer = 1
    Dim loggedToDb As Boolean = False
    Dim appSource As String = Me._applicationSource
    If applicationSource <> "" Then
        appSource = applicationSource
    End If
    '... more code'

    messageBuilder.AppendLine("(" + incommingEx.GetType.Name.ToUpper + ")" + vbCrLf + incommingEx.Message + " - SOURCE: " + incommingEx.Source)
    '...'
    While Not innerEx Is Nothing And innerCount <= 5
        messageBuilder.AppendLine("INNER" + Convert.ToString(innerCount) + " (" + innerEx.GetType.Name.ToUpper + "):" + vbCrLf + **innerEx.Message** + " - SOURCE: " + innerEx.Source)
        If Not innerEx Is Nothing AndAlso Not innerEx.StackTrace Is Nothing Then
            stackTraceBuilder.AppendLine("INNER" + Convert.ToString(innerCount) + ": " + innerEx.StackTrace) 'Me.GetNumberedStack(innerEx))
        End If
        innerEx = innerEx.InnerException
        innerCount += 1
    End While
    '... more code where the error message is inserted in a log table, via a sproc'
End Function
Run Code Online (Sandbox Code Playgroud)

我们以前从未见过这种行为,我们最近将 .net 框架更新到了 4.7.2 版,所以它可能是相关的。

错误文本“字符串或二进制”来自该位

  • innerEx.Message + 这是一个简单的内置异常数据类型。因此,构建字符串的是 VB 和/或 .net 和/或 SQL Server,而不是我们。

该错误发生在调用存储过程之后,其中用户可能输入了 varchar(1000) 文本。存储过程增加了一点,表没有空间容纳所有 1100 个字节。因此错误。存储过程没有 try-catch 块。

Jos*_*ell 13

看起来这个表是用动态数据屏蔽定义的,应用程序用来访问数据库的用户没有查看屏蔽数据的权限(这很好!)。

这就是应用程序和 SSMS 之间的行为不同的原因:我希望您在从 SSMS 运行查询时使用更高权限的用户

这是一个演示:

CREATE TABLE dbo.Test
(
    Id int IDENTITY PRIMARY KEY,
    Filler varchar(100) MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)') NULL
);
GO

CREATE USER TestUser WITHOUT LOGIN;  
GRANT SELECT ON dbo.Test TO TestUser;  
GRANT INSERT ON dbo.Test TO TestUser;
GO

EXECUTE AS USER = 'TestUser';
INSERT dbo.Test 
    (Filler)
VALUES
    (REPLICATE(N'A', 101)); 
REVERT;
Run Code Online (Sandbox Code Playgroud)

其结果是:

CREATE TABLE dbo.Test
(
    Id int IDENTITY PRIMARY KEY,
    Filler varchar(100) MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)') NULL
);
GO

CREATE USER TestUser WITHOUT LOGIN;  
GRANT SELECT ON dbo.Test TO TestUser;  
GRANT INSERT ON dbo.Test TO TestUser;
GO

EXECUTE AS USER = 'TestUser';
INSERT dbo.Test 
    (Filler)
VALUES
    (REPLICATE(N'A', 101)); 
REVERT;
Run Code Online (Sandbox Code Playgroud)

要在应用程序中获取完整消息,您需要授予用户UNMASK权限:

GRANT UNMASK TO TestUser;
Run Code Online (Sandbox Code Playgroud)

INSERT再次运行代码会得到完整的错误文本:

Msg 2628, Level 16, State 1, Line 12
String or binary data would be truncated in table '******', column '******'. Truncated value: '******'.
Run Code Online (Sandbox Code Playgroud)

使用 Azure SQL 数据库时,还可以在 Azure 门户用户界面中配置动态数据屏蔽。您可能想在那里检查(尽管据我所知,以这种方式设置的掩码仍然会更新sys.columns元数据):

Azure 门户中设置的动态数据屏蔽规则的屏幕截图

我还会检查 Azure 中是否还有其他属于同一逻辑 SQL Server 实例的其他数据库——也许正在进行某种奇怪的跨数据库查询。


小智 7

我认为这与 Azure SQL 数据库(仅)中一个新的和未充分报告的错误有关,当错误 245 和 2628 发生时,临时表的处理方式与普通表不同。


Hen*_*sen 7

我发现我已经将敏感度分类添加到我所有的临时表中,(并且只添加到我的一些非临时表中)。

add SENSITIVITY CLASSIFICATION to dbo.Mytable.name with (LABEL = 'General', INFORMATION_TYPE = 'Public')
Run Code Online (Sandbox Code Playgroud)

当我删除敏感度分类时,旧的错误消息又回来了。

我有一个演示错误的示例:

drop table if exists dbo.mytable
go
create table dbo.Mytable (i int not null identity(1,1) primary key clustered, name varchar(10) not null)
go
insert into dbo.Mytable ( name ) values ( 'abc' )
go
select * from dbo.Mytable where name = 1  -- programming error; data type mis-match
Run Code Online (Sandbox Code Playgroud)

返回

(1 row affected)
Msg 245, Level 16, State 1, Line 8
Conversion failed when converting the varchar value 'abc' to data type int.
Run Code Online (Sandbox Code Playgroud)

这是正确的错误消息。现在运行这个:

add SENSITIVITY CLASSIFICATION to dbo.Mytable.name with (LABEL = 'General', INFORMATION_TYPE = 'Public')
Run Code Online (Sandbox Code Playgroud)

当你运行这个

select * from dbo.Mytable where name = 1 -- programming error; data type mis-match
Run Code Online (Sandbox Code Playgroud)

你会看到这个

Msg 245, Level 16, State 1, Line 169
Conversion failed when converting the ****** value '******' to data type ******.
Run Code Online (Sandbox Code Playgroud)

这是不正确的错误消息。

我已经在 Azure SQL 数据库上尝试了此代码,在那里我收到了不正确的消息,在 SQL Server 2019 CU6 上,我只收到了正确的消息。

我已经向微软报告了这个问题,他们已经承认这是一个错误,它将在几个月内修复。

我创建了两个脚本来 1) 记录现有分类,以及 2) 删除所有这些分类。

脚本可以在这里找到: 文档和删除分类


Raz*_*col 6

错误消息中的屏蔽也可能发生在与动态数据屏蔽(或时态表)无关的场景中。请参阅以下示例:

CREATE DATABASE ErrorMessageTest
GO
USE ErrorMessageTest
GO
CREATE USER SimpleUser WITHOUT LOGIN
GO
ALTER ROLE db_datareader ADD MEMBER SimpleUser
GO
CREATE FUNCTION dbo.Numbers(@MaxNumber int)
RETURNS TABLE AS RETURN
 WITH Nbrs_4( n ) AS ( SELECT 1 UNION SELECT 0 ),
          Nbrs_3( n ) AS ( SELECT 1 FROM Nbrs_4 n1 CROSS JOIN Nbrs_4 n2 ),
          Nbrs_2( n ) AS ( SELECT 1 FROM Nbrs_3 n1 CROSS JOIN Nbrs_3 n2 ),
          Nbrs_1( n ) AS ( SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2 ),
          Nbrs_0( n ) AS ( SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2 ),
          Nbrs  ( n ) AS ( SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2 )
        SELECT n
          FROM ( SELECT ROW_NUMBER() OVER (ORDER BY n)
                   FROM Nbrs ) D ( n )
         WHERE n <= @MaxNumber ;
GO
CREATE FUNCTION dbo.Split(@Param nvarchar(MAX),@Separator NCHAR(1))
RETURNS TABLE AS RETURN 
SELECT SUBSTRING(@Param, N, CHARINDEX(@Separator, @Param + @Separator, n) - n) AS VALUE, 
    ROW_NUMBER() OVER (ORDER BY N) AS Position
FROM dbo.Numbers(LEN(@Param)) n
WHERE SUBSTRING(@Separator + @Param, n, 1) = @Separator

GO
EXECUTE AS USER='SimpleUser'

DECLARE @ApplyToMonth NVARCHAR(101) = '1,2,3,4,5,6, test error message,8'

SELECT t.VALUE AS OriginalValue, TRY_CAST(REPLACE(t.VALUE, ' ', '') AS INT) AS IntValue
    FROM dbo.Split(@ApplyToMonth, ',') t
SELECT    x.OriginalValue, x.IntValue,
        CASE WHEN x.IntValue IS NULL THEN CAST(x.OriginalValue AS INT) ELSE 0 END AS RaisErrorColumn
FROM (
    SELECT t.VALUE AS OriginalValue, TRY_CAST(REPLACE(t.VALUE, ' ', '') AS INT) AS IntValue
    FROM dbo.Split(@ApplyToMonth, ',') t
) x

GO
REVERT
GO
USE master
GO
DROP DATABASE ErrorMessageTest
Run Code Online (Sandbox Code Playgroud)

在 SQL Server 2016 和 SQL Server 2017 中,这会产生以下错误消息:

Conversion failed when converting the ****** value '******' to data type ******.
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,这种情况下的解决方案与其他情况相同: GRANT UNMASK TO SimpleUser

我倾向于说这是一个错误,因为在 SQL Server 2019 CU5 中,我收到了完整的错误消息(没有授予 UNMASK):

Conversion failed when converting the nvarchar value ' test error message' to data type int.
Run Code Online (Sandbox Code Playgroud)


Sol*_*zky 5

您看到的行为(即元数据***在非sysadmin/非dbo帐户的错误消息中被替换)似乎是跟踪标志 3625: Metadata Visibility Configuration 的影响。我没有可用于测试的 Azure 帐户,但文档确实表明此功能在 Azure SQL 数据库中可用。

一种不太可能的可能性(实际上,此时甚至不应该)是有人为 配置了短暂的(谢天谢地!)“功能限制”选项ERRORMESSAGE,这实际上与跟踪标志 3625 相同。我相信有几个月,当“功能限制”功能被逐步淘汰时,它可能之前已配置但不再完全可访问。但是,最迟应在 2020 年 3 月 4 日之前(从 Azure SQL 数据库中)100% 删除该功能。