【发布时间】:2019-01-04 12:15:35
【问题描述】:
我想使用merge,但被来自reference 的关于ON 连接条件的警告吓倒了:
重要的是只指定目标表中的列 用于匹配目的。也就是说,从 与相应列进行比较的目标表 源表。不要试图通过过滤来提高查询性能 在 ON 子句中取出目标表中的行,例如通过指定 AND NOT target_table.column_x = 值。这样做可能会意外返回 和错误的结果。
这是一个例子:
-- drop table trg
create table trg(department int not null,student int not null,name nvarchar(20))
alter table trg add constraint PK_trg primary key clustered (department,student)
insert trg values (12,0,'Tony'),(12,1,'Helen'),(55,0,'Tony'),(55,1,'Helen')
-- drop table src
go
create table src(student int not null,name nvarchar(20))
go
alter table src add constraint PK_src primary key clustered (student)
go
insert src values (0,'Antony'),(1,'Helen'),(2,'Mike')
select * from trg
select * from src
trg 表
+------------+---------+-------+
| department | student | name |
+------------+---------+-------+
| 12 | 0 | Tony |
| 12 | 1 | Helen |
| 55 | 0 | Tony |
| 55 | 1 | Helen |
+------------+---------+-------+
两个部门有2个学生(请忽略2nf违规,第三列也应该依赖于部门,但我现在想不出例子)。
现在,我们得到了一个src 表,该表仅有关于部门 12 的信息:
+---------+--------+
| student | name |
+---------+--------+
| 0 | Antony |
| 1 | Helen |
| 2 | Mike |
+---------+--------+
...我们想在src 中用merge 插入此信息。
使用这个:
merge trg using src on trg.student=src.student and trg.department=12
when matched then update set name=src.name
when not matched by target then insert values (12,src.student,src.name)
;
做我们想要的。 trg 表现在具有所需的输出:
+------------+---------+--------+
| department | student | name |
+------------+---------+--------+
| 12 | 0 | Antony |
| 12 | 1 | Helen |
| 12 | 2 | Mike |
| 55 | 0 | Tony |
| 55 | 1 | Helen |
+------------+---------+--------+
我们可以看到,12 部门 Tony 已将名称更改为 Antony,Mike 被插入到部门 12,没有其他任何事情发生。这是由违反参考警告造成的。可以吗?
我想它可以重写为:
merge trg using src on trg.student=src.student
when matched and trg.department=12 then update set name=src.name
when not matched by target then insert values (12,src.student,src.name);
这确实也可以正常工作。
第一种与警告相矛盾的方法是错误的,还是不好的做法?为什么?
【问题讨论】:
-
您好,请问...安东尼、海伦和迈克是 12 系的新生吗?如果是这样,则问题不是参考,因为您的关系是“学生”列,即...学生 0 = Tony -> Mike, Student 1 = Helen -> Helen, 2 = NULL -> Mike (new row ),因此,在组合条件中也将包括名称...问候
标签: sql-server tsql merge