SQL-如何比较CLOB
在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字段,而不是在每次更新表时都不会。