我想使用merge
,并且受到reference关于ON
加入条件的警告的威胁:
仅指定目标表中的列是很重要的 用于匹配目的。也就是说,从 目标表,将其与 源表。不要尝试通过过滤来提高查询性能 在ON子句中淘汰目标表中的行,例如通过指定 并且不是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的信息 only :
+---------+--------+
| 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,第12部门插入了Mike,其他都没有发生。这是通过违反参考警告而做出的。可以吗?
我想它可以改写为:
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);
这确实也可以正常工作。
是与警告错误相抵触的第一种方法,或者是不良做法?为什么?
答案 0 :(得分:3)
发出警告的原因是,如果源表中包含类似55,0,Tony
的内容,则将其视为不匹配内容,并转到INSERT
分支,这可能是意外的。
但是,如果保证您的源表只包含部门12的项目,那么它将按您希望的那样工作。
在这种情况下,您还可以使用表表达式,例如CTE
WITH trg12
AS (SELECT *
FROM trg
WHERE department = 12)
MERGE trg12 trg
using src
ON trg.student = src.student
WHEN matched THEN
UPDATE SET name = src.name
WHEN NOT matched BY target THEN
INSERT
VALUES (12,
src.student,
src.name);
;