web-dev-qa-db-ja.com

「ターゲットテーブルのチェック制約またはパーティション関数で許可されていない値を許可する」でデータの切り替えに失敗する

次の場合

-- 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;

以下は、同じテーブル構造を検証するための "Script Table As ... CREATE" DDLです。

/****** 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 OUTは問題なく動作します。 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に戻ることを確認します。

私はパーティション分割が非常に新しいので、私は物事を間違ってやっていると確信しています。

12
swasheck

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に属していないnullが含まれている可能性があります。

追加 AND source_id IS NOT NULLCHECK制約に、宛先パーティションがパーティション1(nullが行くところ)でない場合。

19
Paul White 9