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

时间:2009-04-10 09:29:57

标签: sql-server sql-server-2005 tsql

我的MS SQL Server 2005表中有一个主键表。我想禁用它。现在我得到错误:

违反PRIMARY KEY约束'PK_Name'。无法在对象'dbo.Table'中插入重复键。

我希望不会发生此错误,并且与没有约束的普通列一样使用PRIMARY KEY,并且在对其进行更改后恢复此约束。如何禁用此约束?

查询我想在PRIMARY KEY约束被禁用时执行是复杂的并且更改主键列中的值。在此查询的某些点上,当主键列中存在重复值时,它会遇到这种情况。但在我的查询结束时,我的所有值都是唯一的。

我对这个约束知之甚少,因为我不是这个表的设计者。我有它的名字,但我现在不知道如果它是集群的等等(这列的配置是什么)。

6 个答案:

答案 0 :(得分:16)

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

答案 1 :(得分:5)

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

我不确定为什么你必须删除一个主键约束,但我会考虑这样做而不用其他候选键替换它是一个应该被调查的红旗。

答案 2 :(得分: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)

更新:这可能不如解析提到的earlier的sp_help结果准确(您将错过排序顺序和文件组),但更容易以编程方式进行。

答案 3 :(得分:0)

不要违反PKEY约束。恕我直言,这是最好的解决方案,你将避免重建PKEY的成本,如果你不能(重复剩余)怎么办?

OR

阅读架构以了解如何重建PKEY约束,然后使用之前发布的解决方案。

答案 4 :(得分:0)

最好将SELECT整个表放入临时表中,如果可能的话,即时进行转换,然后将其复制回来。如果你无法动态转换,那么在临时表上添加一个简单的整数行索引作为主键就容易多了。

答案 5 :(得分:0)

以下为我工作(您必须是db_owner才能执行此操作)

- 声明一个变量以获得表格上的约束并分配给变量

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 = ''

- 构建查询

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

- 执行为删除约束而构建的查询

EXEC(@DropAlterQuery)

- 更改列大小(现在此语句可作为约束删除)

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

- 构建查询

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)