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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何以编程方式禁用主键约束?相关的知识,希望对你有一定的参考价值。

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

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

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

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

我对这个约束知之甚少,因为我不是这个表的设计者。我有它的名字,但我现在不知道它是否已经聚集等等(这个专栏的配置是什么)。

答案

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

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

另一答案
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结果集。

另一答案

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

另一答案

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

要么

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

另一答案

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

另一答案

以下为我工作(您必须是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 = ''

- 构造查询

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)

以上是关于如何以编程方式禁用主键约束?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式更改 UILabel 上的约束打破布局

如何在单击按钮时在一个视图控制器中正确启用和禁用约束

以编程方式向 UIImageView 添加约束

如何以编程方式向以编程方式创建的 UIView 添加约束?

如何在目标 c 中以编程方式添加约束

如何以编程方式设置约束加常量?