Переключение данных при сбое с «разрешает значения, которые не разрешены проверочными ограничениями или функцией разделения на целевой таблице»

12

Учитывая следующее

-- table ddl
create table dbo.f_word(
    sentence_id int NULL,
    sentence_word_id int NULL,
    word_id int NULL,
    lemma_id int NULL,
    source_id int NULL,
    part_of_speech_id int NULL,
    person_id int NULL,
    gender_id int NULL,
    number_id int NULL,
    tense_id int NULL,
    voice_id int NULL,
    mood_id int NULL,
    case_id int NULL,
    degree_id int NULL,
    citation nvarchar(100) NULL
);
-- create partition function
create partition function pf_f_word_source_id (int)
as range left for values 
(
    1,2,3,4,5,6,7,8,9,10,11,12,13,14,
    15,16,17,18,19,20,21,22,23
);

-- create the partition scheme
create partition scheme ps_f_word as partition pf_f_word_source_id to 
(
    [primary],[primary],[primary],[primary],[primary],[primary],[primary],[primary],[primary],
    [primary],[primary],[primary],[primary],[primary],[primary],[primary],[primary],[primary],
    [primary],[primary],[primary],[primary],[primary],[primary]
);

-- partition the index
create unique clustered index cix_fword on dbo.f_word 
(
    source_id,
    sentence_id,
    sentence_word_id,
    word_id,
    lemma_id,
    part_of_speech_id,
    person_id,
    gender_id,
    number_id,
    tense_id,
    voice_id,
    mood_id,
    case_id,
    degree_id 
)
on ps_f_word (source_id);

-- swapin table ddl

create table dbo.f_word_swapin(
    sentence_id int NULL,
    sentence_word_id int NULL,
    word_id int NULL,
    lemma_id int NULL,
    source_id int NULL,
    part_of_speech_id int NULL,
    person_id int NULL,
    gender_id int NULL,
    number_id int NULL,
    tense_id int NULL,
    voice_id int NULL,
    mood_id int NULL,
    case_id int NULL,
    degree_id int NULL,
    citation nvarchar(100) NULL
) on [primary];

-- create the same index on the swapin table
create unique clustered index cix_fword_swapin on dbo.f_word_swapin 
(
    source_id,
    sentence_id,
    sentence_word_id,
    word_id,
    lemma_id,
    part_of_speech_id,
    person_id,
    gender_id,
    number_id,
    tense_id,
    voice_id,
    mood_id,
    case_id,
    degree_id 
);

-- add check constraints WITH CHECK
ALTER TABLE dbo.f_word_swapin
WITH CHECK
ADD CONSTRAINT ck_f_word_swapin_lb
CHECK ( source_id > 12);

ALTER TABLE dbo.f_word_swapin
WITH CHECK
ADD CONSTRAINT ck_f_word_swapin_ub
CHECK ( source_id <= 13);

Затем переместите данные:

-- switch data OUT of the partitioned table
ALTER TABLE dbo.f_word
SWITCH PARTITION 13 TO dbo.f_word_swapin;

-- attempt to switch data back IN 
ALTER TABLE dbo.f_word_swapin
SWITCH TO dbo.f_word PARTITION 13;

Ниже приведен DDL «Script Table As ... CREATE» только для проверки тех же структур таблиц.

/****** Object:  Table [dbo].[f_word_swapin]    Script Date: 9/10/2014 10:01:01 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[f_word_swapin](
    [sentence_id] [int] NULL,
    [sentence_word_id] [int] NULL,
    [word_id] [int] NULL,
    [lemma_id] [int] NULL,
    [source_id] [int] NULL,
    [part_of_speech_id] [int] NULL,
    [person_id] [int] NULL,
    [gender_id] [int] NULL,
    [number_id] [int] NULL,
    [tense_id] [int] NULL,
    [voice_id] [int] NULL,
    [mood_id] [int] NULL,
    [case_id] [int] NULL,
    [degree_id] [int] NULL,
    [citation] [nvarchar](100) NULL
) ON [PRIMARY]

/****** Object:  Table [dbo].[f_word]    Script Date: 9/10/2014 10:09:43 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[f_word](
    [sentence_id] [int] NULL,
    [sentence_word_id] [int] NULL,
    [word_id] [int] NULL,
    [lemma_id] [int] NULL,
    [source_id] [int] NULL,
    [part_of_speech_id] [int] NULL,
    [person_id] [int] NULL,
    [gender_id] [int] NULL,
    [number_id] [int] NULL,
    [tense_id] [int] NULL,
    [voice_id] [int] NULL,
    [mood_id] [int] NULL,
    [case_id] [int] NULL,
    [degree_id] [int] NULL,
    [citation] [nvarchar](100) NULL
)

GO

ВЫКЛЮЧЕНИЕ работает просто отлично. SWITCHing IN вызывает следующую ошибку:

Сообщение 4972, уровень 16, состояние 1, строка 1 Оператор ALTER TABLE SWITCH не выполнен. Проверить ограничения или функцию секционирования исходной таблицы «greek.dbo.f_word_swapin» позволяет значения, которые не разрешены проверочными ограничениями или функцией секционирования для целевой таблицы «greek.dbo.f_word».

Бег:

select target_partition_id = $PARTITION.pf_f_word_source_id(source_id), 
    *
from dbo.f_word_swapin;

проверяет, что все данные должны вернуться в раздел 13

Я действительно довольно плохо знаком с разделением, поэтому я уверен, что я делаю вещи неправильно, я просто не знаю, что это такое.

swasheck
источник
Это также может произойти, если хотя бы для одной из таблиц ваше проверочное ограничение было создано WITH NOCHECK.

Ответы:

19

Что касается CHECKограничений, они запрещают только те строки, для которых возвращается предикат FALSE. Если проверка возвращается UNKNOWN, это не FALSEтак, поэтому строка проходит проверку:

CREATE TABLE dbo.T1 (id int NULL CHECK (id = 1));

INSERT dbo.T1 VALUES (1); -- Ok
INSERT dbo.T1 VALUES (2); -- Error
INSERT dbo.T1 VALUES (NULL); -- Ok!

Ваше проверочное ограничение не запрещает NULLзначения, которые находятся вне допустимого значения, на SWITCHкоторое возражает оператор. Ваша таблица включения может содержать нули, которые не принадлежат разделу 2.

Добавьте AND source_id IS NOT NULLк вашему CHECKограничению, когда целевой раздел не является разделом 1 (куда идут нули).

Пол Уайт 9
источник