Sql 检查update语句中的唯一性

Sql 检查update语句中的唯一性,sql,sql-server,Sql,Sql Server,我有一个表格将一个班级与该班级的学生联系起来: create table class_student (class_id int, student_id int, constraint class_student_u unique nonclustered (class_id, student_id)) 如果我想将所有课程从一个学生转到另一个学生(从他/她注册的所有课程中删除一个学生,并将另一个学生添加到老学生注册的每个课程),我使用以下查询: update cla

我有一个表格将一个班级与该班级的学生联系起来:

create table class_student
    (class_id int,
     student_id int,
     constraint class_student_u unique nonclustered (class_id, student_id))
如果我想将所有课程从一个学生转到另一个学生(从他/她注册的所有课程中删除一个学生,并将另一个学生添加到老学生注册的每个课程),我使用以下查询:

update class_student
set student_id = @newStudent
where student_id = @oldStudent
and class_id not in (select class_id
                     from class_student
                     where student_id = @newStudent)

delete from class_student
where student_id = @oldStudent
update class_student
set student_id = 3
where student_id = 1
and class_id not in (select class_id
                     from class_student
                     where student_id = 3)

delete from class_student
where student_id = 1
如何将课程从一个以上的学生转移到新学生?我不能把
放在student\u id所在的位置(@oldStudent1,@oldStudent2)
,因为如果两个老学生都在同一个类中,在运行上述查询后,将违反唯一约束。此外,如果可能的话,我希望在尽可能少的查询中进行更新(我可以只运行上面的查询两次,但我希望用更少的查询)

我正在使用SQLServer2008R2

编辑:为了澄清,这里有一个例子:

class_id student_id
===================
1        1
1        2
2        3
3        1
3        3
4        2
4        3
这意味着学生1在1班和3班,学生2在1班和4班,学生3在2班、3班和4班。如果我想将所有课程从学生1转移到学生3,我将运行以下查询:

update class_student
set student_id = @newStudent
where student_id = @oldStudent
and class_id not in (select class_id
                     from class_student
                     where student_id = @newStudent)

delete from class_student
where student_id = @oldStudent
update class_student
set student_id = 3
where student_id = 1
and class_id not in (select class_id
                     from class_student
                     where student_id = 3)

delete from class_student
where student_id = 1
我们的数据如下所示:

class_id student_id
===================
1        3
1        2
2        3
3        3
4        2
4        3
class_id student_id
===================
1        3
1        3
2        3
3        3
4        3
相反,如果我运行了此查询:

update class_student
set student_id = 3
where student_id in (1, 2)
and class_id not in (select class_id
                     from class_student
                     where student_id = 3)

delete from class_student
where student_id in (1, 2)
忽略表上的唯一约束,数据如下所示:

class_id student_id
===================
1        3
1        2
2        3
3        3
4        2
4        3
class_id student_id
===================
1        3
1        3
2        3
3        3
4        3

double(1,3)记录是我试图避免的,因为它将导致表中唯一的约束冲突。

我认为您至少需要2条DML语句来实现目标。如果您真的需要一次性完成,那么您可以将语句包装到存储过程中

insert into class_student (class_id, student_id)
select distinct class_id, @newStudent
from class_student
where student_id in (@oldStudent1, @oldStudent2)
and class_id not in (select class_id
                 from class_student
                 where student_id = @newStudent);

delete from class_student
where student_id in (@oldStudent1, @oldStudent2);

编辑:固定插入以包含“不在”子句。

设置原始表时,应始终包含一个唯一的行id,用于引用任何特定行(请参见下面名为“行id”的“标识”列):

如果学生1和2要离开,而你正在通过他们给学生3上的任何课程(除非学生3已经在上这些课程),则代码可以 看起来像这样:

WITH CTE
AS
(
SELECT row_Id,class_id,student_id,RN = ROW_NUMBER()OVER(PARTITION BY
class_id ORDER BY class_id) FROM class_student WHERE student_id in (1,2,3)
)
DELETE FROM class_student where class_id in (select class_id from
class_student  group by class_id having count(class_id) > 1) and student_id
<> 3 and row_id not in (select row_id from cte where student_id <> 3 and
rn >= 2)
Update class_student set student_id = 3
因为类_id 1、3和4是重复的,所以它们在RN(行号)列中的值为2

我在CTE中使用这个结果来删除class_student表中不需要的行,这就是始终具有唯一行id的重要性所在

Delete查询删除class_student表中类ID重复的行。如果一个班级同时有三名学生和一名或两名其他学生参加,则 获取学生ID不是3的行(因为学生3没有离开)

为了成功地完成这项工作(不需要将我们希望保留的行分配给学生3),它需要(通过比较行id)RN=2的行(即类id重复) 而student_id不是3,因此我们保留了student 1和student 2都在做但student 3没有做的课程的一行(即student_id都不是3)

最后,将表中所有剩余的行更新为student_id为3,以便student 3获得所有课程

要查看结果,您可以运行:

select * from class_student