SQL Server - 基于SELECT的UPDATE数据

时间:2017-02-15 12:16:37

标签: sql sql-server

我写了以下内容,它返回了一个只有一个房间的建筑物清单,但该房间的面积(fma0.area)不等于建筑物的面积(fmb0.nia)

select 
rtrim(fma0.bldgcode) As bldgcode
from fma0 
left join fmb0 on fma0.bldgcode = fmb0.bldgcode
where fma0.bldgcode in (
    select fma0.bldgcode
    from fma0 
    left join fmb0 on fma0.bldgcode = fmb0.bldgcode
    where fmb0.bldgstatus = ''
    group by fma0.bldgcode
    having count(fma0.auto_key) = 1
)
and round(fma0.area,0) <> fmb0.nia
and fmb0.nia > 0
order by 1

我需要使用这个建筑物列表来为每个BLDGCODE更新FMA0表(FMA0.GROSS,FMA0.AREA,FMA0.RENTABLE)中的几个字段,并为同一个BLDGCODE提供FMB0.NIA的值

如何将此转换为UPDATE语句,该语句查找每个BLDGCODE的FMB0.NIA值,并更新FMA0表中相同BLDGCODE的每个字段中的值

由于

2 个答案:

答案 0 :(得分:2)

这似乎是一种更简单的方式来获得你想要的建筑物:

select b.bldcode
from fmbo b join
     (select r.bldgcode, max(r.area) as room_area
      from fma0 r
      group by r.bldgcode
      having count(*) = 1
     ) r 
     on r.bldgcode = b.bldgcode and r.room_area <> b.nia;

第一个子查询获得只有一个房间的建筑物中的房间区域。 join然后根据您的规则简单地组合它们。

这很容易变成更新:

update b
    set . . .
    from fmbo b join
         (select r.bldgcode, max(r.area) as room_area
          from fma0 r
          group by r.bldgcode
          having count(*) = 1
         ) r 
         on r.bldgcode = b.bldgcode and r.room_area <> b.nia;

答案 1 :(得分:1)

在大多数情况下,使用对特定表(UPDATE books SET books.title = 'The Hobbit' WHERE books.id = 1)的直接引用执行SQL更新。然而,有时候,通过使用从二级查询语句中获得的数据子集来间接地改变表的内容可能是有益的。

使用辅助SELECT语句执行UPDATE可以通过两种方式之一完成,主要取决于您使用的SQL Server版本。我们将简要探讨这两个选项,以便找到最适合您的选项。

使用INNER JOINS

对于所有SQL Server安装,执行此操作的最基本方法是使用INNER JOIN,从而将两个不同表的列中的值相互比较。

UPDATE
  books
SET
  books.primary_author = authors.name
FROM
  books
INNER JOIN
  authors
ON
  books.author_id = authors.id
WHERE
  books.title = 'The Hobbit'

在上面的示例中,我们通过将查询中的两个表连接到authors.id和books.author_id各自的匹配值,更新books.primary_author字段以匹配“The Hobbit”的authors.name。

使用MERGE同时更新和插入

对于SQL Server 2008及更高版本,Microsoft引入了非常有用的MERGE操作,类似于上面的INNER JOIN方法,但MERGE尝试同时执行UPDATE和INSERT命令。这有效地根据执行的查询同步两个表,根据需要更新和插入记录以匹配。

MERGE INTO
  books
USING
  authors
ON
  books.author_id = authors.id
WHEN MATCHED THEN
  UPDATE SET
    books.primary_author = authors.name
WHEN NOT MATCHED THEN
  INSERT
    (books.author_id, books.primary_author)
  VALUES
    (authors.id, authors.name)

使用MERGE时的完整查询肯定比基本的INNER JOIN更复杂,但是一旦掌握了操作的功能,您就会很快理解这种功能的真正强大程度。

前几行是不言自明的:

MERGE INTO
  books
USING
  authors
ON
  books.author_id = authors.id

我们希望通过使用辅助作者表来合并(更新/插入)书籍表,并且我们基于相同的书籍匹配这两本书.author_id = authors.id比较。

MERGE命令的不同之处在于后面的分支逻辑。

WHEN MATCHED THEN
  UPDATE SET
    books.primary_author = authors.name

这里我们要求SQL仅在记录匹配时执行操作 - 当找到现有记录时。在这种情况下,我们像以前一样执行标准UPDATE,将books.primary_author字段设置为等于authors.name字段。

最后,如果查询发现不存在的匹配比较记录,我们改为执行INSERT。

WHEN NOT MATCHED THEN
  INSERT
    (books.author_id, books.primary_author)
  VALUES
    (authors.id, authors.name)

这里我们只是要求SQL将新记录插入books表并传递author_id和primary_author字段的值,从相关的authors表记录中抓取。

我们的MERGE声明的最终结果是,对于authors表中的每个作者,我们都会验证书中是否存在相应的书。如果找到记录,我们确保使用UPDATE设置books.primary_author,如果找不到匹配项,我们会在书籍中添加新记录。

有了这个,您应该对使用辅助,比较SELECT语句在SQL中更新记录的两种不同方法有充分的了解。