如何在SQL Server中将所有主键从群集转换为非群集

时间:2014-10-18 14:48:21

标签: sql-server primary-key clustered-index

我有一个大型数据库,每个表都有uniqueidentifier聚簇主键。我想从主键中删除聚簇索引,并将其放在每个表的标识列中。

当我想删除聚簇索引时,主键也将被删除。所以我必须再次创建主键。我写的脚本不起作用。请帮帮我

------------drop all clustered primary keys and add nonclustered primary keys-------
DECLARE @table NVARCHAR(512), @tablename NVARCHAR(512),
        @sql NVARCHAR(MAX), @sql2 NVARCHAR(MAX), @sql3 NVARCHAR(MAX), 
        @column NVARCHAR(MAX);

SELECT name As 'Table'
INTO #Indexes
FROM sys.tables 
WHERE name like 'webware%'

WHILE (SELECT COUNT(*) FROM #Indexes) > 0
BEGIN
    SET @table = (SELECT TOP 1 [Table] FROM #Indexes)

    SET @column = (SELECT c.name
                   FROM sys.tables t
                   INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
                   INNER JOIN sys.indexes i ON i.object_id = t.object_id
                   INNER JOIN sys.index_columns ic ON ic.object_id = t.object_id
                   INNER JOIN sys.columns c ON c.object_id = t.object_id 
                                            AND ic.column_id = c.column_id
                   WHERE i.is_primary_key = 1 
                     AND t.name = @table)

    DECLARE @indexname NVARCHAR(512);

    SET @indexname = (SELECT i.name
                      FROM sys.tables t
                      INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
                      INNER JOIN sys.indexes i ON i.object_id = t.object_id
                      INNER JOIN sys.index_columns ic ON ic.object_id = t.object_id
                      INNER JOIN sys.columns c ON c.object_id = t.object_id 
                                               AND ic.column_id = c.column_id
                      WHERE i.is_primary_key = 1 
                        AND t.name = @table)

   SET @sql = 'ALTER TABLE ' + @table + ' DROP CONSTRAINT ' + @indexname

   SET @sql2 = 'DROP INDEX ' +  @indexname + ' ON ' + @table

   SET @sql3 ='ALTER TABLE ' + @table + ' ADD CONSTRAINT ' + @indexname+ ' PRIMARY KEY NONCLUSTERED(' + @column +')'

   EXEC (@sql);
   EXEC (@sql2);
   EXEC (@sql3);

   DELETE FROM #Indexes WHERE [Table] = @table;
END 

DROP TABLE #Indexes

1 个答案:

答案 0 :(得分:0)

主要问题是虽然主键既是约束又是索引,但它是通过约束创建的索引。这意味着,您只能通过CONSTRAINT创建和删除。删除约束后,索引将消失。因此,请移除SET @sql2EXEC (@sql2);

请记住,如果您定义了任何引用任何这些主键的外键,则必须首先删除这些主键,然后在此特定操作完成后重新创建。

您还可以通过同时分配@column@indexname个变量来节省一些查询复杂性:

SELECT @column = c.name,
       @indexname = i.name
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.indexes i ON i.object_id = t.object_id
INNER JOIN sys.index_columns ic ON ic.object_id = t.object_id
INNER JOIN sys.columns c ON c.object_id = t.object_id 
                       AND ic.column_id = c.column_id
WHERE i.is_primary_key = 1 
AND t.name = @table;
相关问题