ALTER TABLE … SWITCHing จากตารางปกติไปยังตารางที่แบ่งพาร์ติชันล้มเหลว


9

รหัสด้านล่างทำสิ่งต่อไปนี้:

  1. สร้างฐานข้อมูล play_partition ใน C: \ TEMP
  2. สร้างสองตารางที่แบ่งพาร์ติชันเหมือนกันคือ play_table และ archive_play_table
  3. สลับพาร์ติชัน play_table 1 ไปยังไฟล์เก็บถาวรพาร์ติชัน 1 1
  4. สร้าง temp_table แบบไม่แบ่งพาร์ติชั่นใหม่ที่มีโครงสร้างเดียวกันกับ play_table บนกลุ่มไฟล์เดียวกันกับ play_table partition 2
  5. สลับ play_table_partition 2 เป็น temp_table
  6. พยายามเปลี่ยน temp_table กลับไปที่ play_table partition 2 และล้มเหลวด้วย

    ข่าวสารเกี่ยวกับ 4982 ระดับ 16 สถานะ 1 บรรทัด 64 คำสั่ง ALTER TABLE SWITCH ล้มเหลว ตรวจสอบข้อ จำกัด ของตารางต้นฉบับ 'play_partition.dbo.temp_table' อนุญาตค่าที่ไม่ได้รับอนุญาตตามช่วงที่กำหนดโดยพาร์ติชัน 2 บนตารางเป้าหมาย 'play_partition.dbo.play_table'

ทำไมมันล้มเหลว

ฉันใช้ SQL Server 2014 (รุ่นทดลองใช้องค์กร)

ความนับถือ,

Colin Daley

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 คำถามเช่นนี้
Thomas Stringer

ขอบคุณ ข้อผิดพลาดนั้นต้องการข้อความที่ดีกว่า เมื่อกล่าวถึงข้อ จำกัด การตรวจสอบบนโต๊ะ (เมื่อไม่มีข้อ จำกัด การตรวจสอบ) มันไม่ได้เกิดขึ้นกับฉันว่าการขาดข้อ จำกัด การตรวจสอบในความเป็นจริงปัญหา
โคลิน Daley

คำตอบ:


11

เมื่อคุณทำงานกับการสลับพาร์ติชัน SQL Server จะต้องตรวจสอบว่าขอบเขตของตาราง / พาร์ติชันต้นฉบับสามารถพอดีกับขอบเขตของตาราง / พาร์ติชันปลายทาง ในคำอื่น ๆ ที่คุณกำลังพยายามที่จะเปลี่ยนจากข้อมูลdbo.temp_tableการdbo.play_tableของพาร์ทิชัน 2. คิดว่ามันเหมือนนี้ข้อมูลสำหรับc1ในdbo.temp_tableเป็นข้อ จำกัด โดยเฉพาะชนิดข้อมูล ( int) ดังนั้นคุณสามารถมีค่าตั้งแต่ -2147483648 เพื่อ 2,147,483,647 . แต่ในทางกลับกันคุณปลายทาง ( dbo.play_tableพาร์ติชัน 2) มีช่วงจาก 4 ถึง 2,147,483,647

ข้อมูลของคุณไม่ได้ละเมิด แต่เป็นข้อมูลเมตาที่ไม่อนุญาต คุณสามารถได้อย่างง่ายดายเพียงแทรกค่า -10 dbo.temp_tableเข้า การสลับพาร์ติชันจะล้มเหลวในลักษณะเดียวกันและเหมาะสมกว่าเนื่องจาก -10 ไม่พอดีกับdbo.play_tableขอบเขตของพาร์ติชันที่สอง

ถ้าคุณต้องการทำให้รหัสนี้ใช้งานได้คุณจะต้องบอก SQL Server อย่างชัดเจนว่าdbo.temp_tableจะไม่มีข้อมูลใด ๆ ที่ไม่เหมาะกับdbo.play_tableพาร์ติชั่นที่ 2 คุณสามารถทำได้ด้วยข้อ จำกัด การตรวจสอบ:

/******************************************************************************
    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_tableเนื่องจากการเพิ่มข้อ จำกัด dbo.temp_tableในการตรวจสอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.