如果你有两个数据来源,如平面文件或表数据,并且要将他们合并在一起,你将怎么做?如果他们有一个共同的属性,如客户ID,那么该解决方案应该是很明显:合并相关的属性,在这个例子中,只需合并客户ID就够了。如果没有任何共同之处该怎么办呢?唯一的要求就是,将数据源1中的记录和数据源2中的记录进行匹配 .并且,那个记录去和另一个记录匹配并没有关系,那么问题是,一个数据源中的每一个纪录如何获得从其他数据源记录的标记。
上述问题可以被描述为向一个数据库中加入了不同的或看似无关的数据。在先前的文章的文章中,涉及如何使用ROWNUM在无关的数据之间创造联系。该合并方法的本质是利用甲骨文提供虚拟数据列来建立联系。下面的查询可以用来作为CREATE TABLE AS SELECT声明的一部分或作为基于满足加入条件既定目标表的插入。
SELECT
*
FROM
(
SELECT
, ROWNUM
AS
rownum_a
FROM
TABLE_A
) ALIAS_A,
(
SELECT
, ROWNUM
AS
rownum_b
FROM
TABLE_B
) ALIAS_B
WHERE
ALIAS_A.rownum_a
=
ALIAS_B.rownum_b;
假设要合并的记录的数目过大(如数以百万计),这种方法潜在的缺点是什么?那么,当一行作为一个记录时又如何了?我们没有真正的控制权决定的查询所返回结果行的顺序,直到我们执行查询之前,甲骨文是不知道记录的行号的。换言之, ROWNUM是在这样的事实上创建的。如果你要从两个地方选择数百万行,你将支付甲骨文公司为每个记录分配行号(只针对你的查询,而不是永远)的时间。
让我们监测将两个有100万行的表合并到一起的一个会话。在这第一个例子中,这个数据源已经记录可100万个记录。表A范围从1到1000000及表B范围从1000001至2000000 (即在第一个表中再加入100万行) .如果加入后能够完美的保持行的顺序,那么有序对将像下面表格这个样子:
当我们查看数据时(通过Toad)发现Oracle数据库并不执行一个完美的排序,并且相差甚远。
该ROWNUM_A和B值一个一个都匹配,因为这是我们匹配/合并的。注意:记录1321 (和1001321 )是如何同ROWNUM 1标记在一起的 .所以我们可以推断是,甲骨文以同样的方式填补表格之间的空白区块。这应该说服你一次甚至永远(如果你至今还不知知道), ROWNUM虚拟数据列已没有意义或与个表中记录的实际顺序无关。
创建表的声明追踪, 经过TKPROF 解析后,输出结果如下:
CREATE
TABLE
TABLE_ROWNUM
AS
SELECT
*
FROM
(
SELECT
ID, ROWNUM
AS
rownum_a
FROM
TABLE_A)
ALIAS_A,
(
SELECT
ID
AS
id_b, ROWNUM
AS
rownum_b
FROM
TABLE_B)
ALIAS_B
WHERE
ALIAS_A.rownum_a
=
ALIAS_B.rownum_b
call
count
cpu elapsed
disk
query
current
rows
--
----- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse
1
0.01
0.00
0
0
0
0
Execute
1
4.41
5.63
1770
12324
5239
1000000
Fetch
0
0.00
0.00
0
0
0
0
--
----- ------ -------- ---------- ---------- ---------- ---------- ----------
total
2
4.42
5.64
1770
12324
5239
1000000
我们知道一个事实,即每个表都有100万行。在分析了表后, NUM_ROWS值显示为1034591 .当与甲骨文本身将通过连续计数报告的值相比较时要小心依靠通过第三方工具检查出的值(包括从USER_TABLES选择NUM_ROWS )。为什么会有差异呢?是否是因为分析是基于样本或估算的数据,或根据检查到的每个记录?