更新:这是一个比正常情况更多的维护问题。
我有下表:
CourseId StudentId
---------------------
1 1
1 2
2 1
CourseId
和StudentId
是复合主键。
假设我想因为某种原因将courseid = 1更新到courseid = 2。这将导致主键约束问题。
有什么不同的方法可以解决这个问题?
答案 0 :(得分:1)
通常,您应该尝试为永远不会更改的主键选择列,因为更改它们可能会有很多原因,其中一个原因是主键约束违规。
为什么要更改CourseId(可能是课程表中的PK),为什么要将其更改为已存在的CourseId?
编辑:添加答案
接受的解决方案存在的问题是,如果要处理大量的表,则删除并重新创建聚簇索引(主键)可能非常耗时且有问题as explained here。
更好的解决方案是首先不插入重复项。例如,如果这些是表中仅有的两列,则可以简单地更新不会导致冲突的记录,然后删除那些将存在的记录(因为已存在的行包含您想要的值集)。
begin tran
create table #example (CourseId int, StudentId int)
insert into #example values (1,1), (1,2), (2,1)
declare @OldValue int, @NewValue int
set @OldValue = 1
set @NewValue = 2
-- Only update records which won't cause a conflict
update e
set CourseId = @NewValue
from #example e
left join #example e2
on (e.StudentId = e2.StudentId and e2.CourseId = @NewValue)
where e.CourseId = @OldValue
and e2.StudentId IS NULL
-- Delete the records which weren't updated
delete from #example
where CourseId = @OldValue
select * from #example
rollback
答案 1 :(得分:1)
运行UPDATE语句:
UPDATE YOUR_TABLE
SET courseid = 2
WHERE courseid = 1
删除重复项 - 此解决方案假定SQL Server 2005 +:
WITH duplicates AS (
SELECT t.courseid,
t.studentid,
ROW_NUMBER() OVER(PARTITION BY t.courseid, t.studentid) AS rank
FROM YOUR_TABLE t)
DELETE FROM duplicates
WHERE rank >= 2
启用/重新创建主键
答案 2 :(得分:0)
最好的答案实际上取决于你的桌子和一切的目的。
如果你提到的更新是一件看似合理的事情,我建议将IDENTITY主键与这两者分开,然后删除它们的约束力。
答案 3 :(得分:0)
我正在和Ryan相提并论。你的问题意味着设计不佳(或理解力差)。 这并不意味着你是傻瓜!
您的PK
,复合或其他,应该是可以唯一标识单个对象的最小列数(即数据片段)。将IsActive
或RegisteredDate
这样的列添加到PK
可能会减轻您“需要”更新ID
列的任何条件。
另外,因为我已经完成了大量的数据设计,所以我可以推断出这两个 ID 列构成了PK
,这是一个“关系表” “两者都是另一张桌子的外键。
我的建议是不要更改ID。