Blog
Checksum de fontes PL/SQL
Assim como temos em ambientes Linux o cksum e o sha1sum que nos permitem gerar um código hash para a comparação de consistência de um arquivo, umas das opções no Oracle Database é a função GET_HASH_VALUE disponível no pacote DBMS_UTILITY que permite gerar um código hash do fonte sendo muito útil para identificar se ele está consistente ou se houve alguma alteração, principalmente quando comparamos extensos códigos PL/SQL que visivelmente daria trabalho para determinar se estão iguais entre uma base de dados e outra, por exemplo.
Criando uma procedure de exemplo e obtendo o hash:
SQL> create or replace procedure exemplo as 2 begin 3 null; 4 end; 5 / Procedure created. SQL> SELECT AVG(DBMS_UTILITY.GET_HASH_VALUE(TEXT,1000000000,POWER(2,30))) AS CHECKSUM FROM DBA_SOURCE WHERE OWNER = 'SYS' AND NAME ='EXEMPLO'; CHECKSUM ---------- 1742638361
Agora recriando a procedure incluindo apenas um espaço entre o null e o ; (ponto e virgula)
SQL> create or replace procedure exemplo as 2 begin 3 null ; 4 end; 5 / Procedure created. SQL> SELECT AVG(DBMS_UTILITY.GET_HASH_VALUE(TEXT,1000000000,POWER(2,30))) AS CHECKSUM FROM DBA_SOURCE WHERE OWNER = 'SYS' AND NAME ='EXEMPLO'; CHECKSUM ---------- 1701853948
Com a inserção de apenas um espaço já podemos constatar que o hash dela já não é igual ao hash do PL/SQL anterior indicando assim que o fonte é diferente.
Recriando a procedure da forma que era originalmente iremos voltar a ter o mesmo hash 1742638361
SQL> create or replace procedure exemplo as 2 begin 3 null; 4 end; 5 / Procedure created. SQL> SELECT AVG(DBMS_UTILITY.GET_HASH_VALUE(TEXT,1000000000,POWER(2,30))) AS CHECKSUM FROM DBA_SOURCE WHERE OWNER = 'SYS' AND NAME ='EXEMPLO'; CHECKSUM ---------- 1742638361
Outro método para se obter o hash de um PL/SQL é através do pacote DBMS_CRYPTO
SQL> set serveroutput on SQL> declare 2 3 string varchar2(32767); 4 l_hash raw(2000); 5 lvschema VARCHAR2(30) :='SYS'; 6 lvname VARCHAR2(30) :='EXEMPLO'; 7 lvtype varchar2(30) :='PROCEDURE'; 8 9 begin 10 11 l_hash:=dbms_crypto.hash(dbms_metadata.get_ddl(lvtype, lvname, lvschema), dbms_crypto.hash_sh1); 12 dbms_output.put_line('HashSHA1='||l_hash||' Name='||lvschema||'.'||lvname); 13 14 end; 15 / HashSHA1=859EEB0AEE5CF93CF9507951E7446D6EAD958885 Name=SYS.EXEMPLO PL/SQL procedure successfully completed.
Espero que a dica possa ser útil para você também.