ALTER TABLE… Normal tablodan bölümlenmiş tabloya geçiş başarısız oluyor


9

Aşağıdaki kod aşağıdakileri yapar:

  1. C: \ TEMP içinde bir play_partition veritabanı oluşturur
  2. Play_table ve archive_play_table adlı iki özdeş bölümlenmiş tablo oluşturur
  3. Play_table bölüm 1'i archive_play_table bölüm 1'e geçirir
  4. Play_table partition 2 ile aynı dosya grubunda play_table ile aynı yapıya sahip yeni bir bölümlenmemiş tablo oluşturur
  5. Play_table_partition 2'yi temp_table olarak değiştirir
  6. Temp_table dosyasını play_table partition 2'ye geri döndürmeye çalışır ve

    Msg 4982, Seviye 16, Durum 1, Satır 64 ALTER TABLE SWITCH deyimi başarısız oldu. 'Play_partition.dbo.temp_table' kaynak tablosunun kısıtlamalarını kontrol edin, 'play_partition.dbo.play_table' hedef tablosunda bölüm 2 tarafından tanımlanan aralığa izin verilmeyen değerlere izin verin.

Neden başarısız oluyor?

SQL Server 2014 (Enterprise Edition Deneme Sürümü) kullanıyorum.

Saygılarımızla,

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;

Sorunuzda +1. Buraya koyduğunuz DDL nedeniyle yeniden yayınlamayı ve yanıtlamayı kolaylaştırdınız. Bunun için teşekkür ederim. Keşke bunun gibi +10 soru yapabilsem.
— Thomas Stringer

Teşekkürler. Bu hatanın daha iyi bir iletiye ihtiyacı var. Tablodaki kontrol kısıtlamalarından bahsettiğinde (kontrol kısıtlaması olmadığında), bana bir kontrol kısıtlamasının eksikliğinin aslında sorun olduğu ortaya çıkmadı.
— Colin Daley

Yanıtlar:


11

Bölüm değiştirme ile çalışırken, SQL Server'ın kaynak tablo / bölüm sınırlarının hedef tablo / bölüm sınırlarına sığabileceğini doğrulaması gerekir. Başka bir deyişle, gelen anahtar verilerine çalışıyoruz dbo.temp_tableetmek dbo.play_tableiçin verileri bu gibi düşünün 2. bölüm 'ın c1in dbo.temp_tableveri türü (sadece kısıtlıdır intEğer -2,147,483,648 dan 2,147,483,647 arasında değişen değerlere sahip olabilir, böylece) . Ancak tam tersine, hedefiniz ( dbo.play_table2. bölüm) 4 ile 2.147.483.647 aralığındadır.

Verileriniz bunu ihlal etmiyor, ancak buna izin veremeyen meta veriler. -10 değerini kolayca ekleyebilirsiniz dbo.temp_table. Bölüm değiştirme, aynı şekilde başarısız olur ve daha anlamlı olur, çünkü -10, dbo.play_table2. bölüm sınırlarına uymaz .

Bu kodun çalışması için SQL Server'ın 2. bölüme dbo.temp_tablesığmayacak hiçbir veriye sahip olmayacağını açıkça söylemeniz gerekir dbo.play_table. Bunu bir kontrol kısıtlamasıyla yapabilirsiniz:

/******************************************************************************
    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
******************************************************************************/

Kodunuza yukarıdaki örnek ekleme, bunu çalışan bir çözüm haline getirir. Artık SQL Server , eklenen kontrol kısıtlaması nedeniyle verilerin dbo.temp_tablebölüm 2'ye sığabileceğini biliyor .dbo.play_tabledbo.temp_table

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.