在“where”子句中使用“in”运算符更新行
Posted
技术标签:
【中文标题】在“where”子句中使用“in”运算符更新行【英文标题】:Updating rows using "in" operator in "where" clause 【发布时间】:2010-04-19 19:13:11 【问题描述】:我偶然发现了我不理解的 SQL 行为。我需要一次更新表中的几行;从找到它们开始:
SELECT * FROM some_table WHERE field1 IN (SELECT ...)
这返回了大约 60 行的选择。现在我很有信心我得到了正确的子查询,所以我只修改了第一部分:
UPDATE some_table SET field2 = some_value WHERE field1 IN (SELECT ...)
换句话说,这与WHERE
之后的第一个查询完全相同。但是,它导致更新了 0 行,而我预计这 60 行。请注意,上面的语句会更改field2
,即我验证some_value
不存在于所选行中。
子查询是一个适度复杂的 SQL 片段,有 2 个(不同的)表、1 个视图、连接和它自己的 WHERE
子句。如果这很重要,Oracle 数据库 10g 就会发生这种情况。
那么,问题是,为什么UPDATE
没有触及SELECT
返回的行?
【问题讨论】:
原始查询是否仍返回约 60 行? 是的。数据库未以任何方式修改。 只是一个猜测 - 您能否为子查询中的所有表/视图以及更新表添加显式别名,看看这是否会改变您的更新结果? 不,抱歉,我不能。这是一个生产数据库,我不能像那样修改它的结构。 我认为 dpbradley 是在谈论修改您的 SQL 语句,而不是实际视图。对于 SQL 中的每个表/视图引用,为其提供一个别名并相应地限定 SQL 中的每个列名。 【参考方案1】:终于搞定了。原来,子查询选择中使用的视图间接(通过另一个视图)称为存储过程/函数。然后该过程访问UPDATE
中正在修改的表。结果,Oracle 抛出了“表some_table
正在修改,函数可能看不到结果”的异常(不记得确切的文本)。但是函数最后使用了when other then return null
,所以错误被有效地隐藏了,子查询根本没有返回任何东西——反过来UPDATE
没有任何效果。
道德:永远不要使用过于宽泛的异常捕获器。我在其他语言中遵循此规则,但显然不是在 PL/SQL 中:-/
【讨论】:
【参考方案2】:如果“some-table”实际上是一个视图,您可能遇到了一个问题,即系统无法计算出如何更新位于该视图下的表。
【讨论】:
不,some_table
是一张真实的桌子。然而,子查询确实包含一个视图。这有关系吗?
不,不应该相关。 “some_value”与子查询无关,是吗?此外,如果子查询结果包含空值,结果可能会变得不稳定。
some_value
实际上是一个字符串文字,所以不,它不相关。也没有 nnulls...
事实上视图是负责的,虽然是非常间接的,最终调用了一个PL/SQL函数。我发布了一个带有解释的自我回答。【参考方案3】:
有一次我输入了一个错误的列名,但在另一个选择中有一个同名的列,所以我的内部查询通过加入外部表来“工作”。 如果您只是自己运行内部查询(没有外部选择或更新),它会起作用吗?
【讨论】:
我需要稍后检查,因为我目前(直到明天)没有访问权限。几乎没有,但我没有看到其他可能的原因。【参考方案4】:可能是行级安全性(也称为虚拟专用数据库),您已被授予读取表行的权限,但不能更新它们。
是否涉及任何数据库链接?
【讨论】:
我确定没有行级安全性,因为我使用该数据库(通常以编程方式,但这次我必须手动发出查询)。数据库链接是什么意思?【参考方案5】:是不是你的 field1 不是你的子查询返回的第一列?我怀疑您的 IN 只会将该值与结果的第一列进行比较。
【讨论】:
没有。我调试了它并发布了一个自我回答,但还不能接受。以上是关于在“where”子句中使用“in”运算符更新行的主要内容,如果未能解决你的问题,请参考以下文章