517 votes

Générer un UUID dans Postgres pour une instruction d'insertion ?

Ma question est assez simple. Je connais le concept de l'UUID et je veux en générer un pour faire référence à chaque "article" d'un "magasin" dans ma base de données. Cela semble raisonnable, non ?

Le problème est que la ligne suivante renvoie une erreur :

honeydb=# insert into items values(
uuid_generate_v4(), 54.321, 31, 'desc 1', 31.94);
ERROR:  function uuid_generate_v4() does not exist
LINE 2: uuid_generate_v4(), 54.321, 31, 'desc 1', 31.94);
        ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

J'ai lu la page à : http://www.postgresql.org/docs/current/static/uuid-ossp.html

enter image description here

J'utilise Postgres 8.4 sur Ubuntu 10.04 x64.

13 votes

Postgres supporte nativement UUID comme un type de données, même capable d'être indexé et utilisé comme clé primaire. Mais pour générer une valeur UUID, par exemple pour établir une valeur par défaut pour une colonne, vous avez besoin d'une extension Postgres (un plugin). De nombreux builds (distributions) de Postgres incluent une telle extension mais ne l'activent pas. Voir la page réponse correcte de Craig Ringer pour apprendre comment l'activer.

2 votes

Si vous avez installé uuid-ossp et que vous obtenez toujours cette erreur, essayez de préfixer la fonction avec le nom de votre schéma, par exemple. select dbo.uuid_generate_v4()

585voto

Craig Ringer Points 72371

uuid-ossp est un module contributif, il n'est donc pas chargé par défaut dans le serveur. Vous devez le charger dans votre base de données pour l'utiliser.

Pour les versions modernes de PostgreSQL (9.1 et plus récentes), c'est facile :

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

mais pour les versions 9.0 et inférieures, vous devez plutôt exécuter le script SQL pour charger l'extension. Voir la documentation des modules de contribution en 8.4 .

Pour les Pg 9.1 et plus récents, lire plutôt les documents actuels de contrib y CREATE EXTENSION . Ces fonctionnalités n'existent pas dans la version 9.0 ou les versions plus anciennes, comme votre 8.4.

Si vous utilisez une version packagée de PostgreSQL, vous devrez peut-être installer un paquet séparé contenant les modules contrib et les extensions. Recherchez 'postgres' et 'contrib' dans la base de données de votre gestionnaire de paquets.

0 votes

Je suis censé taper : pg_config --sharedir pour trouver mon répertoire partagé afin d'importer le module mais la commande ne fonctionne ni dans le shell ni dans l'invite de commande psql.

0 votes

J'ai donc dû exécuter sudo apt-get install libpq-dev afin d'exécuter pg_config --sharedir mais maintenant je n'ai pas de dossier 'contrib' dans mon sharedir qui est supposé exister selon la directive postgresql.org/docs/8.4/static/contrib.html

7 votes

@advocate Vous utilisez un paquetage distro de PostgreSQL, vous devriez donc être en mesure de juste apt-get install postgresql-contrib ou similaire. Essayez apt-cache search postgresql |grep contrib pour trouver le nom du paquet que vous voulez.

435voto

ZuzEL Points 1003

Sans extensions (tricherie)

SELECT uuid_in(md5(random()::text || clock_timestamp()::text)::cstring);

output>> c2d29867-3d0b-d497-9191-18a9d8ee7830

(fonctionne au moins en 8.4)

  • Merci à @Erwin Brandstetter pour clock_timestamp() l'explication.

Si vous avez besoin d'un UUID v4 valide

SELECT uuid_in(overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing to_hex(floor(random()*(11-8+1) + 8)::int)::text from 17)::cstring);

enter image description here * Merci à Denis Stafichuk @Karsten y @autronix


De plus, dans les Postgres modernes, vous pouvez simplement lancer :

SELECT md5(random()::text || clock_timestamp()::text)::uuid

1 votes

Est-ce mieux que uuid-ossp ? uuid_in semble renvoyer les mêmes sorties pour des entrées identiques. Donc, si vous l'utilisez pour créer deux UUIDs au même moment exact (ou avec les mêmes résultats à partir de random() ), ils seront égaux.

6 votes

Pour faire suite à votre PS : SELECT uuid_in(md5(random()::text || now()::text)::cstring);

5 votes

@MattDiPasquale Probablement pas en aucun cas "mieux" que d'utiliser uuid-ossp Mais je travaille par exemple sur une instance PostgreSQL où je n'ai pas les privilèges suffisants pour installer une extension.

98voto

Basil Bourque Points 8938

El réponse de Craig Ringer est correcte. Voici un peu plus d'informations pour Postgres 9.1 et plus

L'extension est-elle disponible ?

Vous ne pouvez installer une extension que si elle a déjà été construite pour votre installation Postgres (votre fichier cluster dans le jargon de Postgres). Par exemple, j'ai trouvé le uuid-ossp inclus dans le programme d'installation pour Mac OS X aimablement fourni par par EnterpriseDB.com. L'un des quelques dizaines d'extensions peuvent être disponibles.

Pour voir si le uuid-ossp est disponible dans votre cluster Postgres, exécutez ce SQL pour interroger l'extension pg_available_extensions catalogue du système :

SELECT * FROM pg_available_extensions;

Installer l'extension

Pour installer ce UUID -utilisez l'option CRÉER UNE EXTENSION comme on le voit dans ce SQL :

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Attention : J'ai trouvé que les caractères de la marque de citation autour du nom de l'extension étaient nécessaires, malgré une documentation contraire.

Le comité des normes SQL ou l'équipe Postgres a choisi un nom étrange pour cette commande. À mon avis, ils auraient dû choisir quelque chose comme "INSTALL EXTENSION" ou "USE EXTENSION".

Vérifier l'installation

Vous pouvez vérifier que l'extension a été installée avec succès dans la base de données souhaitée en exécutant ce SQL pour interroger la base de données de l'extension. pg_extension catalogue du système :

SELECT * FROM pg_extension;

UUID comme valeur par défaut

Pour plus d'informations, voir la Question : Valeur par défaut pour la colonne UUID dans Postgres

L'ancienne méthode

L'information ci-dessus utilise la nouvelle Extensions fonctionnalité ajouté à Postgres 9.1. Dans les versions précédentes, nous devions trouver et exécuter un script dans un fichier .sql fichier. La fonction Extensions a été ajoutée pour faciliter l'installation, en échangeant un peu plus de travail pour l'équipe de l créateur d'une extension pour moins de travail de la part de l'utilisateur/consommateur de l'extension. Voir mon article de blog pour plus de discussion.

Types d'UUIDs

D'ailleurs, le code dans la Question appelle la fonction uuid_generate_v4() . Cela génère un type connu sous le nom de Version 4 où presque tous les 128 bits sont générés de façon aléatoire. Bien que cela convienne à une utilisation limitée à un petit nombre de lignes, si vous voulez éliminer pratiquement toute possibilité de collision, utilisez une autre "version" de l'UUID.

Par exemple, l'original Version 1 combine le Adresse MAC de l'ordinateur hôte avec la date et l'heure actuelles et un nombre arbitraire, les chances de collisions sont pratiquement nulles.

Pour plus de détails, voir ma réponse sur les questions connexes.

1 votes

Et vous pouvez également utiliser CREATE EXTENSION IF NOT EXISTS ... si vous n'êtes pas sûr et ne voulez pas vérifier (dans un script par exemple)

4 votes

Les UUID de la version 4 conviennent à presque toutes les tailles d'ensembles de données, et pas seulement à une "utilisation limitée à de petits ensembles de lignes". Il faudrait générer 1 milliard d'UUID par seconde pendant environ 85 ans (ou environ 45 millions de téraoctets de données, soit des milliers de fois plus que les plus grandes bases de données actuelles) pour avoir ne serait-ce que 50 % de chances de collision. À moins que vous ne soyez la NSA, la version 4 convient à peu près à tous les usages. La version 1, en revanche, souffrait du fait que les adresses MAC sont attribuées de manière séquentielle (et sont souvent usurpées ou indisponibles), ce qui explique en partie l'introduction des versions ultérieures.

0 votes

@Jazz Je ne vois pas en quoi les MACs attribués séquentiellement ou les MACs usurpés sont pertinents pour générer des UUIDs. A moins qu'un MAC que vous utilisiez ne soit usurpé sur une autre machine dans le même contexte où vous utilisez les UUIDs, le MAC usurpé n'est pas pertinent.

85voto

lad2025 Points 38168

PostgreSQL 13 prend en charge nativement gen_random_uuid () :

PostgreSQL inclut une fonction pour générer un UUID :

gen_random_uuid ()  uuid

Cette fonction renvoie un UUID version 4 (aléatoire). Il s'agit du type d'UUID le plus couramment utilisé et il convient à la plupart des applications.

db<>démonstration

4 votes

Je ne comprends pas pourquoi il y a tant d'autres réponses (qui ne fonctionnent pas), c'est aussi simple que cela ! devrait être la réponse acceptée

5 votes

@pdem car PostgreSQL 13 est assez récent. Par exemple, je travaille toujours sur la version 10 du serveur. Cela semble être la meilleure alternative pour la version 13, cependant.

2 votes

@borellini Je comprends, j'ai en fait un serveur de production en 12, j'ai dû créer cette fonction de patch pour que cela fonctionne. create function gen_random_uuid() RETURNS uuid as $$ SELECT md5(random()::text || clock_timestamp()::text)::uuid $$ LANGUAGE SQL;

81voto

brillout.com Points 2289

pgcrypto Extension

Depuis la version 9.4 de Postgres, l'option pgcrypto comprend le module gen_random_uuid() fonction. Cette fonction génère une des fonctions basées sur des nombres aléatoires. Type d'UUID de la version 4 .

Récupère les modules contrib, s'ils ne sont pas déjà disponibles.

sudo apt-get install postgresql-contrib-9.4

Utilisez pgcrypto module.

CREATE EXTENSION "pgcrypto";

El gen_random_uuid() devrait maintenant être disponible ;

Exemple d'utilisation.

INSERT INTO items VALUES( gen_random_uuid(), 54.321, 31, 'desc 1', 31.94 ) ;

Citation de Documentation Postgres sur uuid-ossp module.

Remarque : si vous n'avez besoin que d'UUID générés de manière aléatoire (version 4), envisagez d'utiliser la fonction gen_random_uuid() du module pgcrypto à la place.

3 votes

Oui, mais voir aussi blog.starkandwayne.com/2015/05/23/ où ils mettent en garde contre la fragmentation et suggèrent uuid-ossp à la place.

4 votes

En fait, voir postgresql.org/message-id/ où le problème de fragmentation des uuid dans Postgres est démystifié.

0 votes

Mais Postgres dispose d'index en grappe dans la dernière version, ce qui rend l'article dont le lien figure dans le commentaire ci-dessus peu concluant et incorrect, et nous sommes de retour à la case départ.

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