【问题标题】:Update query using Subquery in Sql Server在 Sql Server 中使用子查询更新查询
【发布时间】:2013-01-15 03:16:33
【问题描述】:

我有一个像这样的简单表格结构:

tempData

╔══════════╦═══════╗
║   NAME   ║ MARKS ║
╠══════════╬═══════╣
║ Narendra ║    80 ║
║ Ravi     ║    85 ║
║ Sanjay   ║    90 ║
╚══════════╩═══════╝

而且我还有另一个表名 tempDataView 像这样

╔══════════╦═══════╗
║   NAME   ║ MARKS ║
╠══════════╬═══════╣
║ Narendra ║       ║
║ Narendra ║       ║
║ Narendra ║       ║
║ Narendra ║       ║
║ Ravi     ║       ║
║ Ravi     ║       ║
║ Sanjay   ║       ║
╚══════════╩═══════╝

我想更新表格 tempDataView ,通过根据 tempDataView - Name 比较设置 Marks使用 tempData - 名称

是的,让我向您展示我的尝试,我尝试使用光标解决这个问题,并且完美解决,但我正在寻找使用 子查询

解决它的方法

这里是:

Declare @name varchar(50),@marks varchar(50)
Declare @cursorInsert CURSOR
set @cursorInsert = CURSOR FOR
Select name,marks from tempData
OPEN @cursorInsert
FETCH NEXT FROM @cursorInsert
into @name,@marks
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE tempDataView set marks = @marks where name = @name
FETCH NEXT FROM @cursorInsert
INTO @name,@marks
END
CLOSE @cursorInsert
DEALLOCATE @cursorInsert

实际上,使用子查询解决它就像我的作业一样。

【问题讨论】:

    标签: sql sql-server tsql sql-update


    【解决方案1】:

    您甚至可以在 UPDATE 语句中加入这两个表,

    UPDATE  a
    SET     a.marks = b.marks
    FROM    tempDataView a
            INNER JOIN tempData b
                ON a.Name = b.Name
    

    为了获得更快的性能,请在两个表的 marks 列上定义一个 INDEX

    使用SUBQUERY

    UPDATE  tempDataView 
    SET     marks = 
            (
              SELECT marks 
              FROM tempData b 
              WHERE tempDataView.Name = b.Name
            )
    

    【讨论】:

    • 它是对的。但请建议我使用子查询来执行此操作。
    • subquery 更新了答案,但我宁愿使用JOIN 而不是SUBQUERY
    • 为什么要在marks 列上定义INDEX?它不应该在Name 列上吗?
    • 遇到错误:子查询返回的值超过 1 个。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。
    • 自行尝试子查询并调整它,直到只得到 1 个结果。大概把SELECT改成SELECT TOP 1
    【解决方案2】:

    因为您只是在学习,我建议您练习将 SELECT 连接转换为 UPDATE 或 DELETE 连接。首先,我建议您生成一个连接这两个表的 SELECT 语句:

    SELECT *
    FROM    tempDataView a
            INNER JOIN tempData b
                ON a.Name = b.Name
    

    然后请注意,我们有两个表别名 ab。使用这些别名,您可以轻松地生成 UPDATE 语句来更新表 a 或 b。对于表 a,您有 JW 提供的答案。如果要更新b,则声明为:

    UPDATE  b
    SET     b.marks = a.marks
    FROM    tempDataView a
            INNER JOIN tempData b
                ON a.Name = b.Name
    

    现在,要将语句转换为 DELETE 语句,请使用相同的方法。下面的语句将只从a 中删除那些名称匹配的记录(保持 b 不变):

    DELETE a
    FROM    tempDataView a
            INNER JOIN tempData b
                ON a.Name = b.Name
    

    您可以将 JW 创建的 SQL Fiddle 用作游乐场

    【讨论】:

    • 正确的学习方式。 +1 展示学习方式。谢谢
    【解决方案3】:

    该主题的标题询问如何在更新中使用子查询。这是一个例子:

    update [dbName].[dbo].[MyTable] 
    set MyColumn = 1 
    where 
        (
            select count(*) 
            from [dbName].[dbo].[MyTable] mt2 
            where
                mt2.ID > [dbName].[dbo].[MyTable].ID
                and mt2.Category = [dbName].[dbo].[MyTable].Category
        ) > 0
    

    【讨论】:

    • 我不确定这将如何编译,count(*) 没有 group by 知道要计算什么。
    • @paqogomez 试一试 - 在任何包含任何记录的表上。例如。 从 EventLog 中选择 count(*),其中年份 = 2018
    • 那么你只是在计算整个表。我支持我的反对票,这与问题无关(无论标题如何)
    • 那是你的特权,但这个线程的标题是“使用子查询更新查询”,我的例子不言而喻就是这样做的。仅供参考,我不计算“整个表” - count(*) 后跟一个“where”子句 - 所以它计算满足“where”条件的行。
    【解决方案4】:

    Here 通过一些示例很好地解释了更新操作。虽然它是 Postgres 站点,但 SQL 查询对其他数据库也有效。 以下示例直观易懂。

    -- Update contact names in an accounts table to match the currently assigned salesmen:
    
    UPDATE accounts SET (contact_first_name, contact_last_name) =
        (SELECT first_name, last_name FROM salesmen
         WHERE salesmen.id = accounts.sales_id);
    
    -- A similar result could be accomplished with a join:
    
    UPDATE accounts SET contact_first_name = first_name,
                        contact_last_name = last_name
      FROM salesmen WHERE salesmen.id = accounts.sales_id;
    

    但是,如果 salesmen.id 不是唯一键,则第二个查询可能会产生意外结果,而如果有多个 id 匹配,则第一个查询肯定会引发错误。此外,如果没有匹配特定的 accounts.sales_id 条目,第一个查询会将相应的名称字段设置为 NULL,而第二个查询根本不会更新该行。

    因此,对于给定的示例,最可靠的查询如下所示。

    UPDATE tempDataView SET (marks) =
        (SELECT marks FROM tempData
         WHERE tempDataView.Name = tempData.Name);
    

    【讨论】:

    • 很遗憾,第一种形式在 MS SQL 服务器中不起作用。
    【解决方案5】:

    在我的示例中,我找到了解决方案,因为我在更新和子查询方面遇到了同样的问题:

    UPDATE
        A
    SET
        A.ValueToChange = B.NewValue
    FROM
        (
            Select * From C
        ) B
    Where 
        A.Id = B.Id
    

    【讨论】:

    • 感谢您的回答!为了帮助其他人阅读本文,您能否快速添加解释为什么此代码可以解决问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 2012-04-17
    • 1970-01-01
    相关资源
    最近更新 更多