更新期间的Sql Server问题

时间:2017-06-09 13:17:31

标签: sql sql-server-2008 sql-server-2012

您好我有点困惑,看到执行查询时的SQL服务器行为。根据我的意见,产量应该是" Priyanka" ,4

Declare @temp table(
Name Varchar(50),
amount int
)

insert @temp values ('Priyanka' ,10 )

Update @temp
set amount=amount-A.a
from (
select  'Priyanka' as Name,1 as a 
union
select  'Priyanka' as Name,5 as a
)A
where [@temp].Name in (A.Name)

select * from @temp

但是 输出

Name    amount
Priyanka    9

任何人都可以告诉我为什么会这样。

2 个答案:

答案 0 :(得分:0)

标准SQL不支持带有from的{​​{1}}子句,而是必须将您对其他表的访问权限写为update子句中的直接子查询。如果你这样做,你会得到错误“子查询返回多个值”,并对问题有所了解。

不幸的是,Microsoft的SQL扩展允许set子句静默忽略了多行可能匹配的事实,使用其中一行并忽略其他行。 1

如果您要使用此扩展程序,则应由您仔细确保目标表中的单行没有多个匹配项。

我会重新排列您的查询,例如:

FROM

我使用Declare @temp table( Name Varchar(50), amount int ) insert @temp values ('Priyanka' ,10 ) ;With A as ( select 'Priyanka' as Name,1 as a union select 'Priyanka' as Name,5 as a ) Update t set amount=amount-Aa.a from @temp t cross apply (select SUM(a) as a from A where Name = t.Name) Aa select * from @temp 将数据汇总到每个目标行的单行。

1 但重要的是,它确实支持应用cross apply的效果“好像”所有行(及其中的列)并行更新的概念。因此,首先使用一行获取更新,然后第二次更新将更新已更新的行。

答案 1 :(得分:0)

您需要汇总联合条目的值。简单地UNION它有多个条目的条目,因此它可以接受任何一个条目并忽略遗骸。

对于您的情况,以下查询将起作用:

DECLARE @temp TABLE (NAME VARCHAR(50), amount INT)

INSERT @temp
VALUES ('Priyanka', 10)

UPDATE t
SET amount = t.amount - A.a
FROM @temp t
JOIN (
    SELECT NAME, SUM(a) AS a FROM (
        SELECT 'Priyanka' AS NAME, 1 AS a
        UNION
        SELECT 'Priyanka' AS NAME, 5 AS a
        ) c
    GROUP BY NAME
    ) A ON A.NAME = t.NAME

SELECT * FROM @temp