-
通过运行
DBCC TRACEON(139, -1)
启用跟踪标志 139。
-
运行
DBCC CHECKDB/TABLE
和
CHECKCONSTRAINTS
命令。
-
通过运行
DBCC TRACEOFF(139, -1)
禁用跟踪标志 139。
-
将 SQL Server 2016) 的数据库兼容级别更改为 130 (,将 2017 SQL Server 和 Azure SQL 数据库) (更改为 140 (。
-
重新生成在步骤 1 中标识的任何结构。
Azure SQL数据库中的跟踪标志 Azure SQL 数据库中不支持设置跟踪标志。 因此,在执行验证之前,必须更改兼容性级别:
-
将数据库兼容级别升级到 140。
-
验证以识别任何受影响的持久化结构。
-
重新生成在步骤 2 中标识的结构。
-
附录 A
包含所有精度改进的详细列表,并提供了每个改进的示例。
-
附录 B
包含执行验证和重新生成任何受影响的结构的详细分步过程。
-
附录 C
和
附录 D
包含有助于查明数据库中可能受影响的对象的脚本。 因此,可以限定验证范围并生成相应的脚本来运行检查。 若要最轻松地确定数据库中的任何持久结构是否受到兼容性级别 130 精度改进的影响,请运行
附录 D
中的脚本以生成正确的验证检查,然后运行此脚本进行验证。
附录 A:兼容性级别 130 中的更改
本附录提供了兼容性级别 130 中对表达式计算的改进的详细列表。 每个更改都包含一个关联的示例查询。 查询可用于显示在使用 130 之前的兼容级别的数据库中执行与使用兼容级别 130 的数据库之间的差异。
下表列出了数据类型转换和其他操作。
数据类型转换
兼容性级别 < 130 的结果
兼容性级别的结果 = 130
float
、
real
、
numeric
、
decimal
、
money
或
smallmoney
datetime
或
smalldatetime
提高舍入精度。 以前,日期和时间是单独转换的,结果在合并之前被截断。
DECLARE @f FLOAT = 1.2 DECLARE @d DATETIME = @f SELECT CAST(@d AS FLOAT)
1.19999996141975
datetime
bigint, int, or smallint
负日期时间,其时间部分正好为半天或半天的计时周期, (结果关闭 1) ,则错误地舍入。
DECLARE @h DATETIME = -0.5 SELECT @h, CAST(@h AS INT)
datetime
或
smalldatetime
float, real, numeric, money, or smallmoney
在某些情况下,提高了最后 8 位精度的精度。
DECLARE @p0 DATETIME = '1899-12-31 23:58:00.470' DECLARE @f FLOAT = CONVERT(FLOAT, @p0) SELECT @f, CAST(@f AS VARBINARY(8))
-0.00138344907407406,0xBF56AA9B21D85800
-0.00138344907407407407,0xBF56AA9B21D8583B
float
边界检查不太严格。
SELECT CAST (3.40282347000E+038 AS REAL)
3.402823E+38
numeric
、
money
和
smallmoney
float
当输入小数位数为零时,当你组合数值的四个部分时,会有舍入不精确性。
DECLARE @n NUMERIC(38, 0)= 41538374868278625639929991208632320 DECLARE @f FLOAT = CAST(@n AS FLOAT) SELECT CONVERT(BINARY(8), @f)
0x4720000000000000
0x4720000000000001
numeric
、
money
和
smallmoney
float
当输入刻度为非零时,当除以 10^scale 时,存在舍入不精度。
DECLARE @n NUMERIC(18, 10) = 12345678.0123456781 DECLARE @f FLOAT = CAST(@n AS FLOAT) SELECT CAST(@f AS BINARY(8))
0x41678C29C06522C4
0x41678C29C06522C3
real
或
float
在某些情况下,提高了舍入精度。
DECLARE @f float = 0.14999999999999999 SELECT CAST(@f AS numeric(1, 1))
real
或
float
在某些情况下,舍入到 16 位以上的数字时,提高了精度。
DECLARE @v decimal(38, 18) = 1E-18 SELECT @v
0.000000000000000000
0.000000000000000001
real
或
float
money
或
smallmoney
在某些情况下,转换大数时的准确度有所提高。
DECLARE @f float = 2SET @f = POWER(@f, 49) + POWER(@f, -2) SELECT CAST(@f AS money)
562949953421312.2048
562949953421312.25
(n)(var)char
numeric
超过 39 个字符的输入不再一定触发算术溢出。
DECLARE @value nchar(100) = '1.11111111111111111111111111111111111111' SELECT CAST(@value AS decimal(2,1))
(n)(var)char
支持前导空格和符号。
DECLARE @value nvarchar(100) = '1' SELECT CAST(@value AS bit)
将值“1”转换为
nvarchar
数据类型位时转换失败。
datetime
time
或
datetime2
提高了转换为具有更高精度的日期/时间类型的精度。 请注意,datetime 值存储为表示 1/300 秒的刻度。 较新的时间和 datetime2 类型存储离散数字,其中位数与精度匹配。
DECLARE @value datetime = '1900-01-01 00:00:00.003' SELECT CAST(@value AS time(7))
00:00:00.0030000
00:00:00.0033333
time
或
datetime2
datetime
在某些情况下改进了舍入。
DECLARE @value time(4) = '00:00:00.0045' SELECT CAST(@value AS datetime)
1900-01-01 00:00:00.007
1900-01-01 00:00:00.003
Operation
兼容性级别 <130 的结果
兼容性级别 130 的结果
RADIANS
使用使用数值数据类型的 或
DEGREES
内置函数。
DEGREES
除以 pi/180,其中它以前乘以 180/pi。 与
RADIANS
类似。
DECLARE @arg1 numeric = 1 SELECT DEGREES(@arg1)
57.295779513082323000
57.295779513082322865
当一个操作数的刻度大于结果刻度时,数值加法或减法。
舍入总是在加法或减法之后发生,而以前有时会发生舍入。
DECLARE @p1 numeric(38, 2) = -1.15 DECLARE @p2 numeric(38, 1) = 10 SELECT @p1 + @p2
CONVERT
具有
NULL
样式。
CONVERT
当目标类型为数值时,with
NULL
style 始终返回
NULL
。
SELECT CONVERT (SMALLINT, '0', NULL);
DATEPART
使用具有 datetime 数据类型的微秒或纳秒选项的 。
在转换为微秒或纳秒之前,值不再在毫秒级别被截断。
DECLARE @dt DATETIME = '01-01-1900 00:00:00.003'; SELECT DATEPART(MICROSECOND, @dt);
DATEDIFF
使用具有 datetime 数据类型的微秒或纳秒选项的 。
在转换为微秒或纳秒之前,值不再在毫秒级别被截断。
DECLARE @d1 DATETIME = '1900-01-01 00:00:00.003' DECLARE @d2 DATETIME = '1900-01-01 00:00:00.007' SELECT DATEDIFF(MICROSECOND, @d1, @d2)
datetime 和 datetime2 值与非零值(毫秒)之间的比较。
使用 datetime2 值运行比较时,不再在毫秒级别截断 Datetime 值。 这意味着之前比较相等的某些值不再比较相等。
DECLARE @d1 DATETIME = '1900-01-01 00:00:00.003' DECLARE @d2 DATETIME2(3) = @d1 SELECT CAST(@d1 AS datetime2(7)), @d2SELECT CASE WHEN (@d1=@d2) THEN 'equal' ELSE 'unequal' END
1900-01-01 00:00:00.0030000,1900-01-01 00:00:00.003 等于
1900-01-01 00:00:00.0033333, 1900-01-01 00:00:00.003 不平等
ROUND
使用数据类型的
float
函数。
舍入结果不同。
SELECT ROUND(CAST (-0.4175 AS FLOAT), 3)
-0.418
-0.417
附录 B:验证和更新持久化结构的步骤
建议确定数据库是否具有受兼容性级别 130 更改影响的任何持久结构,以及是否重新生成任何受影响的结构。
这仅适用于在较旧版本的 SQL Server 或通过使用低于 130 的兼容性级别在数据库中创建的持久结构。 可能受影响的持久化结构包括:
-
受约束约束的
CHECK
表数据
-
持久化计算列
-
在键列或包含列中使用计算列的索引
在这种情况下,请运行以下过程。
步骤 1:验证数据库兼容性级别
-
使用查看或更改数据库的兼容级别中所述的过程检查
数据库的兼容级别
。
-
如果数据库兼容级别低于 130,建议先执行步骤 2 中所述的验证,然后再将兼容级别提高到 130。
步骤 2:识别受影响的持久化结构
通过以下任一方式确定数据库是否包含受兼容性级别 130 中改进的精度和转换逻辑影响的任何持久结构:
-
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS
,用于验证数据库中的所有结构。
-
DBCC CHECKTABLE WITH EXTENDED_LOGICAL_CHECKS
,用于验证与单个表相关的结构。
需要 选项
WITH EXTENDED_LOGICAL_CHECKS
来确保持久化值与计算值进行比较,并标记存在差异的情况。 由于这些检查范围很广,因此使用此选项的语句的
DBCC
运行时比没有 选项的运行
DBCC
语句长。 因此,建议使用大型数据库
DBCC CHECKTABLE
来精确定位单个表。
DBCC CHECKCONSTRAINTS
可用于验证
CHECK
约束。 此语句可以在数据库或表级别使用。
DBCC CHECK
语句应始终在维护时段内运行,因为检查可能会对联机工作负荷造成影响。
数据库级验证
数据库级别的验证适用于小型和中等大小的数据库。 对大型数据库使用表级验证。
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS
用于验证数据库中的所有持久结构。
DBCC CHECKCONSTRAINTS
用于验证数据库中的所有
CHECK
约束。
DBCC CHECKCONSTRAINTS
用于验证约束的完整性。 使用以下脚本验证数据库:
USE [database_name]
DBCC TRACEON(139, -1)
DBCC CHECKCONSTRAINTS
DBCC TRACEOFF(139, -1)
使用跟踪标志可确保通过使用兼容性级别 130 中改进的精度和转换逻辑来执行检查,即使数据库的兼容级别较低,也会强制使用正确的转换语义。
CHECKCONSTRAINTS
如果语句已完成且未返回结果集,则无需执行其他操作。
如果 语句返回结果集,则结果中的每一行都表示违反约束,并且还包含违反约束的值。
- 保存表和约束的名称,以及导致冲突的值 (结果集中的
WHERE
列) 。
以下示例显示了一个 CHECK
具有约束的表,以及一行,该行满足较低兼容性级别下的约束,但违反了兼容级别 130 下的约束。
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=120
CREATE TABLE dbo.table1
c2 datetime,
c3 datetime,
c4 int,
CONSTRAINT chk1 CHECK (c4= (DATEDIFF (ms, c2,c3)))
INSERT dbo.table1 (c2, c3, c4) VALUES
convert(datetime, '1900-01-01 00:00:00.997'),
convert(datetime, '1900-01-01 00:00:01'), 3
DBCC TRACEON(139, -1)
DBCC CHECKCONSTRAINTS
DBCC TRACEOFF(139, -1)
该 CHECKCONSTRAINT
命令返回以下结果。
此结果指示“Where”中的列值组合违反了约束 [chk1]。
DBCC CHECKDB 与 EXTENDED_LOGICAL_CHECKS
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS
验证数据库中的所有持久结构。 这是最方便的选项,因为单个语句会验证数据库中的所有结构。 但是,由于 语句的预期运行时,此选项不适用于大型数据库。
使用以下脚本验证整个数据库:
USE [database_name]
DBCC TRACEON(139, -1)
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS
DBCC TRACEOFF(139, -1)
使用跟踪标志可确保通过使用兼容性级别 130 中改进的精度和转换逻辑来执行检查,即使数据库的兼容级别较低,也会强制使用正确的转换语义。
CHECKDB
如果语句成功完成,则无需执行其他操作。
如果语句完成并出现错误,请执行以下步骤:
- 将 SQL Server Management Studio (SSMS) 的消息窗格中的 语句执行
DBCC
结果保存到 文件中。
- 验证报告的任何错误是否与持久化结构相关
表 1:针对不一致的持久化结构和相应的错误消息
受影响的结构类型
观察到的错误消息
持久化计算列
消息 2537,级别 16 表错误:对象 ID <object_id> 、索引 ID <index_id> 、。 记录检查 (有效的计算列) 失败。 值为 。
对象 ID <object_id> 和索引 ID <index_id>
引用键或包含列中计算列的索引 筛选索引
Msg 8951 表错误:表“table_name”< (ID <object_id) >。> 数据行在索引“index_name”< (> ID <index_id没有匹配的索引行,) > And/或 Msg 8952 表错误:表“table_name>”< (ID <table_name>) 。 索引“”中的索引行 (ID <index_id>) 与任何数据行都不匹配。 此外,可能存在次要错误 8955 和/或 8956。 这包含有关受影响的确切行的详细信息。 本练习可能会忽略这些内容。
对象 ID <object_id> 和索引 ID <index_id>
Msg 8908 索引视图“<view_name>” (对象 ID <object_id>) 不包含视图定义生成的所有行。 And/或 Msg 8907 索引视图“view_name>”< (对象 ID <object_id>) 包含视图定义未生成的行。
对象 ID <object_id>
完成数据库级验证后,请转到步骤 3。
对象级验证
对于较大的数据库,一次验证一个表或一个视图的结构和约束会很有帮助,以减少维护时段的大小,或者将扩展的逻辑检查限制为可能受影响的对象。
使用 附录 C 部分中的查询来识别可能受影响的表。 附录 D 部分中的脚本可用于根据附录 C 部分中列出的查询生成CHECKTABLE
和CHECKCONSTRAINTS
约束。
DBCC CHECKCONSTRAINTS
若要验证与单个表或视图相关的约束,请使用以下脚本:
USE [database_name]
DBCC TRACEON(139, -1)
DBCC CHECKCONSTRAINTS()
DBCC TRACEOFF(139, -1)
使用跟踪标志可确保通过使用兼容性级别 130 中改进的精度和转换逻辑来执行检查,即使数据库的兼容性级别较低,也会强制改进语义。
CHECKCONSTRAINTS
如果语句已完成且未返回结果集,则无需执行其他操作。
如果语句返回结果集,则结果中的每一行都表示违反约束,并且还提供违反约束的值。
保存表和约束的名称,以及导致冲突的值 (结果集中的 WHERE
列) 。
DBCC CHECKTABLE WITH EXTENDED_LOGICAL_CHECKS
若要验证与单个表或视图相关的持久结构,请使用以下脚本:
USE [database_name]
DBCC TRACEON(139, -1)
DBCC CHECKTABLE() WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS
DBCC TRACEOFF(139, -1)
CHECKTABLE
如果语句成功完成,则无需执行其他操作。
如果语句完成并出现错误,请执行以下步骤:
- 将语句执行
DBCC
的结果(在 SSMS 的消息窗格中找到)保存到文件。
- 验证报告的任何错误是否与表 1 中列出的持久化结构相关。
- 完成表级验证后,请转到步骤 3。
步骤 3:升级到兼容性级别 130
如果数据库的兼容级别已为 130,则可以跳过此步骤。
可以使用以下脚本将数据库的兼容级别更改为 130:
USE [database_name]
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=130
由于在兼容性级别 130 下存在查询优化器更改,因此建议在更改兼容级别之前启用查询存储。 有关详细信息,请参阅查询存储使用方案中的在升级到较新的SQL Server期间保持性能稳定性部分。
步骤 4:更新持久结构
如果在步骤 2 中执行的验证过程中未发现不一致,则升级已完成,可以跳过此步骤。
如果在步骤 2 中发现不一致,则需要执行其他操作来消除数据库中的不一致。 所需的操作取决于受影响的结构类型。
只有在数据库兼容级别更改为 130 后,才执行此步骤中的修复操作。
备份数据库 (或数据库)
建议在执行以下部分介绍的任何操作之前执行完整数据库备份。 如果使用 Azure SQL Database,则无需自行备份;如果任何更新出现问题,始终可以使用时间点还原功能来回溯。
CHECK 约束
更正 CHECK
约束冲突需要修改表中的数据或 CHECK
约束本身。
从步骤 2) 中获取的约束 (的名称中,可以按如下所示获取约束定义:
SELECT definition FROM sys.check_constraints
WHERE object_id= OBJECT_ID(N'constraint_name')
若要检查受影响的表行,可以使用 语句先前返回 DBCC CHECKCONSTRAINTS
的 Where 信息:
SELECT *
FROM [schema_name].[table_name]
WHERE Where_clause
必须更新受影响的行或更改约束定义,以确保不违反约束。
更新表数据
没有硬性规则说明应如何更新数据。 通常,对于 返回 DBCC CHECKCONSTRAINTS
的每个不同的 Where 语句,你将运行以下更新语句:
UPDATE [schema_name].[table_name] SET new_column_values
WHERE Where_clause
请考虑以下示例表,其中包含一个约束和一个违反兼容性级别 130 中约束的行:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=120
CREATE TABLE dbo.table1
c2 datetime,
c3 datetime,
c4 int,
CONSTRAINT chk1 CHECK (c4= (DATEDIFF (ms, c2, c3)))
INSERT dbo.table1 (c2, c3, c4) VALUES
(convert(datetime, '1900-01-01 00:00:00.997'),
convert(datetime, '1900-01-01 00:00:01'), 3)
在此示例中,约束非常简单。 列c4
必须等于涉及 和 c3
的c2
表达式。 若要更新表,请将此值分配给 c4
:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=130
UPDATE dbo.table1 SET c4 = datediff (ms, c2,c3)
WHERE [c2] = '1900-01-01 00:00:00.997' AND [c3] = '1900-01-01 00:00:01.000' AND [c4] = '3'
请注意, WHERE
在 update 语句中使用的 子句对应于 返回 DBCC CHECKCONSTRAINTS
的 Where 信息。
更新 CHECK 约束
若要更改约束 CHECK
,必须删除并重新创建它。 建议在同一事务中同时执行这两项操作,以防更新的约束定义存在任何问题。 可以使用以下 Transact-SQL:
BEGIN TRANSACTION
ALTER TABLE [schema_name].[table_name]
DROP CONSTRAINT [constraint_name]
ALTER TABLE [schema_name].[table_name]
ADD CONSTRAINT [constraint_name]
CHECK (new_constraint_definition)
COMMIT
The following example updates the constraint chk1 in dbo.table1:
BEGIN TRANSACTION
ALTER TABLE dbo.table1
DROP CONSTRAINT chk1
ALTER TABLE dbo.table1
ADD CONSTRAINT chk1
CHECK (c4 <= DATEDIFF (ms, c2, c3))
COMMIT
持久化计算列
更新持久化计算列的最简单方法是更新计算列引用的列之一。 列的新值可以与旧值相同,因此操作不会更改任何用户数据。
对于在步骤 2 中记录的计算列中的不一致情况,请遵循 object_id
这些步骤。
标识计算列:
运行以下查询以检索表名以及已记录 object_id
的 持久化计算列的名称:
SELECT QUOTENAME(s.name) + N'.' + QUOTENAME(t.name) AS 'table',
QUOTENAME(c1.name) AS 'persisted computed column',
c1.column_id AS 'computed_column_id' ,
definition AS 'computed_column_definition'
FROM sys.tables t
JOIN sys.computed_columns c1 ON t.object_id=c1.object_id
AND c1.is_persisted=1
JOIN sys.schemas s ON t.schema_id=s.schema_id
WHERE t.object_id=object_id
运行以下查询以标识计算列引用的列。 记下引用的列名之一:
SELECT QUOTENAME(s.name) + N'.' + QUOTENAME(o.name) AS 'referencing object',
o.type_desc AS 'object type', referenced_minor_id AS 'referenced_column_id', c.name AS 'referenced_column_name'
FROM sys.sql_expression_dependencies sed
JOIN sys.computed_columns c1 ON sed.referencing_id=c1.object_id AND sed.referencing_minor_id=c1.column_id
JOIN sys.objects o ON sed.referencing_id=o.object_id
JOIN sys.schemas s ON o.schema_id=s.schema_id
JOIN sys.columns c ON o.object_id=c.object_id AND sed.referenced_minor_id=c.column_id
WHERE referencing_class=1 AND referenced_class=1 AND referencing_id=object_id AND referencing_minor_id=computed_column_id
以下语句将触发计算列引用的列的更新,并触发计算列的更新。
UPDATE [schema_name].[table_name]
SET referenced_column_name=ISNULL(referenced_column_name, referenced_column_name)
ISNULL
语句中的表达式的创建方式不会更改原始列的值,同时仍确保使用 DB 兼容性级别 130 表达式计算逻辑更新计算列。
请注意,对于非常大的表,你可能不希望更新单个事务中的所有行。 在这种情况下,可以通过向 update 语句添加一个 WHERE
子句来批量运行更新,该子句标识行的范围(例如,基于主键)。
标识引用计算列的索引。
SELECT i.name AS [index name]
FROM sys.index_columns ic JOIN sys.indexes i ON ic.object_id=i.object_id AND ic.index_id=i.index_id
WHERE i.object_id=object_id AND ic.column_id=computed_column_id
此查询标识引用持久化计算列的任何索引。 必须重新生成任何此类索引。 为此,请按照以下部分中的步骤操作。
索引、筛选索引和索引视图
索引中的不一致对应于) 表的错误 8951 和 8952 (,或者步骤 2 输出中 DBCC CHECK
) 视图的错误 8907 和 8908 (。
若要修复这些不一致,请使用 REPAIR_REBUILD
运行 DBCC CHECKTABLE
。 这将修复索引结构,而不会丢失任何数据。 但是,数据库必须处于单用户模式,因此在进行修复时其他用户不可用。
还可以手动重新生成受影响的索引。 如果工作负荷无法脱机,则应使用此选项,因为索引重新生成可以作为联机操作执行, (支持的 SQL Server) 版本。
重新生成索引
如果无法在单用户模式下设置数据库,则可以使用 为步骤 2 中标识的每个索引使用 ALTER INDEX REBUILD
单独重新生成索引。
使用以下查询获取给定 object_id
和 的表和 index_id
索引名称。
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + N'.' + QUOTENAME(o.name) AS 'table', i.name AS 'index_name'
FROM sys.objects o JOIN sys.indexes i ON o.object_id=i.object_id
WHERE o.object_id = object_id AND i.index_id = index_id
使用以下语句重新生成索引:
ALTER INDEX index_name ON [schema_name].[table_name] REBUILD WITH (ONLINE=ON)
如果使用的是标准版、Web 版或 Express 版,则不支持联机索引生成。 因此,必须从 ALTER INDEX
语句中删除 选项WITH (ONLINE=ON)
。
以下示例显示了筛选索引的重新生成:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=120
CREATE TABLE dbo.table2
c2 datetime,
c3 float
INSERT dbo.table2 (c2,c3) VALUES ('1899-12-31 23:58:00.470', -0.00138344907407406)
CREATE INDEX ix_1 ON dbo.table2(c2)
WHERE (c2=-0.00138344907407406)
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=130GOALTER INDEX ix_1 ON [dbo].[table2] REBUILD WITH (ONLINE=ON)
如果你有定期维护计划,建议将此索引重新生成作为计划维护的一部分。
使用 DBCC 进行修复
对于与步骤 2 中记录的不一致索引相关的每个 (object_id) ,请运行以下脚本来执行修复。 此脚本将数据库设置为单用户模式进行修复操作。 在最坏的情况下,修复执行完整索引重新生成。
USE [database_name]
ALTER DATABASE CURRENT SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DBCC CHECKTABLE (object_id, REPAIR_REBUILD) WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS
ALTER DATABASE CURRENT SET MULTI_USER
附录 C:用于标识候选表的查询
以下脚本根据是否存在持久性结构和约束(使用受兼容性级别 130 改进影响的数据类型)来标识你可能希望使用 DBCC CHECKTABLE WITH EXTENDED_LOGICAL_CHECKS
验证的候选表。
以下查询集列出了有关需要额外验证的表和可能受影响的结构的详细信息。
以下查询通过使用受影响的数据类型或使用任何受影响的内置函数返回引用列的所有索引视图:
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + N'.' + QUOTENAME(o.name) AS 'view', QUOTENAME(i.name) AS 'index',QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'referenced table', QUOTENAME(c.name) AS 'referenced column', t.name AS 'data type',
-- if the data type is numeric, integer, or money, the only cases that warrent additional checks
-- with DBCC is if the view definition contains a float or datetime value, or a conversion to such value
s.definition
FROM sys.sql_expression_dependencies sed
JOIN sys.objects o ON sed.referencing_id = o.object_id AND o.type=N'V'
JOIN sys.indexes i ON o.object_id=i.object_id
JOIN sys.sql_modules s ON s.object_id=o.object_id
JOIN sys.columns c ON sed.referenced_id=c.object_id AND sed.referenced_minor_id=c.column_idJOIN sys.types t ON c.system_type_id=t.system_type_id
WHERE referencing_class=1 AND referenced_class=1 AND (c.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR s.[definition] LIKE '%DATEDIFF%'
OR s.[definition] LIKE '%CONVERT%'
OR s.[definition] LIKE '%CAST%'
OR s.[definition] LIKE '%DATEPART%'
OR s.[definition] LIKE '%DEGREES%')
持久化计算列
以下查询返回所有包含计算列的表,这些表通过使用受影响的数据类型引用其他列,或者通过使用任何受影响的内置函数(其中列被保留或从索引引用)。
SELECT QUOTENAME(sed.referenced_schema_name) + N'.' +
QUOTENAME(sed.referenced_entity_name) AS 'candidate table with computed column',
QUOTENAME(c1.name) AS 'computed column', c1.is_persisted,QUOTENAME(c2.name) AS 'referenced column', t.name AS 'data type',
-- if the data type is numeric, integer, or money, the only cases that warrent additional checks
-- with DBCC is if the column definition contains a float or datetime value, or a conversion to such value
c1.definition
FROM sys.sql_expression_dependencies sed
JOIN sys.computed_columns c1 ON sed.referencing_id=c1.object_id AND sed.referencing_minor_id=c1.column_id
JOIN sys.columns c2 ON sed.referenced_id=c2.object_id AND sed.referenced_minor_id=c2.column_id
JOIN sys.types t ON c2.system_type_id=t.system_type_idWHERE referencing_class=1 AND referenced_class=1
AND (c2.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR c1.[definition] LIKE '%DATEDIFF%'
OR c1.[definition] LIKE '%CONVERT%'
OR c1.[definition] LIKE '%DATEPART%'
OR c1.[definition] LIKE '%DEGREES%')
AND (
-- the column is persisted
c1.is_persisted=1
-- OR the column is included in an index
OR EXISTS (SELECT 1 FROM sys.index_columns ic WHERE ic.object_id=c1.object_id AND ic.column_id=c1.column_id)
以下查询返回具有筛选索引的所有表,这些表引用筛选条件中具有影响数据类型的列:
SELECT QUOTENAME(sed.referenced_schema_name) + N'.' +
QUOTENAME(sed.referenced_entity_name) AS 'candidate table with filtered index',
QUOTENAME(i.name) AS 'referencing index',
QUOTENAME(c.name) AS 'referenced column',
t.name AS 'data type',
-- if the data type is numeric, integer, or money, the only cases that warrent additional checks
-- with DBCC is where the filter condition contains a float or datetime value
i.filter_definition AS 'filter condition'
FROM sys.sql_expression_dependencies sed
JOIN sys.indexes i ON sed.referencing_id=i.object_id AND sed.referencing_minor_id=i.index_id
JOIN sys.columns c ON sed.referenced_id=c.object_id AND sed.referenced_minor_id=c.column_id
JOIN sys.types t ON c.system_type_id=t.system_type_id
WHERE referencing_class=7 AND referenced_class=1 AND i.has_filter=1
AND c.system_type_id IN ( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
以下查询列出了具有引用受影响数据类型或内置函数检查约束的所有表:
SELECT QUOTENAME(sed.referenced_schema_name) + N'.' +
QUOTENAME(sed.referenced_entity_name) AS 'candidate table with check constraint',
QUOTENAME(c.name) AS 'constraint_name', c.definition AS 'constraint_definition',
QUOTENAME(col.name) AS 'referenced column', t.name AS 'data type'
FROM sys.sql_expression_dependencies sed
JOIN sys.check_constraints c ON sed.referencing_id=c.object_id AND sed.referencing_class=1
JOIN sys.columns col ON sed.referenced_id=col.object_id AND sed.referenced_minor_id=col.column_id
JOIN sys.types t ON col.system_type_id=t.system_type_id
WHERE referencing_class=1 AND referenced_class=1 AND (col.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint)
OR c.[definition] LIKE '%DATEDIFF%'
OR c.[definition] LIKE '%CONVERT%'
OR c.[definition] LIKE '%DATEPART%'
OR c.[definition] LIKE '%DEGREES%')
附录 D:用于创建 CHECK* 语句的脚本
以下脚本合并了上一个附录中的查询,并通过以 和 CHECKTABLE
语句的形式CHECKCONSTRAINTS
呈现表和视图列表来简化结果。
DECLARE @CRLF nvarchar(10) = CHAR(13) + CHAR(10);
DECLARE @sql nvarchar(max) = N'DBCC TRACEON(139,-1); ' + @CRLF ;
SELECT @sql += N'DBCC CHECKTABLE (N''' + object_for_checktable + N''') WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS; ' + @CRLF
--indexed views
SELECT DISTINCT QUOTENAME(SCHEMA_NAME(o.schema_id)) + N'.' + QUOTENAME(o.name) AS 'object_for_checktable'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id AND o.type = N'V'
INNER JOIN sys.indexes AS i ON o.object_id = i.object_id
INNER JOIN sys.sql_modules AS s ON s.object_id = o.object_id
INNER JOIN sys.columns AS c ON sed.referenced_id = c.object_id AND sed.referenced_minor_id = c.column_id
INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
WHERE referencing_class = 1 AND referenced_class=1
AND (c.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR s.[definition] LIKE N'%DATEDIFF%'
OR s.[definition] LIKE N'%CONVERT%'
OR s.[definition] LIKE N'%CAST%'
OR s.[definition] LIKE N'%DATEPART%'
OR s.[definition] LIKE N'%DEGREES%')
UNION
--persisted computed columns
SELECT DISTINCT QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'object_for_checktable'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.computed_columns AS c1 ON sed.referencing_id = c1.object_id AND sed.referencing_minor_id = c1.column_id
INNER JOIN sys.columns AS c2 ON sed.referenced_id=c2.object_id AND sed.referenced_minor_id = c2.column_id
INNER JOIN sys.types AS t ON c2.system_type_id = t.system_type_id
WHERE referencing_class = 1 AND referenced_class = 1
AND (c2.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR c1.[definition] LIKE N'%DATEDIFF%'
OR c1.[definition] LIKE N'%CONVERT%'
OR c1.[definition] LIKE N'%DATEPART%'
OR c1.[definition] LIKE N'%DEGREES%')
AND (
-- the column is persisted
c1.is_persisted = 1
-- OR the column is included in an index
OR EXISTS (SELECT 1 FROM sys.index_columns AS ic
WHERE ic.object_id = c1.object_id AND ic.column_id=c1.column_id)
UNION
--indexed views
SELECT DISTINCT QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'object_for_checktable'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.indexes AS i ON sed.referencing_id = i.object_id AND sed.referencing_minor_id = i.index_id
INNER JOIN sys.columns AS c ON sed.referenced_id = c.object_id AND sed.referenced_minor_id = c.column_id
INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
WHERE referencing_class = 7 AND referenced_class = 1 AND i.has_filter = 1
AND c.system_type_id IN (
59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
)) AS a
SELECT @sql += N'DBCC CHECKCONSTRAINTS (N''' + object_for_checkconstraints + N'''); ' + @CRLF
SELECT DISTINCT QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'object_for_checkconstraints'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.check_constraints AS c ON sed.referencing_id = c.object_id AND sed.referencing_class = 1
INNER JOIN sys.columns AS col ON sed.referenced_id = col.object_id AND sed.referenced_minor_id = col.column_id
INNER JOIN sys.types AS t ON col.system_type_id = t.system_type_id
WHERE referencing_class = 1 AND referenced_class = 1 AND (col.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR c.[definition] LIKE N'%DATEDIFF%'
OR c.[definition] LIKE N'%CONVERT%'
OR c.[definition] LIKE N'%DATEPART%'
OR c.[definition] LIKE N'%DEGREES%')
SET @sql += N'DBCC TRACEOFF(139,-1);';
PRINT @sql;
--to run the script immediately, use the following command:
--EXECUTE sp_executesql @sql;