sql帮助与关联表更新

时间:2010-10-28 00:16:36

标签: sql sql-server tsql

  

更新:这是一个比正常情况更多的维护问题。

我有下表:

CourseId   StudentId
---------------------
1          1
1          2
2          1

CourseIdStudentId复合主键。

假设我想因为某种原因将courseid = 1更新到courseid = 2。这将导致主键约束问题。

有什么不同的方法可以解决这个问题?

4 个答案:

答案 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)

  1. 禁用/删除主键约束
  2. 运行UPDATE语句:

    UPDATE YOUR_TABLE
       SET courseid = 2
     WHERE courseid = 1
    
  3. 删除重复项 - 此解决方案假定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
    
  4. 启用/重新创建主键

答案 2 :(得分:0)

最好的答案实际上取决于你的桌子和一切的目的。

如果你提到的更新是一件看似合理的事情,我建议将IDENTITY主键与这两者分开,然后删除它们的约束力。

答案 3 :(得分:0)

我正在和Ryan相提并论。你的问题意味着设计不佳(或理解力差)。 这并不意味着你是傻瓜!

您的PK,复合或其他,应该是可以唯一标识单个对象的最小列数(即数据片段)。将IsActiveRegisteredDate这样的列添加到PK可能会减轻您“需要”更新ID列的任何条件。

另外,因为我已经完成了大量的数据设计,所以我可以推断出这两个 ID 列构成了PK,这是一个“关系表” “两者都是另一张桌子的外键。

我的建议是不要更改ID。