我一直在测试根据案例结果设置多个列的更新。在所有类似的帖子和例子中,我发现下面的代码应该有效。代码运行后,我希望id 1同时具有f1和f2 ='Y',但只有f1 ='Y'。
我的语法在这里是错误的还是在满足任何条件后停止的情况?任何帮助将不胜感激。
create table test.dbo.testa<br>
(
id int,
f1 char,
f2 char,
f3 char
)
insert into test.dbo.testa (id)
select 1 union all
select 2 union all
select 3
create table test.dbo.testb
(
id int,
f1 varchar(2)
)
insert into test.dbo.testb (id, f1)
select 1, 'f1' union all
select 1, 'f2' union all
select 2, 'f1' union all
select 2, 'f2'
update x
set x.f1 = case when y.f1 = 'f1' then 'Y' else x.f1 end,
x.f2 = case when y.f1 = 'f2' then 'Y' else x.f2 end
from test.dbo.testa x
inner join test.dbo.testb y
on x.id = y.id
答案 0 :(得分:0)
代码上的内部处理逻辑将如下所示:
如果连接的结果在“目标”表中每行产生不超过一行,则此方法正常工作。但是,这里为两个目标表的行生成了两行:
select *
from testa x
inner join testb y
on x.id = y.id
产生
id f1 f2 f3 id f1
1 NULL NULL NULL 1 f1
1 NULL NULL NULL 1 f2
2 NULL NULL NULL 2 f1
2 NULL NULL NULL 2 f2
似乎SQL只考虑每个“目标”行的“第一个”结果行,并根据它执行更新(并注意“第一个”这样的行是相当任意选择的。)
答案 1 :(得分:0)
我的语法在这里是错误的,或者是在任何情况下停止的情况 条件满意吗?
你的语法没有错。问题是如何编写UPDATE ... FROM ...
语句。对于此类UPDATE
语句,重要的是要知道目标表dbo.TestA x
中的每一行在源表dbo.TestB y
中不应超过一行。为此,我们必须查看连接谓词:ON x.id = y.id
。但似乎不是你的情况,因为dbo.TestA
中的每一行dbo.TesteB
都有两行(例如:x.id 1
- &gt;&gt; y.id:{{ 1}},1 - f1
和x.id 1 - f2
- &gt;&gt; y.id:2
,2 - f1
)。在这种情况下,SQL Server将为来自源表2 - f2
的目标表dbo.TestA
中的每一行仅提取 。这就是原始dbo.TestB
语句具有以下结果的原因:
UPDATE
另外,如果更改源表id f1 f2 f3
--- ---- ---- ----
1 Y NULL NULL -- column f2 is not updated
2 Y NULL NULL -- column f2 is not updated
3 NULL NULL NULL
中的行顺序(例如)
dbo.TableB
您将获得不同的结果(使用相同的truncate table test.dbo.testb;
insert into test.dbo.testb (id, f1)
select 1, 'f1' union all
select 1, 'f2' union all
select 2, 'f2' union all
select 2, 'f1'
语句):
UPDATE
应该避免这些情况,因为正如您所看到的,id f1 f2 f3
-- ---- ---- ----
1 Y NULL NULL
2 Y Y NULL <- different results
3 NULL NULL NULL
语句的结果是不可预测的。
非常感谢任何帮助。
UPDATE
或
UPDATE x
SET x.f1 = y.colf1,
x.f2 = y.colf2
FROM dbo.TestA x
INNER JOIN
(
SELECT b.id,
MAX(CASE WHEN b.f1 = 'f1' THEN b.f1 END) AS colf1,
MAX(CASE WHEN b.f1 = 'f2' THEN b.f1 END) AS colf2
FROM dbo.TestB b
GROUP BY b.id
) AS y ON x.id = y.id;
对于最后一个示例,UPDATE x
SET x.f1 = y.f1,
x.f2 = y.f2
FROM dbo.TestA x
INNER JOIN
(
SELECT pvt.*
FROM (
SELECT b.id, b.f1 as value
FROM dbo.TestB b
) src
PIVOT( MAX(src.value) FOR src.value IN([f1], [f2]) ) pvt
) AS y ON x.id = y.id;
派生表
(...) y
生成以下结果:
SELECT pvt.*
FROM (
SELECT b.id, b.f1 as value
FROM dbo.TestB b
) src
PIVOT( MAX(src.value) FOR src.value IN([f1], [f2]) ) pvt
注意:您还应该为dbo.TestA f1,f2和f3列定义最大长度:
id f1 f2
-- ---- ----
1 f1 f2
2 f1 f2