ALTER TABLE…通常のテーブルからパーティションテーブルへの切り替えが失敗する


9

以下のコードは次のことを行います:

  1. C:\ TEMPにデータベースplay_partitionを作成します
  2. 2つの同一のパーティション分割テーブルplay_tableおよびarchive_play_tableを作成します
  3. play_tableパーティション1をarchive_play_tableパーティション1に切り替えます
  4. play_tableパーティション2と同じファイルグループに、play_tableと同じ構造の新しいパーティション分割されていないテーブルtemp_tableを作成します。
  5. play_table_partition 2をtemp_tableに切り替えます
  6. temp_tableをplay_tableパーティション2に戻そうとし、失敗します

    メッセージ4982、レベル16、状態1、行64のALTER TABLE SWITCHステートメントが失敗しました。ソーステーブル 'play_partition.dbo.temp_table'の制約をチェックすると、ターゲットテーブル 'play_partition.dbo.play_table'のパーティション2で定義された範囲では許可されない値が許可されます。

なぜ失敗するのですか?

SQL Server 2014(Enterprise Edition Trial)を使用しています。

よろしく、

コリン・デイリー

http://www.colindaley.com/translator

/* Playing with partitioned tables */

USE master;
GO

DROP DATABASE play_partition;
GO

CREATE DATABASE play_partition
    ON PRIMARY(
        NAME = play_partition
        , FILENAME = 'C:\TEMP\play_partition.mdf')
    ,FILEGROUP play_fg1(
        NAME = play_fg1
        ,FILENAME = 'C:\TEMP\play_fg1f1.ndf')
    ,FILEGROUP play_fg2(
        NAME = play_fg2f1
        ,FILENAME = 'C:\TEMP\play_fg2f1.ndf');
GO

USE play_partition;


CREATE PARTITION FUNCTION play_range(INT)
    AS RANGE LEFT FOR VALUES(3);

-- Partition scheme
CREATE PARTITION SCHEME play_scheme 
    AS PARTITION play_range TO (play_fg1, play_fg2);

-- Partitioned tables
CREATE TABLE dbo.play_table(
    c1 INT NOT NULL CONSTRAINT PK_play_table_c1 PRIMARY KEY CLUSTERED
)
    ON play_scheme(c1);

CREATE TABLE dbo.archive_play_table(
c1 INT NOT NULL CONSTRAINT PK_archive_play_table_c1 PRIMARY KEY CLUSTERED
)
    ON play_scheme(c1);

-- partition 1 = {1, 2, 3}, partiion 2 = {4, 5, 6}
INSERT INTO dbo.play_table(c1) VALUES (1), (2),  (3), (4), (5), (6);

-- move partition 1 from play_table to archive play_table
ALTER TABLE dbo.play_table
    SWITCH PARTITION 1 to dbo.archive_play_table PARTITION 1;

-- create empty table with same structure as dbo.play_table
SELECT * INTO dbo.temp_table FROM dbo.play_table WHERE 1 = 0;

-- move temp_table to filegroup play_fg2
ALTER TABLE dbo.temp_table
    ADD CONSTRAINT PK_temp_table_c1 PRIMARY KEY CLUSTERED(c1) ON play_fg2;

-- move contents of play_table to temp_table, which is not partitioned
-- but is in the same filegroup
ALTER TABLE dbo.play_table
    SWITCH PARTITION 2 TO temp_table;
PRINT 'Switched from partitioned table to non-partitioned table';

-- move data back to partitioned play_table from unpartitioned temp_table
-- FAIL
ALTER TABLE dbo.temp_table
    SWITCH TO play_table partition 2;
PRINT 'Switched from non-partitioned table to partitioned table';


SELECT 'archive_play_table' as table_name, t1.c1
    FROM dbo.archive_play_table AS t1
    UNION ALL
    SELECT 'temp_table' AS table_name, t1.c1
        FROM dbo.temp_table as t1
    ORDER BY 1, 2;

質問に+1してください。ここにDDLを配置したため、再現と回答が簡単になりました。そのため、ありがとうございます。このような+10の質問ができればいいのに。
トーマス・ストリンガー、2014

ありがとう。そのエラーには、より適切なメッセージが必要です。テーブルのチェック制約に言及したとき(チェック制約がない場合)、チェック制約の欠如が実際に問題であるとは思いもよらなかった。
Colin Daley

回答:


11

パーティション切り替えを使用している場合、SQL Serverは、ソーステーブル/パーティションの境界が宛先テーブル/パーティションの境界に収まることを確認する必要があります。言い換えれば、あなたはからスイッチデータにしようとしているdbo.temp_tabledbo.play_table、のためのデータのように考えて2パーティションのc1中には、dbo.temp_tableデータの種類(のみによって制約されているintあなたは-2,147,483,648から2,147,483,647の範囲の値を持つことができるので、) 。ただし、逆に、宛先(dbo.play_tableパーティション2)の範囲は4〜2,147,483,647です。

データはこれに違反していませんが、これを許可できないのはメタデータです。値-10をに簡単に挿入できdbo.temp_tableます。-10はのdbo.play_table2番目のパーティション境界に適合しないため、パーティションの切り替えは同じように失敗し、より意味があります。

このコードを機能させるには、SQL Serverに、の2番目のパーティションにdbo.temp_table収まらないデータが含まれないように明示的に通知する必要がありますdbo.play_table。チェック制約を使用してこれを行うことができます:

/******************************************************************************
    your code omitted for brevity
******************************************************************************/

-- move contents of play_table to temp_table, which is not partitioned
-- but is in the same filegroup
ALTER TABLE dbo.play_table
    SWITCH PARTITION 2 TO temp_table;
PRINT 'Switched from partitioned table to non-partitioned table';

/******************************************************************************
    added check constraint so that data can fit in the destination partition
******************************************************************************/
alter table dbo.temp_table
add constraint CK_TempTable_C1 check (c1 >= 4);
go
/******************************************************************************
    end of added code
******************************************************************************/

-- move data back to partitioned play_table from unpartitioned temp_table
-- this will no longer FAIL
ALTER TABLE dbo.temp_table
    SWITCH TO play_table partition 2;
PRINT 'Switched from non-partitioned table to partitioned table';

/******************************************************************************
    your code omitted for brevity
******************************************************************************/

上記のサンプルコードをコードに追加すると、これが実用的なソリューションになります。これでSQL Server は、にチェック制約が追加されたため、データdbo.temp_tableがパーティション2に収まることを認識しています。dbo.play_tabledbo.temp_table

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.