我偶然发现了我不理解的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
中没有WHERE
选定的行。
子查询是一个非常复杂的SQL文件,包含2个(不同的)表,1个视图,连接和它自己的UPDATE
子句。如果这很重要,那就是Oracle Database 10g。
所以,问题是,为什么SELECT
没有触及{{1}} 返回的行?
答案 0 :(得分:4)
最后把它钉了下来。原来,子查询选择中使用的视图间接(通过另一个视图)称为存储过程/函数。然后,该过程访问了UPDATE
中正在修改的表。结果,Oracle抛出异常,因为“表some_table
正在被修改,函数可能看不到结果”(不记得确切的文本)。但函数最后使用when other then return null
,因此错误被有效隐藏,子查询根本没有返回任何内容 - 反过来UPDATE
没有效果。
道德:永远不要使用过于宽泛的异常捕手。我在其他语言中遵循此规则,但显然不在PL / SQL中: - /
答案 1 :(得分:1)
如果“some-table”实际上是一个视图,那么您可能遇到了系统无法解决如何更新视图基础的表的问题。
答案 2 :(得分:1)
我有一个问题,一次我输错了一个列名,但是另一个选择中有一个同名的列,所以我的内部查询通过加入外表来“工作”。
如果你只是自己运行内部查询(没有外部选择或更新)它是否有效?
答案 3 :(得分:0)
可能是行级安全性(也称为虚拟专用数据库),您可以在其中获得读取表行的权限,但不能更新它们。
是否涉及任何数据库链接?
答案 4 :(得分:0)
你的field1不是从子查询返回的第一列吗?我怀疑你的IN只会将值与结果的第一列进行比较。