Hsu*_*Fai 5 sql sql-server-2012
我有两个数据键,pk应该是在插入行时从数据库生成的,而fk是由另一个系统给出的复杂键。我想为每个fk密钥生成一个pk密钥。
CREATE TABLE test_target (
[pk] [INT] IDENTITY(1,1),
[fk] [varchar](20) NOT NULL)
Run Code Online (Sandbox Code Playgroud)
我可以使用 merge 来确保每当表中不存在相应的fk时都会生成新的pk ,并且我知道我可以输出新创建的 ids。
CREATE TABLE test_source (
[fk] [varchar](20) NOT NULL)
INSERT INTO test_source VALUES('abc123'),('def456'),('ghi789')
MERGE test_target WITH (SERIALIZABLE) AS T
USING test_source AS U
ON U.fk = T.fk
WHEN NOT MATCHED THEN
INSERT (fk) VALUES(U.fk)
OUTPUT inserted.pk, inserted.fk;
Run Code Online (Sandbox Code Playgroud)
然而,我真正想要的是test_source 表中与fk 关联的所有pk。所以我可以通过连接两个表来获得所有内容。
SELECT test_target.* FROM test_target
INNER JOIN test_source ON test_target.fk = test_source.fk
Run Code Online (Sandbox Code Playgroud)
但我觉得在合并语句中 MATCHED 的情况下已经找到了关联pk ,因此在目标表上进行另一次搜索是重复的工作。我的问题是有没有办法在同一个合并语句中输出 MATCHED pk ?
是的,一开始我以为我必须触摸该行并以某种形式更新它,但我意识到我们可以欺骗它。输出子句将输出语句触及的任何行,而不仅仅是未匹配的行,因此您可以包含一个匹配子句 - 问题是使其成为空操作。
create table foo
(
id int
,bar varchar(30)
)
insert into foo (id, bar) values (1,'test1');
insert into foo (id, bar) values (2,'test2');
insert into foo (id, bar) values (3,'test3');
declare @temp int;
merge foo as dest
using
(
values (2, 'an updated value')
, (4, 'a new value')
) as src(id, bar) on (dest.id = src.id)
when matched then
update set @temp=1
when not matched then
insert (id,bar)
values (src.id, src.bar)
output $action, src.id;
Run Code Online (Sandbox Code Playgroud)
您可以在when matches 子句中看到,我将声明的变量设置为1。这很奇怪,需要考虑让输出子句将其拾取以进行输出。如果需要,您可以使用输出中的 $action 来区分发生了哪个操作(插入与更新)。
这给出了以下结果:
$action id
UPDATE 2
INSERT 4
Run Code Online (Sandbox Code Playgroud)
性能方面我想测试如何大规模操作,或者变量分配是否会导致节流效果
| 归档时间: |
|
| 查看次数: |
3679 次 |
| 最近记录: |