SQL UPDATE从多行到单行

时间:2014-08-07 05:34:37

标签: sql sql-server sql-server-2008-r2

这说明了问题:

CREATE TABLE Table_A (id int, value char)
INSERT INTO Table_A VALUES (1, 'A')
INSERT INTO Table_A VALUES (2, 'B')
CREATE TABLE Table_B (id int, value char)
INSERT INTO Table_B VALUES (1, 'C')
INSERT INTO Table_B VALUES (1, 'D')

如果你跑

UPDATE a SET a.value = (SELECT b.value FROM Table_B b WHERE a.id = b.id)
FROM Table_A a, Table_B b WHERE a.id = b.id

您收到错误消息

  

子查询返回的值超过1。这是不允许的   子查询跟随=,!=,<,< =,>,> =或当子查询用作   表达。

但是如果你运行这个

UPDATE a SET a.value = b.value
FROM Table_A a, Table_B b WHERE a.id = b.id

没有抛出任何错误并且您更新了行,为什么会这样?


编辑:

对不起伙计们,你似乎专注于解释为什么第一个查询会出错,但我认为这很明显,对我来说这是一个渴望的结果(因为id为1的Table_A的值设置为具有id 1的Table_B的值是当Table_B中有多个值为id 1)

时,未定义

我的问题实际上是在问为什么第二个查询没有给你一个错误,这给我带来了麻烦(即如果我有多个具有相同id但不同值的行,我希望它会中断)

3 个答案:

答案 0 :(得分:2)

您收到该错误,因为您在设置新值时使用子查询并且子查询返回的结果超过1。

SET a.value = (SELECT b.value FROM Table_B b WHERE a.id = b.id)

更新id = 1的值时会出错,因为表b中有两条记录id = 1。

因此,您的查询将如下所示(这仅用于说明,当然会导致错误)

UPDATE a SET a.value = ('C', 'D') 
FROM Table_A a, Table_B b WHERE a.id = b.id

当您使用此查询时

UPDATE a SET a.value = b.value
FROM Table_A a, Table_B b WHERE a.id = b.id

您使用id字段加入表a和表b,结果是

a.id => a.value => b.value :1 A C

a.id => a.value => b.value :1 A D

没有id = 2的条目记录,因为表b中没有匹配的记录。

因此,您的更新查询将如下所示

UPDATE a SET a.value = 'C'
FROM Table_A a, Table_B b WHERE a.id = 1


UPDATE a SET a.value = 'D'
FROM Table_A a, Table_B b WHERE a.id = 1

答案 1 :(得分:1)

因为subquery会返回两个以上的结果。 Assign语句不接受超过1个值。

您必须使用JOIN

可能是这样的

UPDATE A
SET A.value = B.value
FROM Table_A A INNER JOIN Table_B  B ON A.id = B.id

<强> FIDDLE DEMO

答案 2 :(得分:0)

你的第二个查询没有错误的原因是因为它会将第一个可用的B.value分配给满足条件的a.value A.id = B.id

尝试以下代码段,您将看到Update ... Set的工作原理。

create table #temp (id int, name varchar(100), phone int)
create table #temp1 (id int, phone int)
insert into #temp (id, name)
select 1, 'Mark' union
select 2, 'JOhn' union
select 3, 'Jerry'

insert into #temp1 (id, phone)
select 1, 123456 union
select 1, 222564 union
select 1, 222210

select * from #temp
select * from #temp1

update t
set phone = t1.phone
from #temp1 t1, #temp t
where t.id = t1.id

select * from #temp