您可以使用 BLOB 值的散列并按散列分组以及所有其他(非 BLOB)列,从每个组中选择一个pk
(或rowid
,参见下面的讨论),例如min(pk)
or min(rowid)
,然后选择相应的行从表。
对于散列,您可以使用ora_hash
,但这仅适用于学校作业。如果这是一个严肃的项目,您可能需要使用dbms_crypto.hash
.
这是否是一个正确的解决方案取决于散列 BLOB 值时发生冲突的可能性。在 Oracle 11.1 - 11.2 中,您可以使用 SHA-1 哈希(160 位);也许这足以区分您的 BLOB 值。在更高的 Oracle 版本中,可以使用更长的哈希(在我的版本 12.2 中最多 512 位)。显然,散列越长,查询越慢 - 但由于冲突,您不会错误地将不同的 BLOB 值识别为“重复”的可能性就越高。
其他响应者询问或提到了表中的一个或多个主键 (pk) 列。如果你有一个,你可以使用它来代替rowid
我下面的查询 - 但rowid
应该可以正常工作。(不过,如果您的桌子有 pk,则首选。)
dbms_crypto.hash
为要使用的散列算法接受一个整数参数(1、2、3 等)。这些在包中被定义为命名常量。唉,在 SQL 中你不能引用包常量;您需要事先找到值。(或者,在 Oracle 12.1 或更高版本中,您可以通过在with
子句中包含一个函数来即时执行此操作 - 但让我们保持简单。)
因此,为了涵盖 Oracle 11.1 及更高版本,我假设我们要使用SHA-1算法。要从包中找到它的整数值,我可以这样做:
begin
dbms_output.put_line(dbms_crypto.hash_sh1);
end;
/
3
PL/SQL procedure successfully completed.
如果您的 Oracle 版本更高,您可以检查 的值hash_sh256
,例如;在我的系统上,它是 4。记住这个数字,因为我们将在下面使用它。
查询是:
select {whatever columns you need, including the BLOB}
from {your table}
where rowid in (
select min(rowid)
from {your table}
group by {the non-BLOB columns},
dbms_crypto.hash({BLOB column}, 3)
)
;
注意hash
函数中使用的数字 3 - 这是dbms_crypto.hash_sh1
我们之前发现的 的值。