Удаление всех первичных ключей - PullRequest
2 голосов
/ 26 февраля 2010

Это будет звучать как сумасшедшая просьба. Базы данных, из которых я отправляю отчеты, не имеют внешних ключей, и каждый первичный ключ - это identity_column. Это затрудняет использование таких инструментов, как TOAD, потому что Intellisense работает, считывая отношения PK и FK.

У кого-нибудь есть сценарий для удаления первичных ключей из каждой таблицы в базе данных, чтобы я мог заменить их на «правильный» PK и добавить FK для помощи в составлении отчетов?

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

Любой совет будет оценен.

------- РЕДАКТИРОВАТЬ Это обновлено с правильной информацией. ----------------

Спасибо, ребята, но я понял, что допустил ошибку. Почти у каждой таблицы есть «identity_column» со свойством identity. Эта идентичность является кластерным индексом. Однако он не обозначен как первичный ключ.

Во-первых, в чем разница между первичным ключом и кластерным индексом?

Во-вторых, как я могу написать все кластерные индексы? Будет ли это работать?

SELECT 
  'ALTER TABLE ' + OBJECT_NAME(OBJECT_ID) + ' DROP CONSTRAINT ' + name 
FROM sys.indexes WHERE type_desc = 'CLUSTERED'

Спасибо за ваше терпение

Ответы [ 5 ]

5 голосов
/ 26 февраля 2010

Как насчет чего-то вроде этого ?

-- Helper Procedure 
CREATE PROC #DropConstraints 
  @tableSchema nvarchar(max), 
  @tableName nvarchar(max), 
  @constraintType nvarchar(20) 
AS 
BEGIN 
  DECLARE @cName nvarchar(max); 

  DECLARE constraint_cursor CURSOR FOR 
    SELECT CONSTRAINT_NAME  
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
    WHERE  
      CONSTRAINT_TYPE = @constraintType 
      AND TABLE_NAME = @tableName 
      AND TABLE_SCHEMA = @tableSchema 

  OPEN constraint_cursor 

  FETCH NEXT FROM constraint_cursor INTO @cName 
  WHILE @@FETCH_STATUS = 0 
  BEGIN 
    EXEC ('ALTER TABLE ' + @tableSchema + '.' + @tableName + ' DROP CONSTRAINT ' + @cName); 
    FETCH NEXT FROM constraint_cursor INTO @cName 
  END 

  CLOSE constraint_cursor 
  DEALLOCATE constraint_cursor 
END 
GO

BEGIN TRANSACTION

  -- Setup Cursor for looping 
  DECLARE table_cursor SCROLL CURSOR FOR 
    SELECT TABLE_SCHEMA, TABLE_NAME  
    FROM INFORMATION_SCHEMA.TABLES 

  OPEN table_cursor

  -- Declare Variables

  DECLARE 
    @tableSchema nvarchar(max), 
    @tableName nvarchar(max) 

 -- Drop Primary Keys 

  FETCH FIRST FROM table_cursor INTO @tableSchema, @tableName 
  WHILE @@FETCH_STATUS = 0 
  BEGIN 
    EXEC #DropConstraints @tableSchema, @tableName, 'PRIMARY KEY'; 

    FETCH NEXT FROM table_cursor INTO @tableSchema, @tableName 
  END 

  -- Cleanup 
  CLOSE table_cursor 
  DEALLOCATE table_cursor

COMMIT TRANSACTION 
GO

DROP PROCEDURE #DropConstraints;
GO
4 голосов
/ 26 февраля 2010

Другим вариантом будет двухэтапный процесс:

  1. сначала выберите необходимую информацию в представлениях системного каталога и используйте ее для построения операторов T-SQL, которые вам понадобятся для удаления индексов и ограничений:

    SELECT
      'ALTER TABLE ' + OBJECT_NAME(OBJECT_ID) + ' DROP CONSTRAINT ' + name
    FROM sys.indexes WHERE is_primary_key = 1
    
  2. используйте этот результирующий набор, скопируйте и вставьте его в новое окно запроса и запустите его - он удалит все ограничения первичного ключа из всех ваших таблиц в базе данных, в которой вы запустили это в

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

1 голос
/ 26 февраля 2010

Чтобы отбросить все кластеризованные индексы, необходимо различать ситуации, в которых ограничение (первичное или уникальное) является кластеризованным индексом или является ли индекс без ограничений кластерным индексом. Вы не можете удалить индексы ограничения с помощью DROP INDEX и не можете удалить индексы с помощью DROP CONSTRAINT. Так что вам нужно сделать что-то вроде:

Select 'ALTER TABLE ' + QUOTENAME(OBJECT_NAME([object_id])) + ' DROP CONSTRAINT ' + QUOTENAME([name])
From sys.indexes
Where is_primary_key = 1 Or is_unique_constraint = 1
 And type_desc = 'CLUSTERED'
Union All
Select 'DROP INDEX ' + QUOTENAME([name]) + ' ON ' + QUOTENAME(OBJECT_NAME([object_id])) 
from sys.indexes
Where is_primary_key = 0 And is_unique_constraint = 0
 And type_desc = 'CLUSTERED'

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

Я должен спросить, действительно ли это то, что вы хотите сделать. Отбросив все кластеризованные индексы, вы принудительно восстановите все индексы во всех затронутых таблицах.

1 голос
/ 26 февраля 2010

Чтобы ответить на ваш вопрос о разнице между ПК и кластерным индексом:

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

Имейте в виду, что если в прошлом у вас не было первичных и внешних ключей, ваши данные могут быть тщательно скрыты, и вам не следует создавать внешние ключи, пока вы их не очистите.

0 голосов
/ 27 июля 2015

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

Однако никто не заботится о том факте, что объекты могут отсутствовать в схеме по умолчанию, а также не контролирует, что индексы и ограничения не являются системным объектом, который необходим SQL Server.

это простая версия, только с удалением первичных ключей:

select  'ALTER TABLE ' + quotename(object_schema_name(object_id)) + '.'
        + quotename(object_name(object_id)) + ' DROP CONSTRAINT ' + name
from    sys.indexes
where   is_primary_key = 1

вот вторая версия, которая также сценарий удаления кластерных индексов не первичного ключа:

select  'ALTER TABLE ' + quotename(object_schema_name(object_id)) + '.'
        + quotename(object_name([object_id])) + ' DROP CONSTRAINT '
        + quotename([name])
from    sys.indexes
where   is_primary_key = 1
        or is_unique_constraint = 1
        and type_desc = 'CLUSTERED'
union all
select  'DROP INDEX ' + quotename(i.[name]) + ' ON '
        + quotename(object_schema_name(i.[object_id])) + '.'
        + +quotename(object_name(i.[object_id]))
from    sys.indexes as i
        inner join sys.objects as o on o.object_id = i.object_id
where   is_primary_key = 0
        and is_unique_constraint = 0
        and i.type_desc = 'CLUSTERED'
        and o.[type] not in ( 'S' )
        and o.is_ms_shipped = 0
...