55 votes

Hachage d'une chaîne de caractères en une valeur numérique dans PostgreSQL

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

Quelqu'un peut-il m'indiquer un algorithme ou une API à utiliser pour y parvenir ?

Cela fait des heures que je cherche sur Google, mais je n'ai rien trouvé d'utile jusqu'à présent :(

73voto

Daniel Vérité Points 15675

Il suffit de conserver les 32 ou 64 premiers bits du hachage MD5. Bien sûr, cela annule la principale propriété de md5 (=la probabilité de collision est infinitésimale) mais vous obtiendrez toujours une grande dispersion des valeurs, ce qui est probablement suffisant 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;

17voto

a_horse_with_no_name Points 100769

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

select md5('hello, world');

Cela renvoie une chaîne de caractères avec un numéro hexagonal.

Malheureusement, il n'existe pas de fonction intégrée pour convertir les hexagones en nombres entiers, mais comme vous le faites de toute façon dans PL/pgSQL, cela pourrait vous aider :

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

5voto

dbenhur Points 9694

Doit-il s'agir d'un nombre entier ? Le site pg_crypto fournit un certain nombre de fonctions de hachage standard (md5, sha1, etc). Elles retournent toutes un 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 type binaire non octet que Pg supporte est uuid. Vous pouvez convertir un condensé en uuid comme ceci :

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

3voto

dvlcube Points 98

Il s'agit d'une implémentation de la méthode Java String.hashCode() :

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;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X