如何以编程方式禁用主键约束?

问题描述:

我有我的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

没有主键的关系表是非常糟糕的事情。每行必须以某种方式唯一。如果没有候选键被指定为主键,则整行必须是唯一的。

我不知道你为什么要删除主键约束,但我会考虑这样做,不与其他候选键的一个替代它的是,应进行调查红旗。

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结果集。

请勿违反PKEY约束条件。恕我直言,这是最好的解决方案,你将避免重建PKEY的成本,以及如果你不能(重复剩余)?

OR

阅读模式,以了解如何重建PKEY约束,则使用previouly发布的解决方案。

它可能是一个更好的主意,你的整个表SELECT到一个临时表,执行转换上飞如果可能的话,再拷贝回来。如果不能即时转换,则将简单的整数行索引添加为临时表的主键会容易得多。

要找出主键是什么(假设您的表是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准确(你会错过排序顺序和文件组) ,但更容易编程。

以下为我工作(你必须的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)