update语句使用大小写设置多个列

时间:2014-02-04 20:28:33

标签: sql-server sql-server-2008

我一直在测试根据案例结果设置多个列的更新。在所有类似的帖子和例子中,我发现下面的代码应该有效。代码运行后,我希望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

2 个答案:

答案 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:22 - 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