Le code ci-dessous fait ce qui suit:
Tente de basculer temp_table sur la partition 2 de play_table et échoue avec
Échec de l'instruction ALTER TABLE SWITCH Msg 4982, niveau 16, état 1, ligne 64. Vérifiez les contraintes de la table source 'play_partition.dbo.temp_table' autorisez les valeurs qui ne sont pas autorisées par la plage définie par la partition 2 sur la table cible 'play_partition.dbo.play_table'.
Pourquoi ça échoue?
J'utilise SQL Server 2014 (version d'essai Enterprise Edition).
Cordialement,
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;
Lorsque vous travaillez avec la commutation de partition, SQL Server devra vérifier que les limites de la table/partition source peuvent tenir dans les limites de la table/partition de destination. En d'autres termes, vous essayez de basculer les données de dbo.temp_table
à dbo.play_table
's partition 2. Pensez-y comme ceci, les données pour le c1
dans dbo.temp_table
n'est contraint que par le type de données (int
), vous pouvez donc avoir des valeurs comprises entre -2 147 483 648 et 2 147 483 647. Mais inversement, vous êtes destination (dbo.play_table
partition 2) a une plage de 4 à 2 147 483 647.
Vos données ne violent pas cela, mais ce sont les métadonnées qui ne peuvent pas le permettre. Vous pouvez tout aussi facilement insérer la valeur -10 dans dbo.temp_table
. La commutation de partition échouerait de la même manière et aurait plus de sens, car -10 ne rentre pas dans dbo.play_table
2e limites de partition.
Si vous souhaitez que ce code fonctionne, vous devez indiquer explicitement à SQL Server que dbo.temp_table
n'aura jamais de données qui ne rentrent pas dans dbo.play_table
2e partition. Vous pouvez le faire avec une contrainte de vérification:
/******************************************************************************
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
******************************************************************************/
Cet exemple d'ajout ci-dessus à votre code en fait une solution de travail. Maintenant, SQL Server sait que les données dans dbo.temp_table
peut tenir dans la partition 2 de dbo.play_table
en raison de la contrainte de vérification ajoutée à dbo.temp_table
.