Generate Commands to Create and Drop PKs
Applicability:
SQL Server 2000: Tested
SQL Server 2005: Tested
SQL Server 2008: Tested
SQL Server 2008R2: Tested
SQL Server 2012: Not Tested
Credits:
Author: ChillyDBA
Date: 5 Jul 2012
Description
This SP makes use of the function to get primary key column details.
Returns 2 lists of commands:
Create all PKs in a database using the definitions already in place in the database
Drop all PKs currently in place in the database
NOTE: No changes are made to database structure when running this SP - it only generates TSQL.
NOTE2: The index options in the 'WITH' command in the CREATE scripts were a little challenging to track down in the system tables. In these cases, I have set them to default values as specified in SQL BOL. At a later date, if I discover their whereabouts, I will update the scripts - unless someone can point me in the right direction? In any case, I don't ever remember seeing these options set to anything other than the default values (probably because they are so well hidden)
Code
Stored Procedure:
DROP PROCEDURE dbo.usp_GenerateCreateDropPKCommands
GO
CREATE PROCEDURE dbo.usp_GenerateCreateDropPKCommands(@TableName SYSNAME = NULL)
AS
/***************************************************************
Purpose: To generate commands to create or drop all PKs
No changes are made by this storted procedure
Author: ChillyDBA
History: 5 Jul 2012
****************************************************************/
CREATE TABLE #PKs
(
DatabaseName SYSNAME NULL,
PK_TableSchema SYSNAME NULL,
PK_TableName SYSNAME NULL,
PK_Schema SYSNAME NULL,
PK_Name SYSNAME NULL,
PK_ColumnName SYSNAME NULL,
PK_ColumnOrder INT,
Is_Padded INT,
No_Recompute INT,
Allow_Row_Locks INT,
Allow_Page_Locks INT,
FileGroupName VARCHAR(100),
IX_Type VARCHAR(100),
IX_Sort_Order VARCHAR(5)
)
CREATE TABLE #DropCommands
(
CommandID INT IDENTITY(1,1),
Command VARCHAR(8000)
)
CREATE TABLE #CreateCommands
(
CommandID INT IDENTITY(1,1),
Command VARCHAR(8000)
)
DECLARE
@Command VARCHAR(8000),
@PK_Name SYSNAME,
@PK_Columns VARCHAR(8000)
-- retrieve all PK information for the database
INSERT #PKs
(
DatabaseName,
PK_TableSchema,
PK_TableName,
PK_Schema,
PK_Name,
PK_ColumnName,
PK_ColumnOrder,
Is_Padded,
No_Recompute,
Allow_Row_Locks,
Allow_Page_Locks,
FileGroupName,
IX_Type,
IX_Sort_Order
)
SELECT
pkc.DatabaseName,
pkc.PK_TableSchema,
pkc.PK_TableName,
pkc.PK_Schema,
pkc.PK_Name,
pkc.PK_ColumnName,
pkc.PK_ColumnOrder,
si.Is_Padded,
s.No_Recompute,
si.Allow_Row_Locks,
si.Allow_Page_Locks,
fg.Name,
si.Type_Desc,
CASE sic.Is_Descending_Key WHEN 1 THEN 'DESC' ELSE 'ASC' END
FROM dbo.udf_GetPrimaryKeyColumns(@TableName) pkc
INNER JOIN sys.objects so
ON SCHEMA_ID(pkc.PK_Schema) = so.schema_id
AND pkc.PK_Name = so.name
INNER JOIN sys.indexes si
ON so.parent_object_id = si.OBJECT_ID
AND index_id = 1 --for PK index
INNER JOIN sys.index_columns sic
ON si.OBJECT_ID = sic.OBJECT_ID
AND si.index_id = sic.index_id
AND pkc.PK_ColumnOrder = sic.index_column_id
INNER JOIN sys.stats s
ON si.name = s.name
INNER JOIN sys.filegroups fg
ON si.data_space_id = fg.data_space_id
-- loop through all PK details to create the commands
SELECT @PK_Name = MIN(PK_Name)
FROM #PKs
WHILE @PK_Name IS NOT NULL
BEGIN
SELECT
@Command = '',
@PK_Columns = NULL
-- a useful technique to unpivot a list of columns
-- into a comma-separated list with no trailing comma
SELECT @PK_Columns = COALESCE (@PK_Columns + ', ', '') + '[' + PK_ColumnName + '] ' + IX_Sort_Order
FROM #PKs
WHERE PK_Name = @PK_Name
ORDER BY PK_ColumnOrder
-- create the DROP PK command
SELECT @Command = @Command
+ 'ALTER TABLE ['
+ PK_TableSchema
+ '].['
+ PK_TableName
+ '] DROP CONSTRAINT ['
+ PK_Name
+ ']'
FROM #PKs
WHERE PK_Name = @PK_Name
AND PK_ColumnOrder = 1 -- saves using a messy set of MAX() commands - the PK will always have a columns #1
INSERT #DropCommands(Command)
VALUES (@Command)
-- good practice to zero the variable as is the results of next query are NULL,
-- then the old value (drop command) will remain in the variable
SELECT @Command = ''
-- create the CREATE PK command
SELECT @Command = @Command
+ 'ALTER TABLE ['
+ PK_TableSchema
+ '].['
+ PK_TableName
+ '] ADD CONSTRAINT ['
+ PK_Name
+ '] PRIMARY KEY '
+ IX_Type
+ ' ('
+ @PK_Columns
+ ') '
+ ' WITH (PAD_INDEX =' + CASE Is_Padded WHEN 0 THEN 'OFF' ELSE 'ON' END
+ ', STATISTICS_NORECOMPUTE =' + CASE No_Recompute WHEN 0 THEN 'OFF' ELSE 'ON' END
+ ', SORT_IN_TEMPDB =OFF' -- not stored in sys.indexes so use default value
+ ', IGNORE_DUP_KEY =OFF' -- not stored in sys.indexes so use default value
+ ', ONLINE =OFF' -- not stored in sys.indexes so use default value
+ ', ALLOW_ROW_LOCKS =' + CASE Allow_Row_Locks WHEN 0 THEN 'OFF' ELSE 'ON' END
+ ', ALLOW_PAGE_LOCKS =' + CASE Allow_Page_Locks WHEN 0 THEN 'OFF' ELSE 'ON' END
+ ') ON ['
+ FileGroupName
+ ']'
FROM #PKs
WHERE PK_Name = @PK_Name
AND PK_ColumnOrder = 1 -- saves using a messy set of MAX() commands - the PK will always have a columns #1
INSERT #CreateCommands(Command)
VALUES (@Command)
SELECT @PK_Name = MIN(PK_Name)
FROM #PKs
WHERE PK_Name > @PK_Name
END
SELECT Command AS 'Commands to DROP PKs'
FROM #DropCommands
ORDER BY CommandID
SELECT Command AS 'Commands to CREATE PKs'
FROM #CreateCommands
ORDER BY CommandID
DROP TABLE #DropCommands
DROP TABLE #CreateCommands
DROP TABLE #PKs
Test Code:
USE AdventureWorksDW
GO
EXEC dbo.usp_GenerateCreateDropPKCommands NULL
EXEC dbo.usp_GenerateCreateDropPKCommands 'DimCustomer'