I have a table 'X' and did the following
CREATE PARTITION FUNCTION PF1(INT) AS RANGE LEFT FOR VALUES (1, 2, 3, 4)
CREATE PARTITION SCHEME PS1 AS PARTITION PF1 ALL TO ([PRIMARY])
CREATE CLUSTERED INDEX CIDX_X ON X(col1) ON PS1(col1)
this 3 steps created 4 logical partitions of the data I had.
My question is, how do I revert this partitioning to its original state ?
After 2 days of continuous searching
The Steps:
DROP INDEX CIDX_X on X /* drop the clustered */
CREATE CLUSTERED INDEX CIDX_X1 ON X(col1) ON [PRIMARY] /* Create another clustered index on the table to free it from the partitioning scheme; Here, the "ON [primary]" part is key to removing the partition scheme from the table ! */
DROP PARTITION SCHEME PS1
DROP PARTITION FUNCTION PF1
DROP INDEX CIDX_X1 ON X /* drop the dummy clustered index you created, as it was only created to free the table from the partitioning scheme */
I found that some additional steps should be added to the answer given by Storm, since, there are some points like ... before deleting the clustered index, the publication needs to be dropped because it wont allow the clustered index to get dropped before that and after dropping those partition-scheme and partition function needs to be recreated, and publication also again needs to be started.
Note: I am using SQL 2012
Primary key is normally the most commonly used clustered constraint, so wherever i used primary key, consider that those steps also apply to Clustered constraints too. Also, PS= Partition Scheme, PF = Partition Function.
Some preparatory steps:
Make a drop publication script
Make a create publication script
Identify all tables who have dependencies with the Partition Scheme,and also note down their primary key/clustered index.Also, note down all the fields which the primary key column uses (better to generate the script for primary key or clustered index)
Make a script for tables getting affected.
Make a script for PF and PS that are in question.
All the above, using SQL Management Studio "generate scripts" upon right click. And choose drop and create.
Now, when everything is ready.
1. Drop the publication (use the script that you generated)
2. Drop the Primary key constraint of those tables which are linked with the PS.
alter table [tablename] drop constraint [pk_name]
3. Make a dummy constraint but use the same fields that you used in that deleted primary key. CREATE CLUSTERED INDEX CIDX_X1 ON tablename(field1,field2,field3,field4) ON [PRIMARY]
4. drop the partition scheme and function.
DROP PARTITION SCHEME [PartitionSchemeName_PS]
GO
DROP PARTITION FUNCTION [PartitionfunctionName_PF]
GO
Drop the Dummy Index
DROP INDEX CIDX_X1 ON tablename
Add back the Clustered index/primary key constraint(using the generated scripts as mentioned earlier.
Create the Partition function and Partition schema (ensure that the number of elements of PS > PF. where PS = PF+2 elements)
Add back the publisher (use the generated scripts)
Related
SQL Server 2012 SP3
I've got a table with a clustered unique index which I want to move to the SECONDARY filegroup.
The standard method is to ALTER TABLE ... DROP CONSTRAINT and then ALTER TABLE ... ADD CONSTRAINT it back again in the new filegroup. However, there's a chain of FKs which I'd have to drop and recreate.
Is there any other way to move the underlying data without lots of drops?
Use CREATE UNIQUE CLUSTERED INDEX...WITH(DROP_EXISTING=ON) to move the primary key index to a different filegroup. This will also avoid the sort.
CREATE UNIQUE CLUSTERED INDEX PK_YourTable ON dbo.YourTable(YourPrimaryKeyColumn)
WITH(DROP_EXISTING=ON)
ON [YourSecondaryFileGroup];
In SQL Server, there is no option for altering the cluster index if i want to add one new column to cluster index definition. The only option is to drop and create cluster index with new definition.
From what I understand, drop and create of cluster index is a very costly and time consuming for high volume tables.
Cluster index recreate rebuilds all the nonclustered indexes on a table which can be very expensive.
The question to this forum "is there anyway we can speed up cluster index recreating"
The one workaround what I can think is to drop all non-cluster index before recreating cluster index. Will this approach work ?
Use
CREATE .... WITH (DROP_EXISTING = ON)
Instead of
DROP ...
CREATE ...
This means the non clustered indexes only have to be updated once (to include the new key column). Not twice - first to use the physical rid and then again to use the new CI key.
The DROP_EXISTING clause tells SQL Server that the existing clustered index is being dropped but that a new one will be added in its place, letting SQL Server defer updating the nonclustered index until the new clustered index is in place..
Additionally, SQL Server won't rebuild the nonclustered index at all if the clustered index key doesn't change and is defined as UNIQUE, which isn't an obvious performance benefit of defining a clustered index as UNIQUE
Example
CREATE TABLE #T
(
A INT,
B INT,
C INT
)
CREATE CLUSTERED INDEX IX ON #T(A)
CREATE CLUSTERED INDEX IX ON #T(A,B) WITH (DROP_EXISTING = ON)
DROP TABLE #T
I am trying to change a primary key Id to identity to increment 1 on each entry. But the column has been referenced already by other tables. Is there any way to set primary key to auto increment without dropping the foreign keys from other tables?
If the table isn't that large generate script to create an identical table but change the schema it created to:
CREATE TABLE MYTABLE_NEW (
PK INT PRIMARY KEY IDENTITY(1,1),
COL1 TYPEx,
COL2 TYPEx,
COLn
...)
Set your database to single-user mode or make sure no one is in the
database or tables you're changing or change the table you need to
change to READ/ONLY.
Import your data into MYTABLE_NEW from MYTABLE using set IDENTITY_INSERT on
Script your foreign key constraints and save them--in case you need
to back out of your change later and/or re-implement them.
Drop all the constraints from MYTABLE
Rename MYTABLE to MYTABLE_SAV
Rename MYTABLE_NEW to MYTABLE
Run constraint scripts to re-implement constraints on MYTABLE
p.s.
you did ask if there was a way to not drop the foreign key constraints. Here's something to try on your test system. on Step 4 run
ALTER TABLE MYTABLE NOCHECK CONSTRAINT ALL
and on Step 7 ALTER TABLE MYTABLE CHECK CONSTRAINT ALL. I've not tried this myself -- interesting to see if this would actually work on renamed tables.
You can script all this ahead of time on a test SQL Server or even a copy of the database staged on a production server--to make implementation day a no-brainer and gauge your SLAs for any change control procedures for your company.
You can do a similar methodology by deleting the primary key and re-adding it back, but you'll need to have the same data inserted in the new column before you delete the old column. So you'll be deleting and inserting schema and inserting primary key data with this approach. I like to avoid touching a production table if at all possible and having MYTABLE_SAV around in case "anything" unexpected occurs is a comfort to me personally--as I can tell management "the production data was not touched". But some tables are simply too large for this approach to be worthwhile and, also, tastes and methodologies differ largely from DBA to DBA.
I need to update a large number of keys in a large SQL Server 2005 database and will be dropping FKs and PKs on a bunch of tables, doing the update (which replaces the values of the PK/FK) and then adding the FK and PK again.
My questions are:
Will this process have any effect on exsiting indexes that exist on those tables, either
indexes that include the PK/FK fields or indexes on other unaffected fields. ie will all indexes still exists, will they need a rebuild?
Will this process affect table statistics, requiring a recalc?
Many thanks
If you drop a PK (which is usually a clustered index) SQL Server will drop and recreate all non clustered indexes(this is needed because if you have a clustered index the non clustered indexes point to the clustered index). If you don't have a clustered index (a heap) the non clustered indexes point to the data row
rebuilding a clustered index will automatically update statistics, a reorg won't
If you created the keys with cascade update then they should be updated automatically
example
create table pri(id int not null primary key)
go
create table ForeignK(fid int not null)
go
ALTER TABLE dbo.ForeignK ADD CONSTRAINT
FK_ForeignK_pri FOREIGN KEY
(fid) REFERENCES dbo.pri(id) ON UPDATE CASCADE
ON DELETE NO ACTION
insert pri values(1)
insert ForeignK values(1)
now update the PK table
update pri set id = 5
go
this will now be 5 also
select * from ForeignK
Every change in indexed column has a propagation in structure change.
For foreign key you could disable them and then rebuild. For private key only thing you can do is to rebuild them. I think that SQLMenace explained it clearly why.
More
We're doing a cleanup on a group of databases, and the first step is to get all indexes in the database into the correct filegroups.
Currently, those indexes are mixed between the DATA filegroup and the INDEXES filegroup; they all need to move to the INDEXES filegroup.
This can be done easily enough in script I guess, however how do you best handle an index on a Primary Key?
The following command
DROP INDEX table.indexname
produces the error:
An explicit DROP INDEX is not allowed
on index 'Answer.PK_Answer'. It is
being used for PRIMARY KEY constraint
enforcement.
So what is the best way? Do I need to drop the Primary Key, then drop the Index, then re-create the primary key and finally re-create the index on the correct filegroup? Are there any drawbacks to this method?
You can try the below statement which drops and recreates the index on the index filegroup
CREATE CLUSTERED INDEX PK_Answer
ON tablename(Answer)
WITH (DROP_EXISTING = ON);
Since he has a primary key:
CREATE UNIQUE CLUSTERED INDEX PK_Answer ON tablename(Answer) WITH (DROP_EXISTING = ON);
In case anyone else needed this information (I did), add the FILEGROUP at the end if you wish to MOVE the recreated PRIMARY KEY to another location. Neither of the previous answers stipulated this portion:
CREATE UNIQUE CLUSTERED INDEX PK_TableName_Answer ON TableName(Answer) WITH(DROP_EXISTING = ON) ON [INDEX];