MSSQLSERVER_2570

适用于:SQL Server

详细信息

属性 Value
产品名称 SQL Server
事件 ID 2570
事件源 MSSQLSERVER
组件 SQLEngine
符号名称 DBCC_COLUMN_VALUE_OUT_OF_RANGE
消息正文 页面P_ID、对象 ID O_ID、索引 ID I_ID、分区 ID PN_ID、分配单位 ID A_ID(类型类型)中的槽S_ID。 列COLUMN_NAME值与数据类型“DATATYPE”的范围不一。 请将该列更新为合法的值。

说明

指定列中包含的列值超出了列数据类型的可能值范围。 如果表列中的数据无效,则可能会遇到问题,具体取决于针对无效数据执行的操作类型。 但是,在执行或DBCC CHECKDBDBCC CHECKTABLE命令之前,也可能出现任何问题,并且不会发现无效数据。

由于存在无效数据,你可能会注意到某些症状(但包括但不限于):

  • 对受影响的列执行查询时,访问冲突或其他异常。
  • 针对受影响的列执行的查询返回的结果不正确。
  • 针对受影响的列生成统计信息时出错或问题。
  • 错误消息,如下所示:

    检测到 Msg 9100、Level 23、State 2、LineNum <> 可能索引损坏。 请运行 DBCC CHECKDB。

DATA_PURITY检查

执行 DBCC CHECKDBDBCC CHECKTABLE 命令时,SQL Server 对数据库中每个表的每一行中的列值执行“数据纯洁”验证。 执行这些检查以确保存储在列中的值有效。 也就是说,验证可确保值不在与列的数据类型关联的域范围内。 执行的验证的性质取决于列的数据类型。 以下非详尽列表提供了一些示例:

列数据类型 执行的数据验证类型
Unicode 字符 数据长度应为 2 的倍数。
Datetime 日期字段应介于 1753 年 1 月 1 日和 9999 年 12 月 31 日之间。 时间字段必须早于“11:59:59.997PM”。
实际和浮点数 检查是否存在无效的浮点值,例如 SNAN、QNAN、NINF、ND、PD 和 PINF。

并非所有数据类型都会检查列数据的有效性。 仅检查可能具有范围外存储值的那些值。 例如, tinyint 数据类型的有效范围为 0 到 255,并且存储在单个字节中(只能存储介于 0 到 255 之间的值),因此检查值不是必需的。

注意

默认情况下启用这些检查,并且无法禁用,因此在执行或DBCC CHECKTABLE命令时DBCC CHECKDB无需显式使用 DATA_PURITY 选项。 但是,如果使用 PHYSICAL_ONLY 选项, DBCC CHECKDBDBCC CHECKTABLE不会执行数据纯洁检查。

DATA_PURITY问题报告

如果执行启用了选项的或DBCC CHECKDBDBCC CHECKTABLE命令DATA_PURITY(或者自动运行数据纯度检查),并且命令检查DBCC的表中存在无效数据,输出DBCC将包含指示与数据相关的问题的其他消息。 以下示例错误消息指示数据纯洁性问题:

DBCC results for "account_history". 
Msg 2570, Level 16, State 2, Line <LineNum> 
Page (1:1073), slot 33 in object ID <ObjectID>, index ID 0, partition ID <PartitionID>, alloc unit ID <UnitID> (type "In-row data"). Column "account_name" value is out of range for data type "nvarchar". Update column to a legal value. 
 
Msg 2570, Level 16, State 2, Line <LineNum> 
Page (1:1156), slot 120 in object ID <ObjectID>, index ID 0, partition ID <PartitionID>, alloc unit ID <UnitID> (type "In-row data"). Column "account_name" value is out of range for data type "nvarchar". Update column to a legal value.
There are 153137 rows in 1080 pages for object "account_history". 
CHECKDB found 0 allocation errors and 338 consistency errors in table "account_history" (object ID <ObjectID>). 
CHECKDB found 0 allocation errors and 338 consistency errors in database '<DatabaseName>'. 
DBCC execution completed. If DBCC printed error messages, contact your system administrator. 

DBCC results for 'table1'. 
Msg 2570, Level 16, State 3, Line <LineNum> 
Page (1:154), slot 0 in object ID <ObjectID>, index ID 0, partition ID <PartitionID>, alloc unit ID <UnitID> (type "In-row data"). Column "col2" value is out of range for data type "real". Update column to a legal value. 
There are 4 rows in 2 pages for object "table1". 
CHECKDB found 0 allocation errors and 1 consistency errors in table 'table1' (object ID <ObjectID>). 
CHECKDB found 0 allocation errors and 1 consistency errors in database 'realdata'. DBCC execution completed. If DBCC printed error messages, contact your system administrator. 

DBCC results for 'table2'. 
Msg 2570, Level 16, State 3, Line <LineNum> 
Page (1:155), slot 0 in object ID <ObjectID>, index ID 0, partition ID <PartitionID>, alloc unit ID <UnitID> (type "In-row data"). Column "col2" value is out of range for data type "decimal". Update column to a legal value. 
There are 4 rows in 1 pages for object "table2". 
CHECKDB found 0 allocation errors and 1 consistency errors in table 'table2' (object ID <ObjectID>). 
CHECKDB found 0 allocation errors and 1 consistency errors in database 'realdata'. DBCC execution completed. If DBCC printed error messages, contact your system administrator. 

DBCC results for 'table3'. 
Msg 2570, Level 16, State 3, Line <LineNum> 
Page (1:157), slot 0 in object ID <ObjectID>, index ID 0, partition ID <PartitionID>, alloc unit ID <UnitID> (type "In-row data"). Column "col2" value is out of range for data type "datetime". Update column to a legal value. 
There are 3 rows in 1 pages for object "table3". 
CHECKDB found 0 allocation errors and 1 consistency errors in table 'table3' (object ID <ObjectID>). 
CHECKDB found 0 allocation errors and 1 consistency errors in database 'realdata'. DBCC execution completed. If DBCC printed error messages, contact your system administrator. 

For every row that contains an invalid column value, a 2570 error is generated. 

原因

无效或超出范围的数据可能已存储在 SQL Server 数据库中,原因如下:

  • 通过远程过程调用 (RPC) 事件将数据插入 SQL Server 中无效。
  • 物理数据损坏的其他潜在原因使列值无效。

修复数据纯洁问题

无法使用任何 DBCC 修复选项修复 2570 错误。 原因是 DBCC 无法确定应使用什么值替换无效的列值。 因此,必须手动更新列值。 若要执行手动更新,必须找到有问题的行。 使用以下方法之一查找行:

  • 对包含无效值的表执行查询,以查找包含无效值的行。
  • 使用错误 2570 中的信息来标识具有无效值的行。

以下部分详细介绍了这两种方法,并提供示例来查找具有无效数据的行。

找到正确的行后,需要对将用于替换现有无效数据的新值做出决策。 必须根据适用于应用程序的值范围以及该特定数据行的逻辑含义,仔细做出此决定。 您有下列选择:

  • 如果知道它应该是什么值,请将其设置为该特定值。
  • 将其设置为可接受的默认值。
  • 将列值设置为 NULL.
  • 将列值设置为该列的数据类型的最大值或最小值。
  • 如果认为没有列的有效值,特定行无效,请完全删除该行。

使用 T-SQL 查询查找具有无效值的行

需要执行的查询类型来查找具有无效值的行取决于报告问题的列的数据类型。 如果查看 2570 错误消息,你将注意到两条有助于解决此问题的重要信息。 在下面的示例中,列 account_name 的值是数据类型 nvarchar的范围不足。 我们可以轻松地识别存在问题的列和涉及的列的数据类型。 因此,一旦你知道数据类型和涉及的列,就可以制定查询来查找包含该列无效值的行,并选择标识该行(作为子句中的谓词)以进一 WHERE 步更新或删除这些行。

Unicode 数据类型
SELECT col1, DATALENGTH(account_name) AS Length, account_name  
FROM account_history 
WHERE DATALENGTH(account_name) % 2 != 0
Float 数据类型

通过更改为实际主键列(s)、col2从 2570 错误到col1列以及table1输出中的CHECKDB表来运行以下代码片段。

SELECT col1, col2 FROM table1 
WHERE col2<>0.0 AND (col2 < 2.23E-308 OR col2 > 1.79E+308) AND (col2 < -1.79E+308 OR col2 > -2.23E-308)
实际数据类型

通过更改为实际主键列(s)、col2从 2570 错误到col1列以及table1输出中的CHECKDB表来运行以下代码片段。

SELECT col1, col2 FROM testReal  
WHERE col2<>0.0 AND (col2 < CONVERT(real,1.18E-38) OR col2 > CONVERT(real,3.40E+38)) AND (col2 < CONVERT(real,-3.40E+38) OR col2 > CONVERT(real,-1.18E-38))  
ORDER BY col1; -- checks for real out of range 
十进制和数值数据类型
SELECT col1 FROM table2 
WHERE col2 > 9999999999.99999  
OR col1 < -9999999999.99999

请记住,你需要根据已定义 decimalnumeric 列的精度和小数位数调整值。 在上面的示例中,列定义为 col2 decimal(15,5)

Datetime 数据类型

需要执行两个不同的查询来标识包含列无效值的 datetime 行。

SELECT col1 FROM table3 
WHERE col2 < '1/1/1753 12:00:00 AM' OR col2 > '12/31/9999 11:59:59 PM' 

SELECT col1 FROM table3 WHERE 
((DATEPART(ms,col2)+ (1000*DATEPART(s,col2)) + (1000*60*DATEPART(mi,col2)) + (1000*60*60*DATEPART(hh,col2)))/(1000*0.00333))  > 25919999

使用物理位置查找具有无效值的行

如果使用 T-SQL 方法找不到具有无效值的行,则可以使用此方法。 在 2570 错误消息中,打印包含无效值的行的物理位置。 例如,查看以下消息:

Page (1:157), slot 0 in object ID <ObjectID>, index ID 0, partition ID <PartitionID>, alloc unit ID <UnitID> (type "In-row data"). Column "col2" value is out of range for data type "datetime". Update column to a legal value. 

在此消息中,你会注意到 Page (1:157), slot 0。 这是标识行所需的信息。 是FileId,是,也是SlotId0157PageInFile1

获取此信息后,需要执行以下命令:

DBCC TRACEON (3604)
DBCC PAGE (realdata , 1 , 157 , 3)

注意

此命令打印页面的全部内容。 命令的参数 DBCC PAGE 包括:

  • Database name:数据库的名称。
  • File number:数据库文件的文件编号。
  • Page number:要检查的页码。
  • Print option:一个可选参数,用于确定输出详细信息级别。

执行此命令后,你会注意到一个输出,其中包含类似于以下格式的信息:

Slot 0  Offset 0x60 Length 19
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
Memory Dump @0x44D1C060
00000000: 10001000 01000000 ffffffff ffffffff †................
00000010: 0200fc†††††††††††††††††††††††††††††††...
Slot 0 Column 0  Offset 0x4 Length 4  col1 = 1
Slot 0 Column 1  Offset 0x8 Length 8  col2 = Dec 31 1899 19:04PM
Slot 1 Offset 0x73 Length 19
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
Memory Dump @0x44D1C073
00000000: 10001000 02000000 0ba96301 f8970000 †..........c.....
00000010: 0200fc†††††††††††††††††††††††††††††††...
Slot 1 Column 0 Offset 0x4 Length 4 col1 = 2
Slot 1 Column 1 Offset 0x8 Length 8 col2 = Jul 8 2006 9:34PM
Slot 2 Offset 0x86 Length 19
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
Memory Dump @0x44D1C086
00000000: 10001000 03000000 0ba96301 f8970000 †..........c.....
00000010: 0200fc†††††††††††††††††††††††††††††††... 
Slot 2 Column 0 Offset 0x4 Length 4 col1 = 3
Slot 2 Column 1 Offset 0x8 Length 8 col2 = Jul 8 2006 9:34PM

在此输出中,可以清楚地看到感兴趣的行的列值。 在这种情况下,需要存储在 slot 0 页面中的行。 从错误消息中,你知道 col2 这是有问题的错误消息。 因此,你可以获取其值col1Slot 0并将其用作 update 语句的子句中的WHERE谓词或删除语句。

警告

建议使用第一种方法(即使用 T-SQL 查询查找所需的信息)。 仅使用 DBCC PAGE 命令作为最后手段。 在生产环境中使用此命令时,请特别注意。 建议在测试服务器上还原生产数据库,使用 DBCC PAGE所需的所有信息,然后在生产服务器上执行更新。 与往常一样,请确保在发生错误时保留备份就绪,并且需要还原到数据库的早期副本。

另请参阅