在Sql Server中使用子查询更新查询
我有这样一个简单的表结构: 表tempData在Sql Server中使用子查询更新查询,sql,sql-server,tsql,sql-update,Sql,Sql Server,Tsql,Sql Update,我有这样一个简单的表结构: 表tempData ╔══════════╦═══════╗ ║ NAME ║ MARKS ║ ╠══════════╬═══════╣ ║ Narendra ║ 80 ║ ║ Ravi ║ 85 ║ ║ Sanjay ║ 90 ║ ╚══════════╩═══════╝ 我还有另一个表名为tempDataView,如下所示 ╔══════════╦═══════╗ ║ NAME ║ MARKS ║ ╠════════
╔══════════╦═══════╗
║ NAME ║ MARKS ║
╠══════════╬═══════╣
║ Narendra ║ 80 ║
║ Ravi ║ 85 ║
║ Sanjay ║ 90 ║
╚══════════╩═══════╝
我还有另一个表名为tempDataView,如下所示
╔══════════╦═══════╗
║ NAME ║ MARKS ║
╠══════════╬═══════╣
║ Narendra ║ ║
║ Narendra ║ ║
║ Narendra ║ ║
║ Narendra ║ ║
║ Ravi ║ ║
║ Ravi ║ ║
║ Sanjay ║ ║
╚══════════╩═══════╝
我想更新表tempDataView,方法是根据tempDataView-Name与tempData-Name相比设置标记
是的,让我向您展示我尝试过的,我尝试使用光标来解决这个问题,它的解决非常完美,但我正在找到使用子查询来解决它的方法
这是:
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
实际上,使用子查询解决它就像我的家庭作业一样 即使在
UPDATE
语句中,您也可以联接这两个表
UPDATE a
SET a.marks = b.marks
FROM tempDataView a
INNER JOIN tempData b
ON a.Name = b.Name
标记上定义索引
使用子查询
UPDATE tempDataView
SET marks =
(
SELECT marks
FROM tempData b
WHERE tempDataView.Name = b.Name
)
因为您刚刚学习,我建议您练习将选择连接转换为更新或删除连接。首先,我建议您生成一个连接这两个表的SELECT语句:
SELECT *
FROM tempDataView a
INNER JOIN tempData b
ON a.Name = b.Name
然后请注意,我们有两个表别名a
和b
。使用这些别名,您可以轻松地生成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 FIDLE作为一个游戏此线程的标题询问如何在更新中使用子查询。下面是一个例子:
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
用一些例子很好地解释了更新操作。虽然它是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\u id条目不匹配,则第一个查询会将相应的名称字段设置为NULL,而第二个查询根本不会更新该行
因此,对于给定的示例,最可靠的查询如下所示
UPDATE tempDataView SET (marks) =
(SELECT marks FROM tempData
WHERE tempDataView.Name = tempData.Name);
在我的示例中,我找到了这个问题的解决方案,因为我在更新和子查询方面也遇到了同样的问题:
UPDATE
A
SET
A.ValueToChange = B.NewValue
FROM
(
Select * From C
) B
Where
A.Id = B.Id
是的。但是请建议我使用子查询的任何方法。用subquery
更新答案,但是我宁愿使用JOIN
而不是subquery
。为什么要在标记
列上定义索引
?它是否应该位于Name
列上?出现错误:子查询返回的值超过1。当子查询在=、!=、=或者当子查询用作表达式时。请单独尝试子查询并调整它,直到只得到1个结果。可能将SELECT
更改为selecttop1
这是正确的学习方法+1用于显示学习方法。谢谢我不确定这将如何编译,计数(*)没有分组依据来知道要计数什么。@paqogomez只需在任何有记录的表上尝试一下即可。e、 g。从EventLog中选择count(*),其中year=2018,这样您就可以简单地计算整个表。我支持我的反对票,这与您的特权问题(无论标题如何)无关,但此线程的标题是“使用子查询更新查询”,我的示例不言而喻地做到了这一点。仅供参考,我不是在计算“整个表”-count(*)后面跟着一个“where”子句-因此它是在计算满足“where”条件的行。不幸的是,第一个表单在MS SQL server中不起作用。谢谢您的回答!为了帮助其他人阅读本文,您是否可以快速添加一个解释,说明为什么此代码可以解决此问题?