理解这个SQL查询

5

我是oracle数据库新手,能否有人帮我理解这个查询语句。这个查询语句从表中消除重复项。

DELETE FROM table_name A 
 WHERE ROWID > (SELECT min(rowid) 
                  FROM table_name B 
                 WHERE A.key_values = B.key_values);

任何改进查询的建议都是受欢迎的。
编辑:这不是作业,我不理解子查询正在做什么,以及ROWID > On子查询是什么意思?
此查询的来源可在此处查看。

你对查询中的哪部分不理解?这是你的作业吗? - Frederik Wordenskjold
2
@Frederik Wordenskjold 作业警察? - user479911
不是作业,子查询中实际执行了什么? - SuperMan
你需要阅读关于相关子查询的资料:http://www.oracle-database-tips.com/oracle_subquery.html - Sam Saffron
@arex1337 这只会浪费我的时间。我只是在问个问题,没什么大不了的。你为什么会这么想呢?难道是作业警察吗? - Frederik Wordenskjold
4个回答

5

深入分析实际机制:

DELETE FROM table_name A 

这是一个标准的查询语句,用于从名为"table_name"的表中删除记录。在子查询中,它被别名为"A"。

WHERE ROWID > 

这将对删除操作施加一个条件,即对于遇到的每一行,其ROWID必须满足大于某个条件。

            (SELECT min(rowid) 
              FROM table_name B 
             WHERE A.key_values = B.key_values)

这是一个与主DELETE语句相关的子查询。它使用外部查询的值A.key_values。因此,给定DELETE语句中的一条记录,它将运行此子查询,以查找在同一表中(现在别名为B)承载相同key_values值的所有记录的最小rowid(内部记录id)。

因此,综合起来,假设你有以下行:

rowid   |  key_values
=======    ============
1          A
2          B
3          B
4          C
5          A
6          B

子查询根据具有相同“key_values”的所有记录计算出每个记录的最小rowid为:
rowid   |  key_values    | min(rowid)
=======    ============    ===========
1          A               1
2          B               2
3          B               2  **
4          C               4
5          A               1  **
6          B               2  **

对于带有**标记的记录,条件为:

WHERE ROWID > { subquery }

变为真,它们将被删除。

编辑-额外信息

此答案先前声明ROWID按插入顺序增加。这是非常不正确的。事实是rowid只是一个文件.块.块上的插槽-一个物理地址

http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:53140678334596

Tom的后续 2008年12月1日-中央时区早上6点:

很可能D将成为表中的“第一”-因为它取代了A的位置。

如果rowid始终“增长”,则永远不会重用空间(这是rowid始终增长的含义之一-我们将无法重用旧空间,因为rowid只是一个文件.块.块上的插槽-一个物理地址)


很好的解释。我本来想展示实际的ROWID样例而不是纯整数,但概念已经讲得很清楚了。 - Jeffrey Kemp

3

引用AskTom

在插入时会为行分配rowid,并且是不可变的(永远不会改变)...除非该行被删除并重新插入(这意味着它是另一行,而不是同一行!)

您提供的查询依赖于该rowid,并且基于每个key_values,删除所有行中rowid值高于最小值的行。因此,任何重复项都将被删除。

您提供的子查询是一个相关子查询,因为子查询中的表引用与子查询外部的表引用之间存在关系。


5
不能正确地认为“插入第一行后的重复记录将被删除”,因为ROWID并不保证按插入顺序递增,事实上通常并不是这样。 - Jeffrey Kemp

3

Rowid 是一个伪列,用于在表中唯一标识每一行;是数字类型。

此查询查找所有在 AA.key_values = B.key_values 的行,并删除除最小的 rowid 以外的所有行。这只是一种任意选择要保留的重复内容的方法。


1

ROWID 是一个数字,每插入一行就会递增。如果你有两个 ROWID 数字 16 和 24,你就知道 16 是在 24 前插入的。你的 delete 语句会删除所有重复项,只保留第一个插入的副本。明白了吗?


-1 这是不正确的。ROWID 采用特定格式,通常不会“对每个新行进行递增”。请参见 http://alexzeng.wordpress.com/2008/10/15/oralce-physical-rowid-structure/。 - Jeffrey Kemp
感谢您的更正。对于此情况,只需确保它能唯一标识一行并且可比较(具有严格顺序)即可。 - 9000

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