带连接的SQL Update

时间:2012-03-23 17:11:48

标签: sql sql-server tsql join sql-update

除了加入之外,还有其他更快捷的方法来进行更新吗?这是我的查询,但它有点慢:

UPDATE @user_dupes
  SET ExternalEmail = ud2.Email
 FROM @user_dupes ud1
INNER JOIN(
SELECT Email, UserName 
  FROM @user_flat_emailtable_dupes
 WHERE EmailType = 2
   AND Email IS NOT NULL AND LEN(Email) > 0
) ud2
ON ud1.UserName = ud2.UserName

感谢您的任何想法

3 个答案:

答案 0 :(得分:4)

如果您使用的是SQL Server,那么您几乎就在那里。这只是一个小问题:

UPDATE ud1 --little fix here!
  SET ExternalEmail = ud2.Email
 FROM @user_dupes ud1
INNER JOIN
(
SELECT Email, UserName 
  FROM @user_flat_emailtable_dupes
 WHERE EmailType = 2
   AND Email IS NOT NULL AND LEN(Email) > 0
) ud2
ON ud1.UserName = ud2.UserName

答案 1 :(得分:4)

在@Adrian所说的基础上进行了一些改变......

UPDATE
  ud1   -- @Adrian's change.  Update the instance that you have already aliased.
SET
  externalEmail = ud2.Email
FROM
  @user_dupes                   AS ud1
INNER JOIN
  @user_flat_emailtable_dupes   AS ud2
    ON ud1.UserName = ud2.UserName
WHERE
      ud2.EmailType = 2      -- Removed sub-query, for layout, doubt it will help performance
  AND ud2.Email IS NOT NULL
  AND ud2.Email <> ''        -- Removed the `LEN()` function

但最重要的过去可能是确保你有索引。 JOIN对于此逻辑(或相关的子查询等)是必需的,因此您希望连接具有高效性。

@user_dupes上的(UserName)索引,以及@user_flat_emailtable_dupes上的(EmailType,Email,UserName)索引。 (假设ud2是过滤后的较小的表)

使用指定的索引,从LEN(Email) > 0Email <> ''的更改可能允许索引搜索而不是扫描。你的桌子越大,这就越明显。

答案 2 :(得分:1)

我相信这个查询会做同样的事情(尽管你必须确保形成没有重复用户名的@user_flat_emailtable_dupes)。我没有检查他们是否有不同的执行计划。看起来你正在提炼垃圾输入,我提到这部分是因为我做了很多,并且发现MERGE很有用(因为我不知道UPDATE FROM如何工作所以对我来说更有用)。部分是因为我从未使用MERGE和变量。似乎至少目标表必须是别名,或者解析器决定@ ud1是标量变量并且它会中断。

MERGE @user_dupes AS ud1
USING @user_flat_emailtable_dupes AS ud2
    ON emailType = 2 
   AND COALESCE(ud2.email, '') <> ''
   AND ud2.username = ud1.username
WHEN MATCHED THEN UPDATE
    SET externalEmail = ud2.email
    ;