snippetsqlModerate
How to create a partitioned table based on date?
Viewed 0 times
createdatebasedhowpartitionedtable
Problem
I'm trying to create a partitioned table where partitioning is determined by
Msg 1908, Level 16, State 1, Line 1 Column 'OrderDate' is partitioning
column of the index 'PK_OrderID'. Partition columns for a unique index
must be a subset of the index key. Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
How to modify this to get it work:
OrderDate. I'm trying to create a clustered index on OrderDate and a nonclustered primary key on OrderID. But I get an error saying:Msg 1908, Level 16, State 1, Line 1 Column 'OrderDate' is partitioning
column of the index 'PK_OrderID'. Partition columns for a unique index
must be a subset of the index key. Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
How to modify this to get it work:
CREATE TABLE dbo.Orders
(
OrderID INT NOT NULL ,
Name NVARCHAR(20) NULL ,
OrderDate DATE NOT NULL ,
)
ON PartSchemeOrders(OrderDate)
CREATE CLUSTERED INDEX IX_OrderDate
on dbo.Orders (OrderDate)
on PartSchemeOrders(OrderDate)
ALTER TABLE dbo.Orders
ADD CONSTRAINT PK_OrderID PRIMARY KEY NONCLUSTERED (OrderID)Solution
As the error message says, any partition-aligned unique index has to include the partitioning key in the index key. This requirement exists so the engine can enforce uniqueness on updates without checking every partition.
In your case, this means including
Of course this changes the uniqueness that the nonclustered index enforces. Now, only the combination of
The alternative is to have the nonclustered primary key non-aligned:
This preserves the uniqueness of
You can read more about partitioning in this section of Books Online and more on the issues of aligned and non-aligned indexes in this excellent answer by Remus Rusanu.
In your case, this means including
OrderDate in the nonclustered index key, or having a non-aligned index. Both are potentially valid choices, depending on your circumstances. To preserve alignment, your table and index definitions would be:CREATE TABLE dbo.Orders
(
OrderID integer NOT NULL,
Name nvarchar(20) NULL,
OrderDate date NOT NULL,
CONSTRAINT PK__Orders_OrderID_OrderDate
PRIMARY KEY NONCLUSTERED
(OrderID, OrderDate)
ON PS (OrderDate)
)
ON PS (OrderDate);
GO
CREATE CLUSTERED INDEX CX__Orders_OrderDate
ON dbo.Orders (OrderDate)
ON PS (OrderDate);Of course this changes the uniqueness that the nonclustered index enforces. Now, only the combination of
OrderID and OrderDate is guaranteed to be unique. It is theoretically possible to add duplicate OrderIDs, so long as the OrderDate is different. Whether this change of semantic is acceptable to you depends on your circumstances, but it is something to be aware of.The alternative is to have the nonclustered primary key non-aligned:
CREATE TABLE dbo.Orders
(
OrderID integer NOT NULL,
Name nvarchar(20) NULL,
OrderDate date NOT NULL,
CONSTRAINT PK__Orders_OrderID
PRIMARY KEY NONCLUSTERED
(OrderID)
ON [PRIMARY]
)
ON PS (OrderDate);
GO
CREATE CLUSTERED INDEX CX__Orders_OrderDate
ON dbo.Orders (OrderDate)
ON PS (OrderDate);This preserves the uniqueness of
OrderID alone, and has some benefits with queries that compute MIN or MAX aggregates using the index, but you lose the ability to SWITCH partitions in and out without dropping the primary key and recreating it after the switching operation.You can read more about partitioning in this section of Books Online and more on the issues of aligned and non-aligned indexes in this excellent answer by Remus Rusanu.
Code Snippets
CREATE TABLE dbo.Orders
(
OrderID integer NOT NULL,
Name nvarchar(20) NULL,
OrderDate date NOT NULL,
CONSTRAINT PK__Orders_OrderID_OrderDate
PRIMARY KEY NONCLUSTERED
(OrderID, OrderDate)
ON PS (OrderDate)
)
ON PS (OrderDate);
GO
CREATE CLUSTERED INDEX CX__Orders_OrderDate
ON dbo.Orders (OrderDate)
ON PS (OrderDate);CREATE TABLE dbo.Orders
(
OrderID integer NOT NULL,
Name nvarchar(20) NULL,
OrderDate date NOT NULL,
CONSTRAINT PK__Orders_OrderID
PRIMARY KEY NONCLUSTERED
(OrderID)
ON [PRIMARY]
)
ON PS (OrderDate);
GO
CREATE CLUSTERED INDEX CX__Orders_OrderDate
ON dbo.Orders (OrderDate)
ON PS (OrderDate);Context
StackExchange Database Administrators Q#29420, answer score: 11
Revisions (0)
No revisions yet.