SQL-如何比较CLOB

时间:2020-03-06 14:30:11  来源:igfitidea点击:

在DB2触发器中,我需要比较CLOB字段的值。
就像是:

IF OLD_ROW.CLOB_FIELD != UPDATED_ROW.CLOB_FIELD

但是"!="不适用于比较CLOB。

比较的方式是什么?

编辑添加:

如果在更新期间更改Clob字段,我的触发器需要执行一些操作。这就是我需要比较触发代码中的2个CLOB的原因。
我正在寻找有关如何完成此操作的详细信息

解决方案

我相信不可能在CLOB字段上使用这类运算符,因为它们的存储方式。

计算Clob的md5(或者其他)哈希值,然后进行比较。初始计算会很慢,但是比较却很容易。如果大量数据不经常更改,这可能是一个好方法。

一种计算md5的方法是通过触发器中的Java语句。将它们保存在同一表中(如果可能)或者构建一个简单的辅助表。

Iglekott的想法很不错,但有一个警告:

如果数据可能受到攻击,请谨慎使用哈希比较。当前对于特定的MD5值生成哈希冲突在计算上是不可行的,但是可以生成两个将产生相同MD5的不同输入(因此不会触发代码)。也可以生成两个具有相同前缀的不同字符串,这些字符串会哈希为相同的值。

如果这种攻击可能导致系统完整性受到损害,并且这是一个令人担忧的问题,则我们需要探索其他选择。最简单的方法就是简单地切换哈希函数,SHA-2目前没有已知的漏洞。

如果这不是问题,请使用CRC。我们不打算在这里寻求加密安全性。如果将这些东西安装在智能炸弹上,请不要使用加密功能较弱的功能," mkay? :-)

在Oracle 10g中,可以使用DBMS_LOB.compare()API。

例子:

select * from table t where dbms_lob.compare(t.clob1, t.clob2) != 0

完整的API:

DBMS_LOB.COMPARE (
   lob_1            IN BLOB,
   lob_2            IN BLOB,
   amount           IN INTEGER := 4294967295,
   offset_1         IN INTEGER := 1,
   offset_2         IN INTEGER := 1)
  RETURN INTEGER;

DBMS_LOB.COMPARE (
   lob_1            IN CLOB  CHARACTER SET ANY_CS,
   lob_2            IN CLOB  CHARACTER SET lob_1%CHARSET,
   amount           IN INTEGER := 4294967295,
   offset_1         IN INTEGER := 1,
   offset_2         IN INTEGER := 1)
  RETURN INTEGER; 

DBMS_LOB.COMPARE (
   lob_1            IN BFILE,
   lob_2            IN BFILE,
   amount           IN INTEGER,
   offset_1         IN INTEGER := 1,
   offset_2         IN INTEGER := 1)
  RETURN INTEGER;

DB2是否将"!="用于不等于? ANSI SQL标准对不等于使用<>

如果CLOB小于或者等于32K,则可以将它们强制转换为VARCHAR,从而允许比较,LIKE和各种SQL字符串函数。

否则,我们可能要考虑添加一列以包含CLOB的哈希,并更改应用程序以在CLOB更新时使该哈希保持最新状态。

md5的想法可能是最好的,但是另一种替代方法是创建一个仅在更新CLOB字段时才触发的特殊触发器。

根据语法图,我们可以将触发器定义为:

CREATE TRIGGER trig_name AFTER UPDATE OF CLOB_FIELD 
//trigger body goes here

这是假设应用程序(或者正在更新表的任何人)足够聪明,仅在对clob字段进行了更改时才更新CLOB字段,而不是在每次更新表时都不会。