2009-04-10 5 views
6

У меня есть таблица с первичным ключом в моей таблице MS SQL Server 2005. Я хотел бы отключить его. Теперь я получаю ошибку:Как отключить ограничение первичного ключа программным путем?

Нарушение ограничения PRIMARY KEY 'PK_Name'. Невозможно вставить дубликат ключа в объект «dbo.Table».

Я бы хотел, чтобы эта ошибка не возникала и работать с PRIMARY KEY как с обычным столбцом без ограничений, а затем восстанавливать это ограничение после внесения в него изменений. Как отключить это ограничение?

Запрос, который я хочу выполнить, в то время как ограничение PRIMARY KEY отключено, является сложным и изменяет значения в столбце первичного ключа. В некоторых точках этого запроса он попадает в ситуацию, когда у меня есть повторяющиеся значения в столбце первичного ключа. Но в конце моего запроса у меня все значения уникальны.

Я мало знаю об этом ограничении, потому что я не дизайнер этой таблицы. У меня есть это имя, но я не сейчас, если он сгруппирован и так далее (что такое конфиг этого столбца).

+0

Изменение значений PK: это звучит действительно очень странно! Как вы можете изменить значения, которые должны использоваться для реализации отношений между таблицами? Вы уверены, что решение, которое вы пытаетесь разработать, - это решение вашей проблемы? –

+0

У меня нет никаких отношений на этом ПК. Я знаю, что это звучит странно и, возможно, так, но это решение, которое мне нужно применить в этом месте. –

+1

Если есть дубликаты, то это уже не первичный ключ, так зачем добавлять его обратно? Вы считали связанный первичный ключ, который позволит вам сохранить ограничение? –

ответ

5

Реляционные таблицы без первичных ключей - очень плохая вещь. Каждая строка должна быть уникальной. Если ни один из ключей-кандидатов не обозначен как первичный, вся строка должна быть уникальной.

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

+0

Вы указали, почему это решение плохо, поэтому я решил отметить ваш ответ как правильный. И еще больше я задал еще один вопрос о решении, которое будет делать эту работу правильным образом: –

+3

Одна из причин, по которой вы можете отказаться от ограничения, заключается в том, что вы выполняете изменения таблицы для большого количества данных. Недавно мы добавили два новых столбца в таблицу с 8 записей Mil. Для добавления столбцов потребовалось 23 часа. Если мы отбросим ограничения, это займет 12 минут. Конечно, мы говорим об автономном обновлении. Если это онлайн-обновление, было бы опасно отказаться от ограничений. – dsum

13
ALTER TABLE mytable DROP CONSTRAINT PK_Name 

Чтобы включить его:

ALTER TABLE mytable ADD CONSTRAINT PK_Name PRIMARY KEY /* CLUSTERED */ (pk_column) 

раскомментировать CLUSTERED, если вы хотите, чтобы ваша PRIMARY KEY быть кластерной (т.е. строки таблицы сами при упорядочении)

Чтобы выяснить, если PRIMARY KEY кластеризован по нет, выпуск:

EXEC sp_help 'mytable' 

и посмотрите в возвращаемом наборе результатов 6th.

+0

Это, похоже, удаляет ограничение.Как его восстановить? –

+0

Проблема в том, что я не знаю, есть ли у меня первичный ключ CLUSTERED или нет. Поэтому я не могу восстановить его таким образом. –

+1

Первичный ключ кластеризуется по умолчанию - поэтому, если вы его не изменили, он сгруппирован. –

0

Не нарушайте ограничение PKEY. ИМХО это лучшее решение, вы избежите затрат на восстановление PKEY, и что, если вы не сможете (дублировать оставшееся)?

ИЛИ

Прочитайте схему, чтобы узнать, как восстановить PKEY ограничение затем использовать Previouly отправил решение.

+0

Восстановление PKEY для меня не для меня, поэтому я хотел бы пойти в этом направлении. –

0

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

2

Чтобы узнать, что такое первичный ключ (если ваша таблица является dbo.T1):

select si.name as name, 
(case when (si.status & 16) > 0 then 1 else 0 end) as isclust, 
si.keycnt as keycnt, 
si.indid as indid 
from sysindexes si 
left join sysobjects so on so.id = si.id 
where si.indid > 0 
and si.indid < 255 
and so.xtype <> 'S' 
and so.id = OBJECT_ID('dbo.T1') 
and (si.status & 2048) > 0 

Это даст вам что-то вроде:

 
name         isclust  keycnt indid 
--------------------------------------------------------------- 
PK_T1          1   2  1 

Здесь у вас есть первичный ключ имя (PK_T1), будь то кластерный или нет, количество полей в нем (2) и index id (он вам понадобится позже).

Следующая выполните следующее:

select INDEX_COL('dbo.T1', 1, 1) --returns Field1 
select INDEX_COL('dbo.T1', 1, 2) --returns Field2 

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

Имея эту информацию, вы должны быть в состоянии восстановить первичный ключ следующим образом:

ALTER TABLE dbo.T1 ADD CONSTRAINT PK_T1 PRIMARY KEY CLUSTERED (Field1, Field2) 

Update: Это может быть не столь точны, как синтаксический анализ результата sp_help упомянул earlier (вы упускаете порядок сортировки и группы файлов) , но проще программно.

0

Ниже работал для меня (вы должны быть db_owner для выполнения этого действия)

--Declare переменного, чтобы получить контрсилы на столе и присваиваемые переменную

DECLARE @PK_CONST_NAME AS varchar(100)<br> 
SET @PK_CONST_NAME = (SELECT NAME FROM SYS.KEY_CONSTRAINTS WHERE OBJECT_NAME(PARENT_OBJECT_ID) = '[TABLENAME]') 

- Переменные для хранения запросов

SET @DropAlterQuery = ''<br> 
SET @RecreateAlterQuery = '' 

- Contruct Запрос

SET @DropAlterQuery = CONCAT('ALTER TABLE [TABLENAME] DROP CONSTRAINT ',@PK_CONST_NAME) 

- Выполнение запроса сконструированный для Droping контрсил

EXEC(@DropAlterQuery) 

- Alter Column Size (Теперь это утверждение работает контрсилы отбрасываются)

ALTER TABLE [TABLENAME] 
ALTER COLUMN BATCH_ID VARCHAR(200) NOT NULL 

- Contruct запрос

SET @RecreateAlterQuery = CONCAT(CONCAT('ALTER TABLE [TABLENAME] ADD CONSTRAINT ',@PK_CONST_NAME), ' PRIMARY KEY (<<PRIMARY KEY COLUMN1>>, <<PRIMARY KEY COLUMN2>>, <<PRIMARY KEY COLUMN2>>... So on)') 

- Выполнение запроса сконструированный для воссоздают сброшенные контрсилами

EXEC(@RecreateAlterQuery) 
Смежные вопросы