2008-09-21 32 views
8

en un activador de DB2, necesito comparar el valor de un campo CLOB. Algo así como: "! ="SQL - ¿Cómo se compara un CLOB

IF OLD_ROW.CLOB_FIELD != UPDATED_ROW.CLOB_FIELD 

pero no funciona para comparar CLOBs.

¿Cuál es la manera de compararlo?

Editado para añadir:

Mi gatillo tiene que hacer algún tipo de acción si el campo Clob fue cambiado durante una actualización. Esta es la razón por la que necesito comparar los 2 CLOB en el código de activación. Busco alguna información detallada sobre cómo se puede hacer esto

+0

entonces probablemente debería considerar @ respuesta de igelkott. Es probable que sea la mejor manera. Calcula la nueva suma de comprobación MD5 y la compara con la anterior, y si difieren, el CLOB ha cambiado. Hay una posibilidad extremadamente pequeña de que cambie y obtienes la misma suma de comprobación, pero no te preocupes. –

Respuesta

1

Creo que no es posible utilizar este tipo de operadores en los campos CLOB, debido a la forma en que se almacenan.

+0

Esta es la razón por la que estoy preguntando. Gracias. –

7

Calcula el hash md5 (u otro) de los clobs y luego compáralos. El cálculo inicial será lento, pero la comparación es rápida y fácil. Este podría ser un buen método si la mayor parte de sus datos no cambia con mucha frecuencia.

Una forma de calcular md5 es a través de una declaración java en su desencadenador. Guárdelos en la misma tabla (si es posible) o cree una tabla auxiliar simple.

6

idea de Iglekott es buena, con una advertencia:

tener cuidado con compare-por-hash si sus datos son propensos a ser atacado. Actualmente, no es factible computacionalmente generar una colisión hash para un valor MD5 específico, pero es posible generar dos entradas diferentes que producirán el mismo MD5 (por lo tanto, no se activará el código). También es posible generar dos cadenas diferentes con con el mismo prefijo que hash con el mismo valor.

Si ese tipo de ataque puede comprometer la integridad de su sistema, y ​​eso es una preocupación, desea explorar otras opciones. Lo más fácil sería simplemente cambiar las funciones hash, SHA-2 no tiene vulnerabilidades actualmente conocidas.

Si esto no es una preocupación - diablos, vaya con CRC. No vas a buscar seguridad criptográfica aquí. Simplemente no vayas con una función criptográficamente débil si estas cosas se están instalando en una smartbomb, 'mkay? :-)

8

En Oracle 10g puede usar la API DBMS_LOB.compare().

Ejemplo:

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

API completo:

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; 
+0

Tenga en cuenta que "Las funciones con NULL o valores de entrada no válidos para los parámetros devuelven un NULL". Esto puede ser significativo en algunos casos. – Vadzim

-1

¿El uso de DB2 para != no iguales? El estándar ANSI SQL usa <> para no iguales.

+0

DB2 permite tanto <> como! = Indistintamente. El problema con esta pregunta no era el operador utilizado para comparar, sino el hecho de que los tipos de datos de objeto grandes (BLOB/CLOB) no permiten comparaciones de igualdad en su tipo nativo. Sin embargo, DB2 permite que las expresiones SQL moldeen la parte superior de un BLOB o CLOB a un tipo de datos diferente, incluidos los tipos que permiten operaciones de comparación. –

1

Si los CLOB son 32K o menos, puede convertirlos como VARCHAR, lo que permite la comparación, LIKE y varias funciones de cadena SQL.

De lo contrario, es posible que desee considerar agregar una columna para contener el hash del CLOB y cambiar las aplicaciones para mantener ese hash actualizado cada vez que se actualiza el CLOB.

2

La idea de md5 es probablemente la mejor, pero otra alternativa es crear un activador especial que solo se active cuando se actualiza el campo CLOB.

De acuerdo con la syntax diagram, definiría el gatillo como:

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

Esto es asumiendo que su solicitud (o quien haga la actualización de la tabla) es lo suficientemente inteligente como para actualizar el campo CLOB sólo cuando no ha sido un cambio realizado en el campo de clob, y no cada vez que su tabla se actualiza.

0

Simplemente declare el disparador para disparar si esa columna en particular se actualiza.

create trigger T_TRIG on T 
before update of CLOB_COL 
... 
0

Generar un valor hash y compararlos es la mejor manera en mi humilde opinión.

Aquí está el código no probado:

... 
declare leftClobHash integer; 
declare rightClobHash integer; 
set leftClobHash = (
    SELECT DBMS_UTILITY.GET_HASH_VALUE(OLD_ROW.CLOB_FIELD,100,1024) AS HASH_VALUE 
    FROM SYSIBM.SYSDUMMY1); 
set rightClobHash = (
    SELECT DBMS_UTILITY.GET_HASH_VALUE(UPDATED_ROW.CLOB_FIELD,100,1024) AS HASH_VALUE 
    FROM SYSIBM.SYSDUMMY1); 

IF leftClobHash != rightClobHash 
... 

en cuenta que necesita el privilegio EXECUTE en el módulo DBMS_UTILITY. Puede encontrar más información sobre el código SQL PL proporcionado en los siguientes enlaces.