2009-04-10 97 views
6

我有我的MS SQL Server 2005表中的主鍵的表。我想禁用它。現在我得到的錯誤:PRIMARY KEY約束 'PK_NAME' 的如何以編程方式禁用主鍵約束?

衝突。無法在對象'dbo.Table'中插入重複鍵。

我想這個錯誤不會發生,並與PRIMARY KEY像正常柱無約束的工作,不是做我更改之後恢復此約束。如何禁用這個約束?

查詢我想執行,同時主鍵約束禁用是複雜的,變化的主鍵列值。在這個查詢的某些點上,當我在主鍵列中有重複的值時,它會觸發這種情況。但在查詢結束時,我的所有值都是唯一的。

我不知道很多關於此約束,因爲我不是這個表的設計師。我有它的名字,但是現在如果它是集羣化的(如此配置)。

+0

更改PK值查詢:這聽起來真的很奇怪!你如何改變應該用於實現表之間關係的值?你確定你正在試圖闡述的解決方案是解決你的問題嗎? – 2009-04-10 10:20:42

+0

我對這個PK沒有任何關係。我知道這聽起來很奇怪,也許是這樣,但這是我需要在這個地方應用的解決方案。 – 2009-04-10 10:43:04

+1

如果有重複,那麼它不再是一個主鍵,那麼爲什麼將它添加回來呢?你有沒有考慮一個連接的主鍵,可以讓你保持約束? – 2009-04-10 11:36:40

回答

5

沒有主鍵的關係表是非常糟糕的事情。每行必須以某種方式唯一。如果沒有候選鍵被指定爲主鍵,則整行必須是唯一的。

我不知道你爲什麼要刪除主鍵約束,但我會考慮這樣做,不與其他候選鍵的一個替代它的是,應進行調查紅旗。

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

請勿違反PKEY約束條件。恕我直言,這是最好的解決方案,你將避免重建PKEY的成本,以及如果你不能(重複剩餘)?

OR

閱讀模式,以瞭解如何重建PKEY約束,則使用previouly發佈的解決方案。

0

它可能是一個更好的主意,你的整個表SELECT到一個臨時表,執行轉換上飛如果可能的話,再拷貝回來。如果不能即時轉換,則將簡單的整數行索引添加爲臨時表的主鍵會容易得多。

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)索引ID(稍後您將需要它)。

下運行以下命令:

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

這會給你從索引兩個字段的名稱。第一個參數是你的表名,第二個是先前獲得的索引ID,第三個是從1到keycnt循環(在前一步中返回)。

有了這個信息,你應該能夠重建主鍵如下:

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

更新:這可能不會像解析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) 

- 執行對滴速的約束上

EXEC(@DropAlterQuery) 

構造查詢 - 改變柱尺寸(現在,這個說法可以作爲約束上被丟棄)

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)