SQL Server 2008联接表中带有Join和Where子句的更新查询

5

不确定为什么这个不起作用:

UPDATE 
    ust
SET  
    ust.isUnsubscribedFromSystemEmails = 1
FROM         
    UserSetting AS ust 
INNER JOIN
    [User] ON ust.userID = [User].userID 
AND 
    [User].emailAddress IN (SELECT emailAddress FROM BadEmailAddresses)

以通俗易懂的方式来说,我想将UserSetting表中userID与用户表中的userID相同且用户表中的emailAddress不在另一个表格中的电子邮件列表中的字段isUnsubscribed设置为未订阅状态。我可以使用几乎相同的语法在isUnsubbed列上运行选择操作,它可以正常工作。谢谢!:我已经查看了此类问题的其他类似问题,语法似乎是相同的,但显然我错过了什么。

为什么它不工作?你有错误信息吗(如果有,是什么信息?)或者你没有得到预期的结果(如果是这样,那么得到的结果是什么?)? - remi bourgarel
很抱歉,这是个好问题!但它没有解析查询。 - toddm
误按了回车键。列或表达式“isUnsubscribedFromSystemEmails”无法更新。该列存在且可写。没有权限问题。然后我得到一些其他的东西,错误消息是:无效的对象名称“ust”。UserSetting表肯定存在!使用相同的连接和where子句进行选择会给出正确的结果。 - toddm
@toddm: "并且用户表中的emailAddress不在另一个表中的电子邮件列表中" - 你是指BadEmailAddresses,如果是这样,你是指“并且用户表中的emailAddressBadEmailAddresses的电子邮件列表中吗?” - user359040
仅就“isUnsubscribedFromSystemEmails”列名发表一下评论。除了有点长之外,我试图避免使用否定的名称。我更喜欢使用类似“SendSystemEmails”的名称。 - Andrew Carmichael
嗨 Paul,我发现在命名方面你永远不能够过于明确。为什么不把它命名得好看且有描述性呢?将实体命名为这样可以帮助开发者在不猜测的情况下理解属性的作用。至于负面的命名,我同意……尽管在这种情况下,如果他们取消订阅,则是消极的!;') - toddm
5个回答

10

是的,你忽略了一些东西。

set语句不能引用设置左侧别名。

尝试:

UPDATE  
    ust 
SET   
    isUnsubscribedFromSystemEmails = 1 
--select *
FROM          
    UserSetting AS ust  
INNER JOIN 
    [User] ON ust.userID = [User].userID  
WHERE [User].emailAddress IN (SELECT emailAddress FROM BadEmailAddresses) 

我添加了被注释掉的 select 语句,这样你就可以检查是否获得了所需的结果集。


"无法解析查询文本",无效的对象名称为'ust'。 - toddm
选择 * 从 UserSetting AS ust
内部连接 [User] ON ust.userID = [User].userID

[User].emailAddress IN (SELECT emailAddress FROM BadEmailAddresses) 顺便说一句,这个语句可以正常工作并返回预期的结果吗?
- toddm
如果选择操作正常运作,我就不知道问题出在哪里了。为什么你不提供一些来自用户设置、用户和错误电子邮件地址的样本数据,这样我们就可以根据你所期望的数据进行测试。 - HLGEM
我在我的机器上尝试了我给你的内容,它解析并运行正常。你确定你使用的是我提供的完全一样的内容吗?(我将最后一个 "and" 改成了 "where",但从功能上来说两者是一样的,两个版本都可以工作,只是我更喜欢仅使用 join 所需的部分)。关键是将 ust.isUnsubscribedFromSystemEmails = 1 改为 isUnsubscribedFromSystemEmails = 1。 - HLGEM

2

虽然在某些情况下,UPDATE...FROM语法是必不可少的,但我更喜欢在可能的情况下使用子查询。这样做是否符合您的需要?

UPDATE UserSetting
SET isUnsubscribedFromSystemEmails = 1
WHERE userID in (SELECT userID from [User]
                WHERE emailAddress in (SELECT emailAddress FROM BadEmailAddresses))

这个有效。谢谢!虽然此后集合被更新了两次,但我现在并不在意。谢谢! - toddm

0

试试这个:

UPDATE UserSetting ust SET usr.isUnsubscribedFromSystemEmails = 1
WHERE ust.emailAdress IN (select emailAddress from bademailAddresses);

我尝试过这个..首先isUnsubbed列在ust表中..即使有了这个更改,查询仍无法解析。 - toddm

0

尝试:

UPDATE  
    UserSetting
SET   
    isUnsubscribedFromSystemEmails = 1 
FROM          
    UserSetting 
INNER JOIN 
    [User] ON UserSetting.userID = [User].userID  
AND  
    [User].emailAddress IN (SELECT emailAddress FROM BadEmailAddresses)

这将把UserSetting.isUnsubscribedFromSystemEmails中的每条记录设置为true。 - toddm
那么每个用户的电子邮件都是错误的吗? - HLGEM

0
注意:仅供记录(假设您已使其他所有内容正常工作),您还可以在BadEmailAddresses表上执行内部连接。
如果您遇到任何性能问题,则可能希望在两个表中的emailAddress列上建立索引。

2
实际上,当子查询像问题中的那样简洁时,INNER JOIN 的性能比子查询差。更合适的扩展是将 [User] 转换为一个视图,在 WHERE 子句中运行子查询。 - Mike Perrenoud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接