Generare un UUID in Postgres per l'istruzione Insert?


368

La mia domanda è piuttosto semplice. Sono a conoscenza del concetto di UUID e desidero generarne uno per fare riferimento a ciascun 'elemento' da un 'archivio' nel mio DB con. Sembra ragionevole vero?

Il problema è che la seguente riga restituisce un errore:

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.

Ho letto la pagina all'indirizzo: http://www.postgresql.org/docs/current/static/uuid-ossp.html

inserisci qui la descrizione dell'immagine

Sto eseguendo Postgres 8.4 su Ubuntu 10.04 x64.


8
Postgres supporta nativamente UUID come tipo di dati, persino in grado di essere indicizzato e utilizzato come chiave primaria. Ma per generare un valore UUID, ad esempio per stabilire un valore predefinito per una colonna, è necessaria un'estensione Postgres (un plug-in). Molte build (distribuzioni) di Postgres includono tale estensione ma non attivano l'estensione. Vedi la risposta corretta di Craig Ringer per sapere come attivarla.
Basil Bourque,

2
Se hai installato uuid-ossp e ricevi ancora questo errore prova a aggiungere il prefisso alla funzione con il nome del tuo schema, ad es.select dbo.uuid_generate_v4()
Richard

Risposte:


435

uuid-osspè un modulo contrib, quindi non è caricato nel server per impostazione predefinita. È necessario caricarlo nel database per usarlo.

Per le moderne versioni PostgreSQL (9.1 e successive) è facile:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

ma per 9.0 e versioni precedenti devi invece eseguire lo script SQL per caricare l'estensione. Vedere la documentazione per i moduli contrib in 8.4 .

Per Pg 9.1 e versioni successive leggi invece i documenti contrib e CREATE EXTENSION. Queste funzionalità non esistono nelle versioni 9.0 o precedenti, come la tua 8.4.

Se stai usando una versione in pacchetto di PostgreSQL, potresti dover installare un pacchetto separato contenente i moduli e le estensioni contrib. Cerca nel database del gestore pacchetti "postgres" e "contrib".


6
@advocate Stai usando un PostgreSQL distribuito in pacchetti distro, quindi dovresti essere in grado di farlo correttamente apt-get install postgresql-contribo in modo simile. Prova apt-cache search postgresql |grep contriba trovare il nome del pacchetto che desideri.
Craig Ringer,

2
sudo apt-get install postgresql-contrib è stato eseguito correttamente. Quindi ho dovuto eseguire psql -d dbname -f SHAREDIR / contrib / module.sql e ora funziona !!! seleziona uuid_generate_v1 (); ora restituisce 1. Grazie mille!
anon58192932

5
Nota che se non installi il postgresql-contribpacchetto, otterrai l'errore: ERRORE: impossibile aprire il file di controllo dell'estensione "/usr/share/postgresql/9.3/extension/uuid-ossp.control": nessun file o directory
Ha disegnato Noakes il

1
Ho pubblicato quel commento quando la stringa di errore è stata cancellata su Google. Inoltre fornisce un nome pacchetto specifico, almeno per Ubuntu.
Drew Noakes,

2
Se hai importato un db che ha già uuid-ossp nelle estensioni, uuid_generate_v4 () potrebbe non funzionare. In tal caso, basta rimuovere l'estensione e crearla di nuovo e dovrebbe funzionare.
Dragos Rusu,

303

Senza estensioni (cheat)

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

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

(funziona almeno in 8.4)

  • Grazie a @Erwin Brandstetter per la clock_timestamp()spiegazione.

Se è necessario un UUID v4 valido

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);

inserisci qui la descrizione dell'immagine * Grazie a @Denis Stafichuk @Karsten e @autronix


Inoltre, nei moderni Postgres, puoi semplicemente lanciare:

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


5
Per seguire il tuo PS: SELEZIONAuuid_in(md5(random()::text || now()::text)::cstring);
Blaskovicz il

4
@MattDiPasquale Probabilmente non è in alcun modo "migliore" dell'uso uuid-ossp, ma ad esempio sto lavorando su un'istanza PostgreSQL in cui non ho i privilegi sufficienti per installare un'estensione.
Stefan Haberl,

25
@JosephLennox: clock_timestamp()è la migliore alternativa in entrambi i casi per questo. A differenza now()o CURRENT_TIMESTAMPè volatile e restituisce l'ora corrente attuale. SELECT uuid_in(md5(random()::text || clock_timestamp()::text)::cstring);Inoltre, nei moderni Postgres puoi semplicemente lanciare: SELECT md5(random()::text || clock_timestamp()::text)::uuid- non c'è bisogno di più magia. Caso d'uso: stackoverflow.com/a/8335376/939860
Erwin Brandstetter

17
No. Se questo funziona affatto, è pura fortuna. un UUID ha un formato, non solo caratteri esadecimali casuali messi insieme. Il primo numero del 3 ° gruppo è la versione uuid per intance (di solito 4 in questi giorni). Se l'applicazione controlla quella cifra per vedere con quale versione di uuid sta trattando e fa qualcosa di conseguenza, fallirà nel tuo codice.
Tuncay Göncüoğlu,

7
@Tuncay Göncüoğlu: è abbastanza semplice generare un UUID v4 valido (l'approccio di sovrapposizione di stringhe spreca comunque 2 bit di casualità):select overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing '8' from 17)::uuid;
Karsten

75

La risposta di Craig Ringer è corretta. Ecco qualche informazione in più per Postgres 9.1 e versioni successive ...

L'estensione è disponibile?

Puoi installare un'estensione solo se è già stata creata per l'installazione di Postgres (il tuo cluster nel gergo di Postgres). Ad esempio, ho trovato l' estensione uuid-ossp inclusa come parte dell'installer per Mac OS X gentilmente fornita da EnterpriseDB.com. È possibile che siano disponibili alcune decine di estensioni .

Per vedere se l' estensione uuid-ossp è disponibile nel cluster Postgres, esegui questo SQL per eseguire una query nel pg_available_extensionscatalogo di sistema:

SELECT * FROM pg_available_extensions;

Installa estensione

Per installare l' estensione relativa a UUID , utilizzare il comando CREATE EXTENSION come mostrato in questo SQL:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Attenzione: ho trovato i caratteri del MARCHIO DI PREVENTIVO intorno al nome dell'estensione, nonostante la documentazione contraria.

Il comitato degli standard SQL o il team di Postgres hanno scelto un nome strano per quel comando. A mio avviso, avrebbero dovuto scegliere qualcosa come "INSTALLA ESTENSIONE" o "UTILIZZA ESTENSIONE".

Verifica installazione

È possibile verificare che l'estensione sia stata installata correttamente nel database desiderato eseguendo questo SQL per eseguire una query nel pg_extensioncatalogo di sistema:

SELECT * FROM pg_extension;

UUID come valore predefinito

Per maggiori informazioni, vedi la domanda: valore predefinito per la colonna UUID in Postgres

The Old Way

Le informazioni sopra riportate utilizzano la nuova funzione di estensione aggiunta a Postgres 9.1. Nelle versioni precedenti, dovevamo trovare ed eseguire uno script in un file .sql . La funzione Estensioni è stata aggiunta per rendere l'installazione più semplice, scambiando un po 'più di lavoro per il creatore di un'estensione per meno lavoro da parte dell'utente / consumatore dell'estensione. Vedi il mio post sul blog per ulteriori discussioni.

Tipi di UUID

A proposito, il codice nella domanda chiama la funzione uuid_generate_v4(). Questo genera un tipo noto come Versione 4 in cui quasi tutti i 128 bit vengono generati casualmente. Sebbene ciò vada bene per un uso limitato su un set di righe più piccolo, se si desidera eliminare virtualmente qualsiasi possibilità di collisione, utilizzare un'altra "versione" di UUID.

Ad esempio, la versione 1 originale combina l' indirizzo MAC del computer host con la data-ora corrente e un numero arbitrario, la possibilità di collisioni è praticamente nulla.

Per ulteriori discussioni, vedere la mia risposta sulla domanda correlata.


1
E puoi anche usarlo CREATE EXTENSION IF NOT EXISTS ...se non sei sicuro e non vuoi controllare (in uno script per esempio)
Uwe Allner

2
Gli UUID versione 4 vanno bene per quasi tutti i set di dati di dimensioni, non solo "uso limitato su set di righe più piccoli". Dovresti generare 1 miliardo di UUID al secondo per circa 85 anni (o circa 45 milioni di terabyte di dati, migliaia di volte più grandi dei database più grandi di oggi) per avere anche il 50% di possibilità di collisione. A meno che tu non sia la NSA, la versione 4 va bene per qualsiasi scopo. La versione 1, d'altra parte, soffriva del fatto che gli indirizzi MAC sono assegnati in sequenza (e spesso sono falsificati o non disponibili), il che è parte del motivo per cui sono state introdotte versioni successive.
Jazz

1
@BasilBourque Il problema con v1 non è la probabilità di collisione se implementato correttamente, è la probabilità di un'implementazione errata. Come afferma Wikipedia: "L'unicità degli UUID versione 1 e 2 ... dipende anche dal fatto che i produttori di schede di rete assegnano correttamente indirizzi MAC univoci alle loro schede, che come altri processi di produzione sono soggetti ad errori". Inoltre, in alcuni ambienti containerizzati o virtualizzati, gli indirizzi MAC reali dall'hardware sottostante non sono disponibili. Se molti contenitori hanno lo stesso MAC ma i propri contatori clockseq, i loro UUID v1 potrebbero scontrarsi.
Jazz

1
@BasilBourque I punti deboli della v1 non sono il punto principale del mio commento. La tua risposta originale implica che v4 non è adatto per grandi set di dati a causa di una maggiore probabilità di collisione rispetto a v1. Questo è fuorviante e forse falso, sebbene sia difficile calcolare la probabilità di collisione per v1 perché è così dipendente dall'implementazione.
Jazz

1
@BasilBourque Ad esempio, il progetto node-uuid calcola la probabilità che i loro contatori clockseq siano gli stessi (in modo che due processi generino la stessa sequenza di UUID v1) come 1 in 4.6e18. Questo è piccolo, sì, ma molto più probabile della possibilità di una collisione immediata in v4, che è 1 in 5.3e36. Ovviamente, più a lungo si generano UUID v4, più è probabile che si verifichi una collisione, il che non è vero per la v1, ma è necessario generare 1,52 miliardi di UUID v4 prima che la probabilità di collisione superi quella dell'implementazione v1 del nodo. La maggior parte delle persone non ha 1,52 miliardi di record per tabella.
Jazz

61

pgcrypto Estensione

A partire da Postgres 9.4, il pgcryptomodulo include la gen_random_uuid()funzione. Questa funzione genera uno del tipo di UUID versione 4 basato su numeri casuali .

Ottieni moduli contrib, se non già disponibili.

sudo apt-get install postgresql-contrib-9.4

Usa il pgcryptomodulo.

CREATE EXTENSION "pgcrypto";

La gen_random_uuid()funzione dovrebbe ora essere disponibile;

Esempio di utilizzo.

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


Citazione dal documento Postgres suluuid-ossp modulo.

Nota: se hai solo bisogno di UUID generati casualmente (versione 4), considera invece di utilizzare la funzione gen_random_uuid () dal modulo pgcrypto.


3
Sì, ma vedi anche blog.starkandwayne.com/2015/05/23/… dove avvertono della frammentazione e suggeriscono invece uuid-ossp.
Malik A. Rumi,

3
In realtà, vedi postgresql.org/message-id/… in cui viene risolto il problema della frammentazione degli uuidi in Postgres
Bob Kocisko,

Ma postgres ha indici raggruppati nell'ultima versione, rendendo il post collegato nel commento sopra inconcludente e errato e torniamo al punto 1
Michael Goldshteyn,

1
@MichaelGoldshteyn: no, Postgres non ha indici cluster (a partire da Postgres 12)
a_horse_with_no_name

3
ALTER TABLE table_name ALTER COLUMN id SET DEFAULT uuid_in((md5((random())::text))::cstring);

Dopo aver letto la risposta di @ ZuzEL, ho usato il codice sopra come valore predefinito dell'ID colonna e funziona bene.


1

I prossimi PostgreSQL 13 supporteranno nativamente gen_random_uuid () senza la necessità di abilitare alcuna estensione:

PostgreSQL include una funzione per generare un UUID:

gen_random_uuid ()  uuid

Questa funzione restituisce un UUID versione 4 (casuale). Questo è il tipo di UUID più comunemente usato ed è appropriato per la maggior parte delle applicazioni.

db <> demo violino

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.