Bas*_*sel 6 sql-server t-sql partitioning filtered-index
在向表中插入新行时,我遇到了字符数据转换的神秘错误。故障排除表明过滤索引是问题的根源。
索引的过滤器使用 DateTime 列,该列也是表的分区列。一些客户端默认与俄语连接并收到错误消息。我设法在测试表上重现它。
有没有人对为什么会发生这种情况有任何想法?
use YOUR_DATABASE ;
go
select @@VERSION ;
-- Microsoft SQL Server 2016 (SP2-CU1) ...
-----------------------------------------------------------------------------
-- CREATE DATETIME PARTITIONED TABLE
set language english ;
drop table if exists dbo.test_of_filtered_idx ;
drop partition scheme ps_test_of_filtered_idx ;
drop partition function pf_test_of_filtered_idx ;
go
set language english ;
go
create partition function pf_test_of_filtered_idx (datetime)
as range right
for values ('1999-11-01 00:00:00.000' , '1999-12-01 00:00:00.000' , '2000-01-01 00:00:00.000' , '2000-02-01 00:00:00.000')
create partition scheme ps_test_of_filtered_idx
as partition pf_test_of_filtered_idx
ALL to ([primary])
create table dbo.test_of_filtered_idx
(
id int not null identity (1,1) ,
dt datetime not null ,
payload char(127) not null default(replicate('A' , 127)) ,
constraint PK__test_of_filtered_idx primary key clustered (id , dt)
) on [ps_test_of_filtered_idx] (dt) ;
go
-----------------------------------------------------------------------------
-- INSERT TEST ROW AND CREATE DATETIME FILTERED INDEX
set language russian ;
go
insert into dbo.test_of_filtered_idx (dt) output inserted.* values ('15.12.1999 00:00:00.000' /* russian datetime format DMY */) ;
go
set language english ;
go
create index IXF__test_of_filtered_idx__dt
on dbo.test_of_filtered_idx
(dt) include (id)
where dt >= '1999-12-10 00:00:00.000'
and dt < '2000-01-20 00:00:00.000' ;
go
-----------------------------------------------------------------------------
-- CHECK
set language english ;
go
insert into dbo.test_of_filtered_idx (dt) output inserted.* values ('12/15/1999 00:00:00.000' /* native american datetime format MDY */) ;
go
-- GET ERROR
set language russian ;
go
insert into dbo.test_of_filtered_idx (dt) output inserted.* values ('15.12.1999 00:00:00.000' /* russian datetime format DMY */) ;
-- ?????????????? ???? ?????? varchar ? ??? ?????? datetime ??????? ? ?????? ???????? ?? ??????? ?????????.
-- The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
go
-----------------------------------------------------------------------------
-- DROP INDEX AND GET ERRORFREE INSERTION
set language english ;
go
drop index IXF__test_of_filtered_idx__dt
on dbo.test_of_filtered_idx
;
go
set language russian ;
go
insert into dbo.test_of_filtered_idx (dt) output inserted.* values ('15.12.1999 00:00:00.000' /* russian datetime format DMY */) ;
go
-----------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
错误来自转换字符串2000-01-20 00:00:00.000(在过滤的索引定义中)
更改过滤索引以使用明确的日期时间格式有效。
create index IXF__test_of_filtered_idx__dt
on dbo.test_of_filtered_idx
(dt) include (id)
where dt >= '19991210 00:00:00.000'
and dt < '20000120 00:00:00.000' ;
Run Code Online (Sandbox Code Playgroud)
对我来说,过滤索引范围是根据客户端的设置解释的,因此在过滤索引中可以包含或不包含相同的日期,这取决于插入时客户端的设置(如下所示),这对我来说绝对是错误的演示)
CREATE TABLE T
(
dt DATETIME
)
CREATE INDEX IXF__test_of_filtered_idx__dt
ON T (dt)
WHERE dt >= '1999-01-06' AND dt < '1999-02-06';
SET LANGUAGE ENGLISH
GO
INSERT INTO T
VALUES ( DATEADD(DAY,5,'1999-01-01')); --6th Jan
GO
SET LANGUAGE RUSSIAN
INSERT INTO T
VALUES ( DATEADD(DAY,5,'1999-01-01')); --Still 6th Jan
GO
SET LANGUAGE ENGLISH
GO
SELECT *
FROM T
Run Code Online (Sandbox Code Playgroud)
返回两行 - 都具有相同的日期
+-------------------------+
| dt |
+-------------------------+
| 1999-01-06 00:00:00.000 |
| 1999-01-06 00:00:00.000 |
+-------------------------+
Run Code Online (Sandbox Code Playgroud)
但
SET LANGUAGE ENGLISH
GO
SELECT *
FROM T
WHERE dt >= '1999-01-06'
AND dt < '1999-02-06';
Run Code Online (Sandbox Code Playgroud)
使用过滤后的索引并只返回其中之一
+-------------------------+
| dt |
+-------------------------+
| 1999-01-06 00:00:00.000 |
+-------------------------+
Run Code Online (Sandbox Code Playgroud)
此时运行DBCC CHECKTABLE (T) WITH EXTENDED_LOGICAL_CHECKS对于任何一种语言都会失败。
Msg 8951, Level 16, State 1, Line 4
Table error: table 'T' (ID 1045578763). Data row does not have a matching index row in the index 'IXF__test_of_filtered_idx__dt' (ID 2). Possible missing or invalid keys for the index row matching:
Msg 8955, Level 16, State 1, Line 4
Data row (4:24:1) identified by (HEAP RID = (4:24:1)) with index values 'dt = '1999-01-06 00:00:00.000' and HEAP RID = (4:24:1)'.
DBCC results for 'T'.
There are 2 rows in 1 pages for object "T".
CHECKTABLE found 0 allocation errors and 1 consistency errors in table 'T' (object ID 1045578763).
repair_rebuild is the minimum repair level for the errors found by DBCC CHECKTABLE (tempdb.dbo.T).
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
656 次 |
| 最近记录: |