# Hashfunktion Oracle 10g Express



## sbg (19. Mai 2011)

Hallo Leute, 

ich bin neu hier und möchte gerne für meine bestehende Oracle 10g Datenbank folgenes erzeugen:

Beim anlegen einer neuen Person in der Tabelle PERSON soll ein automatischer Hashwert erstellt werden. Dieser Hashwert soll in der Tabelle PERSON in der Spalte HASH mit eingetragen werden.

Daher meine Frage:
Gibt es eine Oracle Hash Funktion, die das ganze löst, oder muss ich dass über TRIGGER lösen?

Bei Google finde ich leider nur die Sachen bezüglich einer Hash-tabelle und Hash-clustering....

Bitte um Hilfe


----------



## dbwizard (19. Mai 2011)

Hallo,

in einer 10G R2 Oracle DB gibt es eine Funktion DBMS_UTILITY.get_hash_value. Du musst schauen, ob dies auch in der XE implemetiert ist. Alternativ findest du diverse Funktionen zu diesem Thema in der DBMS_CRYPTO Package oder auch in DBMS_OBFUSCATION_TOOLKIT, wobei letzteres so wie ich mich erinnere keine HASH Fuktionen beinhaltet




Gruss


----------



## sbg (19. Mai 2011)

hi, danke für die rasche info!

also DBMS_CRYPTO ist installiert- man muss nur noch grant execute on dbms_crypto to XXXX machen, (als SYS user) dann ****t der zugriff....

mit deiner genannte funktion komme ich leider nicht ganz hin....

hab die MD5 und SH1 funktionen getestet- beide funktionieren und ich kann mir die Hashes von den Eintrrägen erzeugen- ich möchte aber gerne dass bei einem neuen Eintrag in die DB automatisch in der Spalte HASH ein eindeutiger HASHWERT eingetragen wird.

würde dass über einen trigger und systimestamp gehen****

oder irre ich mich hier?


----------



## MPr (20. Mai 2011)

harmlos wäre vermutlich ORA_HASH:

```
SQL> select ora_hash('hello world') from dual;

ORA_HASH('HELLOWORLD')
----------------------
            1896528268
```
Gruß
Martin


----------



## MPr (20. Mai 2011)

in Oracle 10 kann man die Befüllung der HASH-Spalte via Trigger durchführen - obwohl Trigger (in der Regel) häßlich, schlecht wartbar und übel für die Performance sind:

```
-- 10.2.0.4
create table test
( string_value varchar2(32)
, hash_value number);

create or replace trigger hash_trigger
before insert
on test
for each row
begin
  select ora_hash(:new.string_value)
  into :new.hash_value
  from dual;
end hash_trigger;
/

insert into test(string_value) values ('HELLO WORLD');

SQL> select * from test;

STRING_VALUE                     HASH_VALUE
-------------------------------- ----------
HELLO WORLD                      3784902367
```
Viel hübscher geht das in 11g, wo man zu diesem Zweck virtual columns verwenden kann:

```
-- 11.1.0.7
create table test
( string_value varchar2(32)
, hash_value NUMBER GENERATED ALWAYS AS (ora_hash(string_value)) virtual);

insert into test(string_value) values ('HELLO WORLD');

SQL> select * from test;

STRING_VALUE                     HASH_VALUE
-------------------------------- ----------
HELLO WORLD                      3784902367
```

Gruß

Martin


----------



## sbg (20. Mai 2011)

sieht gut aus- werd ich gleich ausprobieren- danke für die hilfe


----------



## sbg (23. Mai 2011)

Hallo Leute, anbei mal meine Tabelle (Oracle 10g EX)


```
CREATE TABLE  "PERSON" 
   (	"PERS_ID" NUMBER NOT NULL ENABLE, 
	"P_VORNAME" VARCHAR2(50), 
	"P_NACHNAME" VARCHAR2(50), 
	"SVNR" NUMBER(*,0), 
	"DATUM_EINTRAG" DATE, 
	"ADRESSE" VARCHAR2(80), 
	"HASH" VARCHAR2(100), 
	 CONSTRAINT "PK_PERSON" PRIMARY KEY ("PERS_ID") ENABLE
   )
/


CREATE OR REPLACE TRIGGER  "HASH_TRIGGER2" 
before insert on 
Person for each row 
begin

select ora_hash(systimestamp)   into :new.HASH   from Person; end hash_trigger2;
/
ALTER TRIGGER  "HASH_TRIGGER2" ENABLE
/
```


Tabelle selber funktioniert, und insert von daten hat auch funktioniert- bis ich den trigger gemacht habe- seitdem kommt bei folgenden insert befehl:



```
insert into Person values ('1234','Tom','Moser','123324','23-02-2011','Schefa 23','8');
```


ORA-01422: Exakter Abruf gibt mehr als die angeforderte Zeilenzahl zurück
ORA-06512: in "INSTALLATEUR.HASH_TRIGGER2", Zeile 3
ORA-04088: Fehler bei der Ausführung von Trigger 'INSTALLATEUR.HASH_TRIGGER2'

leider weiss ich nicht wirklich wie ich den fehler weg bekomme. denke mal das ich irgendwo auf die ganze tabelle und nicht auf die zeile alleine zugreife....

hat da jemand eine idee****

besten dank Chris


----------



## MPr (23. Mai 2011)

das ist das Gute an knappen Testfällen: man kann sie problemlos durchspielen und die Fehlermeldungen untersuchen. Im gegebenen Fall bekomme ich initial zwar nicht ORA-01422, sondern ORA-01403: "Keine Daten gefunden", aber die Ursache ist trotzdem klar: im Trigger wird in der Query auf die Tabelle "Person" zugegriffen, die bei mir zunächst leer ist, was ORA-01403 ergibt. Wenn ein Datensatz in der Tabelle vorliegt, gibt's keine Fehlermeldung, aber sobald mehr als ein Datensatz enthalten ist, folgt ORA-01422. Hier soll aber überhaupt keine Tabelle erscheinen, sondern nur ein Lookup pro Einzelsatz (for each row) durchgeführt werden - und deshalb muss man hier nur "Person" durch dual ersetzen und schon läuft's:

```
CREATE OR REPLACE TRIGGER  "HASH_TRIGGER2"
before insert on
Person for each row
begin
select ora_hash(systimestamp)   into :new.HASH   from dual; end hash_trigger2;
/

Trigger wurde erstellt.

SQL> insert into Person values ('12345','Tom','Moser','123324','23-02-2011','Schefa 23','8');

1 Zeile wurde erstellt.

SQL> insert into Person values ('123456','Tom','Moser','123324','23-02-2011','Schefa 23','8');

1 Zeile wurde erstellt.

SQL> insert into Person values ('1234567','Tom','Moser','123324','23-02-2011','Schefa 23','8');

1 Zeile wurde erstellt.

select PERS_ID, HASH from person;

 PERS_ID HASH
-------- -----------
    1234 175263980
    1235 1524367124
   12345 1823310661
  123456 3771441293
 1234567 2156626565
```
Gruß

Martin


----------



## sbg (23. Mai 2011)

besten Dank, jetzt funktionierts!
Echt super dieses Forum- ich hoffe ich kann hier auch jemanden mal weiter helfen.

Thema kann geschlossen werden.


----------

