假设我有两个列,列Col1,Col2和Col3分别为VARCHAR2, CLOB 和NUMBER类型。
如何获得这些表格的差异? (即表B 中存在但不存在于表A 中的记录列表)
Table A:
╔═══════╦═════════════════╦══════╗
║ Col1 ║ Col2 ║ Col3 ║
╠═══════╬═════════════════╬══════╣
║ P1111 ║ some_long_text1 ║ 1234 ║
║ P1111 ║ some_long_text1 ║ 1233 ║
║ P1111 ║ some_long_text2 ║ 1233 ║
╚═══════╩═════════════════╩══════╝
Table B:
╔═══════╦═════════════════╦══════╗
║ Col1 ║ Col2 ║ Col3 ║
╠═══════╬═════════════════╬══════╣
║ P1111 ║ some_long_text1 ║ 1234 ║
║ P1111 ║ some_long_text1 ║ 1235 ║
║ P1112 ║ some_long_text2 ║ 1233 ║
╚═══════╩═════════════════╩══════╝
Expected results:
╔═══════╦═════════════════╦══════╗
║ Col1 ║ Col2 ║ Col3 ║
╠═══════╬═════════════════╬══════╣
║ P1111 ║ some_long_text1 ║ 1235 ║
║ P1112 ║ some_long_text2 ║ 1233 ║
╚═══════╩═════════════════╩══════╝
答案 0 :(得分:2)
要比较LOB
类型,您可以使用DBMS_LOB.COMPARE
功能。
SELECT table_b.*
FROM table_b
LEFT JOIN table_a
ON table_b.col1 = table_a.col1
AND DBMS_LOB.COMPARE(table_b.col2, table_a.col2) = 0
AND table_b.col3 = table_a.col3
WHERE table_a.col1 IS NULL;
答案 1 :(得分:1)
您可以使用dbms_lob.substr()函数,如下所示使用减号运算符
{{1}}
答案 2 :(得分:0)
在Oracle中,我认为你可以做到这一点
SELECT * FROM TableB WHERE (Col1, Col2, Col3) NOT IN (SELECT Col1, Col2, Col3 from TABLEA)
您加入的其他DBS:
SELECT * FROM TableB left outer join TableA
on (a.Col1=b.Col1 and a.Col2=b.Col2 and a.Col3=b.Col3)
WHERE a.col1 is null
您可能需要在CLOB列上执行校验和/哈希,但是它是否包含在比较中。
答案 3 :(得分:0)
根据您的预期结果,似乎左连接将运作良好。
实现这一点的效果:
Select B.Col1
,B.Col2
,B,Col3
FROM TableB B
LEFT OUTER JOIN TableA A
ON B.Col1 = A.Col1
WHERE B.Col2 = A.Col2
AND B.Col3 = A.Col3
AND A.Col1 IS NULL
由于WHERE
条件会过滤数据集,因此有必要匹配所有内容,包括与表A匹配的NULL
值。仅包含A.Col1 IS NULL
WHERE
然后您确定只能看到TableB中没有相应TableA值的值。
连接很昂贵,而Left Joins更是如此。仅加入一个键值应该有助于提高效率(特别是因为您无论如何都希望匹配所有记录)。通过在WHERE
子句中放置其他连接谓词,您可以对这些谓词进行过滤。
现在 - 就CLOB
上的匹配而言 - 散列这些值可能有也可能没有任何好处。这取决于数据的大小和使用的散列算法。 Oracle Optimizer可以自动选择对列进行哈希处理以进行比较,也可以使用函数强制它。
我认为引擎应该被允许做出这个选择 - 我相信会有其他人不同意我,他们都有正当理由。我的论点是这样的:如果优化程序可以自己做出这个决定,为什么不强制执行额外的步骤?
如果这将是一个经常被调用的大量使用的查询(例如,作为存储过程),那么创建一个存储CLOB
的预先计算的哈希值的列可能会有好处便于比较。这种改变几乎肯定会消除在执行期间要求每个CLOB进行散列的开销,这可能是一个非常CPU密集的操作。我个人不建议索引散列列,因为我希望每个CLOB条目可能是唯一值。如果是这种情况,则表的PK应足以基于行唯一性进行匹配。
答案 4 :(得分:0)
1)您必须为lob对象创建UDT。
create or replace type lob_wrapper is object
( x clob,
hash varchar2(100),
constructor function lob_wrapper(p_x clob) return self as result,
MAP MEMBER FUNCTION get_hash RETURN varchar2
)
;
create or replace type body lob_wrapper
as
constructor function lob_wrapper(p_x clob)
return self as result
as
temp_ varchar(1000) := p_x;
begin
self.x := p_x;
-- add here better implementation of hashing clob.
select ora_hash(temp_) into self.hash from dual;
return;
end;
MAP MEMBER FUNCTION get_hash RETURN varchar2 is
v_hash varchar2(4000);
begin
return hash;
end;
end;
对象构造计算clob的哈希值。在示例中,我使用的是ora_hash
,但您应该选择更好的解决方案(dbms_crypto.hash
)。
当db尝试比较两个对象时,将调用object中的映射函数get_hash
。
select col1,lob_wrapper(col2) col2 ,col3 from test_clob_b
minus
select col1,lob_wrapper(col2) col2 ,col3 from test_clob_a
要从对象获取原始值,请添加另一个选择。
select col1,t.col2.x oringal_value,col3, t.col2.hash hash_value from (
select col1,lob_wrapper(col2) col2 ,col3 from test_clob_b
minus
select col1,lob_wrapper(col2) col2 ,col3 from test_clob_a
) t;