web-dev-qa-db-fra.com

Hachage d'une chaîne à une valeur numérique dans PostgreSQL

J'ai besoin de convertir des chaînes stockées dans ma base de données en une valeur numérique. Le résultat peut être Entier (préféré) ou Bigint. Cette conversion doit être effectuée côté base de données dans une fonction PL/pgSQL.

Quelqu'un peut-il me signaler un algorithme ou une API qui peut être utilisée pour y parvenir?

Je recherche cela sur Google depuis des heures maintenant, je n'ai rien trouvé d'utile jusqu'à présent :(

33
Salman A. Kagzi

Conservez simplement les 32 ou 64 premiers bits du hachage MD5. Bien sûr, cela annule la propriété principale de md5 (= la probabilité de collision étant infinitésimale) mais vous obtiendrez toujours une large dispersion de valeurs qui est probablement suffisante pour votre problème.

Fonctions SQL dérivées des autres réponses:

Pour bigint:

create function h_bigint(text) returns bigint as $$
 select ('x'||substr(md5($1),1,16))::bit(64)::bigint;
$$ language sql;

Pour int:

create function h_int(text) returns int as $$
 select ('x'||substr(md5($1),1,8))::bit(32)::int;
$$ language sql;
41
Daniel Vérité

Vous pouvez créer une valeur de hachage md5 sans problème:

select md5('hello, world');

Cela renvoie une chaîne avec un nombre hexadécimal.

Malheureusement, il n'y a pas de fonction intégrée pour convertir hex en entier, mais comme vous le faites dans PL/pgSQL de toute façon, cela pourrait aider:

https://stackoverflow.com/a/8316731/330315

14

Doit-il s'agir d'un entier? Le module pg_crypto fournit un certain nombre de fonctions de hachage standard (md5, sha1, etc.). Ils reviennent tous au bytea. Je suppose que vous pourriez jeter quelques bits et convertir bytea en entier.

bigint est trop petit pour stocker un hachage cryptographique. Le plus grand support de Pg de type binaire non bytea est uuid. Vous pouvez lancer un condensé sur uuid comme ceci:

select ('{'||encode( substring(digest('foobar','sha256') from 1 for 16), 'hex')||'}')::uuid;
                 uuid                 
--------------------------------------
 c3ab8ff1-3720-e8ad-9047-dd39466b3c89
4
dbenhur

Ceci est une implémentation de la String.hashCode() de Java:

CREATE OR REPLACE FUNCTION hashCode(_string text) RETURNS INTEGER AS $$
DECLARE
  val_ CHAR[];
  h_ INTEGER := 0;
  ascii_ INTEGER;
  c_ char;
BEGIN
  val_ = regexp_split_to_array(_string, '');

  FOR i in 1 .. array_length(val_, 1)
  LOOP
    c_ := (val_)[i];
    ascii_ := ascii(c_);
    h_ = 31 * h_ + ascii_;
    raise info '%: % = %', i, c_, h_;
  END LOOP;
RETURN h_;
END;
$$ LANGUAGE plpgsql;
0
dvlcube