2014-10-18 7 views
0

У меня есть большая база данных с uniqueidentifier кластеризованным первичным ключом на каждой его таблице. Я хочу удалить кластерные индексы из первичных ключей и поместить их в столбец идентификаторов в каждой таблице.Как преобразовать все первичные ключи из кластеризованного в некластерный в SQL Server

Когда я хочу удалить кластерные индексы, первичный ключ также будет удален. Поэтому я снова должен создать первичные ключи. сценарий, который я написал, не работает. Пожалуйста, помогите мне

------------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 
+2

OK - у вас есть много кода здесь, глядя в основном ОК для меня - в чем проблема? Разве это не делает то, что вы хотите? Вы получили сообщение об ошибке? Если да: ** что такое ** ошибка ?? –

+0

есть 2 ошибки. first: Невозможно удалить индекс «WebWare_System_SystemType.PK_WebWare_System_SystemType», потому что он не существует или у вас нет разрешения. –

+0

second: Операция CREATE UNIQUE INDEX завершена, потому что был найден дубликат ключа для имени объекта «dbo.WebWare_Membership_UserInRole» и имени индекса «PK_WebWare_Membership_UserInRole». Значение повторяющегося ключа - (55303843-6d22-4a85-b17f-12826e630cac). Msg 1750, уровень 16, состояние 0, строка 1 Не удалось создать ограничение. См. Предыдущие ошибки. Заявление было прекращено. –

ответ

0

Основная проблема заключается в том, что в то время как первичный ключ является как ограничение и индекс, это показатель, который создается с помощью ограничения. Смысл, вы создаете и опускаете только через CONSTRAINT. Как только вы отмените ограничение, индекс исчезнет. Итак, удалите SET @sql2 и EXEC (@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; 
+0

@PariaMolayem: для ошибки № 1, пожалуйста, убедитесь, что вы действительно можете отказаться от этого ПК. По крайней мере, найти объект еще можно сказать, что с этим именем не существует объекта. Для ошибки № 2 я считаю, что ваше предположение о том, что PK является просто полем UNIQUEIDENTIFIER, не всегда корректно, и эта таблица 'UserInRole' имеет составной ключ этого поля, а другой, то есть ваш запрос должен быть обновлен для учета составных PK , И наконец, почему JOIN to Schemas? Если все таблицы находятся в одной и той же схеме, удалите этот JOIN. –

+0

благодарит за советом. теперь у меня нет никакой ошибки, но все же это не работает для некоторых таблиц. когда я запускаю «@sql» и «@ sql3» только для этих таблиц, он работает. но когда я запускаю его динамически в этом скрипте, он не работает. Я не знаю, в чем проблема или где искать проблему. –

+0

это еще одна ошибка: «Msg 3733, уровень 16, состояние 2, строка 6 Constraint« PK_WebWare_Portal_Modules_Related »не принадлежит к таблице« WebWare_System_SchemaInSystem ». Msg 3727, Уровень 16, Состояние 0, Строка 6 Невозможно отказаться от ограничения. Смотрите предыдущие ошибки, знаете ли вы, о чем это? –

 Смежные вопросы

  • Нет связанных вопросов^_^