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.