Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak naprawić „Wyrażenie ALTER TABLE SWITCH nie powiodło się” Msg 4982 (SQL Server)

Jeśli otrzymasz komunikat o błędzie 4982 w SQL Server, dzieje się tak dlatego, że Twoja tabela źródłowa nie ma ograniczenia, które ogranicza dane tylko do zakresu obsługiwanego przez partycję, na którą próbujesz się przełączyć.

Przykład błędu

Oto jak wygląda błąd:

Msg 4982, Level 16, State 1, Line 1
ALTER TABLE SWITCH statement failed. Check constraints of source table 'Test.dbo.OrdersOld' allow values that are not allowed by range defined by partition 3 on target table 'Test.dbo.OrdersNew'.

Dokładne sformułowanie będzie zależeć od nazw tabel, partycji, środowiska itp.

Podczas próby przełączenia danych na nową partycję chcesz mieć pewność, że dane są zgodne z zakresem tej partycji. Na przykład, jeśli twoja partycja ma zakres od 1 do 10, nie chcesz przypadkowo umieszczać tam wartości od 11 do 20.

SQL Server też chce mieć pewność i dlatego pojawia się ten błąd. Podczas próby przełączenia danych SQL Server szuka w tabeli źródłowej CHECK ograniczenie, które ogranicza dane do zakresu określonego w partycji docelowej. Jeśli go nie znajdzie, pojawi się ten błąd.

Aby to naprawić, dodaj CHECK ograniczenie do tabeli źródłowej i upewnij się, że ogranicza dane do zakresu obsługiwanego przez partycję, na którą się przełączasz.

Przykład kodu problemu

Oto kod, który spowodował błąd:

ALTER DATABASE Test ADD FILEGROUP OrdersNewFg1;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg1dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg1dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg1;
GO

ALTER DATABASE Test ADD FILEGROUP OrdersNewFg2;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg2dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg2dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg2;
GO
ALTER DATABASE Test ADD FILEGROUP OrdersNewFg3;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg3dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg3dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg3;
GO
ALTER DATABASE Test ADD FILEGROUP OrdersNewFg4;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg4dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg4dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg4;
GO

CREATE PARTITION FUNCTION OrdersNewPartitionFunction (date)  
    AS RANGE RIGHT FOR VALUES (
        '20200201', 
        '20200301',
        '20200401'
    );
GO

CREATE PARTITION SCHEME OrdersNewPartitionScheme
    AS PARTITION OrdersNewPartitionFunction  
    TO (
        OrdersNewFg1,
        OrdersNewFg2,
        OrdersNewFg3,
        OrdersNewFg4
        );  
GO

CREATE TABLE OrdersOld (
    OrderDate date NOT NULL,
    OrderId int IDENTITY NOT NULL,
    OrderDesc varchar(255) NOT NULL,
    CONSTRAINT chkDate CHECK (OrderDate >= '20200301' AND OrderDate < '20200401'),
    CONSTRAINT PKOrdersOld PRIMARY KEY CLUSTERED(OrderDate,OrderId)
    )
    ON OrdersNewFg3;
GO

INSERT INTO OrdersOld(OrderDate, OrderDesc) VALUES
    ('20200302', 'Cat food'),
    ('20200315', 'Water bowl'),
    ('20200318', 'Saddle for camel'),
    ('20200321', 'Dog biscuits'),
    ('20200328', 'Bigfoot shoes');
GO

CREATE TABLE OrdersNew (
    OrderDate date NOT NULL,
    OrderId int IDENTITY NOT NULL,
    OrderDesc varchar(255) NOT NULL
    )  
    ON OrdersNewPartitionScheme (OrderDate),
    CONSTRAINT PKOrdersNew PRIMARY KEY CLUSTERED(OrderDate,OrderId);  
GO

ALTER TABLE OrdersOld
SWITCH TO OrdersNew PARTITION 3;

Wynik:

Msg 4982, Level 16, State 1, Line 1
ALTER TABLE SWITCH statement failed. Check constraints of source table 'Test.dbo.OrdersOld' allow values that are not allowed by range defined by partition 3 on target table 'Test.dbo.OrdersNew'.

Rozwiązanie

Oto ten sam kod, ale tym razem z odpowiednim CHECK dodano ograniczenie.

ALTER DATABASE Test ADD FILEGROUP OrdersNewFg1;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg1dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg1dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg1;
GO

ALTER DATABASE Test ADD FILEGROUP OrdersNewFg2;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg2dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg2dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg2;
GO
ALTER DATABASE Test ADD FILEGROUP OrdersNewFg3;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg3dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg3dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg3;
GO
ALTER DATABASE Test ADD FILEGROUP OrdersNewFg4;
GO

ALTER DATABASE Test ADD FILE (  
    NAME = OrdersNewFg4dat,  
    FILENAME = '/var/opt/mssql/data/OrdersNewFg4dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB
    )  
TO FILEGROUP OrdersNewFg4;
GO

CREATE PARTITION FUNCTION OrdersNewPartitionFunction (date)  
    AS RANGE RIGHT FOR VALUES (
        '20200201', 
        '20200301',
        '20200401'
    );
GO

CREATE PARTITION SCHEME OrdersNewPartitionScheme
    AS PARTITION OrdersNewPartitionFunction  
    TO (
        OrdersNewFg1,
        OrdersNewFg2,
        OrdersNewFg3,
        OrdersNewFg4
        );  
GO

CREATE TABLE OrdersOld (
    OrderDate date NOT NULL,
    OrderId int IDENTITY NOT NULL,
    OrderDesc varchar(255) NOT NULL,
    CONSTRAINT chkDate CHECK (OrderDate >= '20200301' AND OrderDate < '20200401'),
    CONSTRAINT PKOrdersOld PRIMARY KEY CLUSTERED(OrderDate, OrderId)
    )
    ON OrdersNewFg3;
GO

INSERT INTO OrdersOld(OrderDate, OrderDesc) VALUES
    ('20200302', 'Cat food'),
    ('20200315', 'Water bowl'),
    ('20200318', 'Saddle for camel'),
    ('20200321', 'Dog biscuits'),
    ('20200328', 'Bigfoot shoes');
GO

CREATE TABLE OrdersNew (
    OrderDate date NOT NULL,
    OrderId int IDENTITY NOT NULL,
    OrderDesc varchar(255) NOT NULL,
    CONSTRAINT PKOrdersNew PRIMARY KEY CLUSTERED(OrderDate, OrderId)
    )  
    ON OrdersNewPartitionScheme (OrderDate);  
GO

ALTER TABLE OrdersOld
SWITCH TO OrdersNew PARTITION 3;

Wynik:

Commands completed successfully.

Dane zostały teraz pomyślnie przeniesione na partycję.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Skrypt spisu kolekcji SQL Server -2

  2. Konfiguracja replikacji transakcyjnej serwera SQL

  3. Czy SQL Server może wysłać żądanie internetowe?

  4. Błąd SQL Server 4104:Nie można powiązać wieloczęściowego identyfikatora.

  5. SQL Server DATEPART() vs DATENAME() — jaka jest różnica?