Postgres for Insert deyiminde bir UUID oluşturuluyor mu?


368

Sorum oldukça basit. Bir UUID kavramının farkındayım ve her bir 'eşyaya' DB'mdeki bir 'mağazadan' atıfta bulunmak için bir tane oluşturmak istiyorum. Makul görünüyor değil mi?

Sorun şu satırda bir hata döndürür:

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.

Sayfayı şu adreste okudum: http://www.postgresql.org/docs/current/static/uuid-ossp.html

resim açıklamasını buraya girin

Ubuntu 10.04 x64 üzerinde Postgres 8.4 kullanıyorum.


8
Postgres, UUID'yi bir veri türü olarak yerel olarak destekler , hatta birincil anahtar olarak dizine eklenip kullanılabilir. Ancak , bir sütun için varsayılan bir değer oluşturmak gibi bir UUID değeri oluşturmak için Postgres uzantısına (eklenti) ihtiyacınız vardır. Postgres'in birçok derlemesi (dağıtımları) böyle bir uzantı içerir ancak uzantıyı etkinleştirmez. Nasıl etkinleştireceğinizi öğrenmek için Craig Ringer'in doğru cevabına bakın .
Basil Bourque

2
Uuid-ossp yüklüyse ve hala bu hatayı alıyorsanız, işlevi şema adınızla öneklemeyi deneyin, örn.select dbo.uuid_generate_v4()
Richard

Yanıtlar:


435

uuid-osspkatkıda bulunan bir modüldür, bu nedenle varsayılan olarak sunucuya yüklenmez. Kullanmak için veritabanınıza yüklemelisiniz.

Modern PostgreSQL sürümleri (9.1 ve daha yeni) için bu kolay:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

ancak 9.0 ve altı sürümler için uzantıyı yüklemek için SQL komut dosyasını çalıştırmalısınız. 8.4'teki katkı modülleri için belgelere bakın .

Pg 9.1 ve daha yeni sürümler için geçerli katkı belgelerini ve CREATE EXTENSION. Bu özellikler, 8.4 sürümünüz gibi 9.0 veya daha eski sürümlerde mevcut değildir.

PostgreSQL'in paketlenmiş bir sürümünü kullanıyorsanız, katkıda bulunan modülleri ve uzantıları içeren ayrı bir paket kurmanız gerekebilir. Paket yöneticisi veritabanınızda 'postgres' ve 'katkıda bulun' için arama yapın.


6
@advocate Distro-paketlenmiş bir PostgreSQL kullanıyorsunuz apt-get install postgresql-contrib. apt-cache search postgresql |grep contribİstediğiniz paket adını bulmaya çalışın .
Craig Ringer

2
sudo apt-get install postgresql-katkıda başarıyla çalıştı. Sonra psql -d dbname -f SHAREDIR / antrenman / module.sql çalıştırmak zorunda kaldı ve şimdi çalışıyor !!! uuid_generate_v1 () öğesini seçin; şimdi 1 döndürüyor. Çok teşekkürler!
anon58192932

5
postgresql-contribPaketi yüklemezseniz hatayı alırsınız: HATA: "/usr/share/postgresql/9.3/extension/uuid-ossp.control" uzantı denetim dosyasını açamadı: Böyle bir dosya veya dizin yok
Drew Noakes

1
Bu yorumu, Google'da hata dizesi çıktığı için yayınladım. Ayrıca en azından Ubuntu için belirli bir paket adı verir.
Drew Noakes

2
Zaten Uzantılar'da uuid-ossp olan bir db'yi içe aktardıysanız, uuid_generate_v4 () çalışmayabilir. Durum buysa, uzantıyı kaldırın ve tekrar oluşturun ve çalışması gerekir.
Dragos Rusu

302

Uzantısız (hile)

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

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

(en az 8.4 sürümde çalışır)

  • @Erwin Brandstetter'e clock_timestamp()açıklama için teşekkürler .

Geçerli bir v4 UUID'ye ihtiyacınız varsa

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

resim açıklamasını buraya girin * @Denis Stafichuk @Karsten ve @autronix sayesinde


Ayrıca, modern Postgres'te şunları yapabilirsiniz:

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


5
PS'nizi takip etmek için: SELECTuuid_in(md5(random()::text || now()::text)::cstring);
Blaskovicz

4
@MattDiPasquale Muhtemelen herhangi bir anlamda "kullanmaktan daha iyi" değil uuid-ossp, ama örneğin bir uzantı yüklemek için yeterli ayrıcalıklara sahip değilim PostgreSQL örneği üzerinde çalışıyorum.
Stefan Haberl

25
@ Josephephennox: Bunun clock_timestamp()için her iki durumda da daha iyi bir alternatiftir. Bunun aksine now()veya CURRENT_TIMESTAMPuçucudur ve gerçek geçerli saati döndürür. SELECT uuid_in(md5(random()::text || clock_timestamp()::text)::cstring);Ayrıca, modern Postgres'de şunları yapabilirsiniz: SELECT md5(random()::text || clock_timestamp()::text)::uuid- daha fazla sihire gerek yok. Kullanım örneği: stackoverflow.com/a/8335376/939860
Erwin Brandstetter

17
Hayır! Eğer bu işe yaramıyorsa, tamamen şanslı. bir UUID, sadece rastgele hex karakterleri bir arada değil, bir formata sahiptir. 3. grubun ilk sayısı, intance için uuid versiyonudur (genellikle bu günlerde 4). Uygulamanız, hangi uuid sürümünün ele alındığını görmek için bu basamağı kontrol ederse ve buna göre bir şey yaparsa, kodunuzda başarısız olur.
Tuncay Göncüoğlu

7
@Tuncay Göncüoğlu: Geçerli bir v4 UUID oluşturmak oldukça basittir (dize kaplaması yaklaşımı 2 bit rasgelelik harcıyor):select overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing '8' from 17)::uuid;
Karsten

75

Craig Ringer tarafından cevap doğrudur. İşte Postgres 9.1 ve sonrası için biraz daha bilgi…

Uzantı Var mı?

Zaten senin Postgres kurulumu (sizin için inşa edilmiş, yalnızca bir uzantı yükleyebilir küme Postgres lingo). Örneğin, uuid-ossp uzantısını EnterpriseDB.com tarafından sağlanan Mac OS X yükleyicisinin bir parçası olarak buldum . Bir Herhangi birkaç düzine uzantıları bulunabilir.

Uuid-ossp uzantısının Postgres kümenizde kullanılabilir olup olmadığını görmek için, pg_available_extensionssistem kataloğunu sorgulamak için şu SQL'i çalıştırın :

SELECT * FROM pg_available_extensions;

Uzantısı yükleyin

Bu UUID ile ilişkili uzantıyı yüklemek için , bu SQL'de görüldüğü gibi CREATE EXTENSION komutunu kullanın :

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Dikkat: Aksi belgelere rağmen, uzantı adı etrafında QUOTATION MARK karakterlerini gerekli buldum.

SQL standartları komitesi veya Postgres ekibi bu komut için tek bir ad seçti. Bana göre, "UZATMA YÜKLE" veya "UZATMA KULLAN" gibi bir şey seçmelilerdi.

Yüklemeyi Doğrula

pg_extensionSistem kataloğunu sorgulamak için bu SQL'i çalıştırarak uzantının istenen veritabanına başarıyla yüklendiğini doğrulayabilirsiniz :

SELECT * FROM pg_extension;

Varsayılan değer olarak UUID

Daha fazla bilgi için, Soru: Postgres'te UUID sütunu için varsayılan değer konusuna bakın.

Eski Yol

Yukarıdaki bilgiler Postgres 9.1'e eklenen yeni Uzantılar özelliğini kullanmaktadır . Önceki sürümlerde, bir .sql dosyasında bir komut dosyası bulup çalıştırmamız gerekiyordu . Uzantıları yükleme işlemini kolaylaştırmak için eklenti kullanıcısı / tüketicisi tarafında daha az çalışma yapmak üzere bir uzantıyı oluşturan kişi için biraz daha fazla işlem yapmak amacıyla eklenmiştir . Daha fazla tartışma için blog gönderime bakın .

UUID Türleri

Bu arada, Soru'daki kod işlevi çağırır uuid_generate_v4(). Bu , 128 bitin neredeyse tamamının rastgele oluşturulduğu Sürüm 4 olarak bilinen bir tür oluşturur. Bu, daha küçük satır kümelerinde sınırlı kullanım için iyi olsa da, herhangi bir çarpışma olasılığını neredeyse ortadan kaldırmak istiyorsanız, UUID'nin başka bir "sürümünü" kullanın.

Örneğin, orijinal Sürüm 1 birleştirir MAC adresi geçerli tarih-zaman ana bilgisayarın ve keyfi bir sayı, çakışması olasılığı hemen hemen sıfırdır.

Daha fazla tartışma için, ilgili Soruya verilen cevabım bölümüne bakın .


1
Ayrıca CREATE EXTENSION IF NOT EXISTS ...emin değilseniz ve kontrol etmek istemiyorsanız da kullanabilirsiniz (örneğin bir senaryoda)
Uwe Allner

2
Sürüm 4 UUID'ler, yalnızca "daha küçük satır kümelerinde sınırlı kullanım" için değil, hemen hemen her boyuttaki veri kümesi için uygundur. % 50'lik bir çarpışma şansına sahip olmak için yaklaşık 85 yıl boyunca saniyede 1 milyar UUID oluşturmanız (veya yaklaşık 45 milyon terabayt veri, bugünün en büyük veritabanlarından binlerce kat daha büyük) üretmeniz gerekir. NSA değilseniz, Sürüm 4 herhangi bir amaç için uygundur. Öte yandan, sürüm 1, MAC adreslerinin ardışık olarak atandığından (ve genellikle sahte veya kullanılamıyor), bu da sonraki sürümlerin neden sunulduğunun bir parçasıydı.
Jazz

1
@BasilBourque v1 ile ilgili sorun doğru uygulandığında çarpışma olasılığı değil, yanlış uygulama olasılığıdır. Wikipedia'nın belirttiği gibi: "Sürüm 1 ve 2 UUID'lerin benzersizliği ... aynı zamanda, diğer üretim süreçleri gibi hataya tabi olan kartlarına benzersiz MAC adresleri düzgün atanan ağ kartı üreticilerine de bağlıdır." Ayrıca, bazı kapsayıcı veya sanallaştırılmış ortamlarda, temel donanımdan gerçek MAC adresleri kullanılamaz. Birçok kap aynı MAC'a ancak kendi saat sayacı sayaçlarına sahipse, v1 UUID'leri çarpışabilir.
Jazz

1
@BasilBourque v1'deki zayıf yönler yorumumun ana noktası değil. Orijinal cevabınız, v4'ün, v1'den daha yüksek çarpışma olasılığı nedeniyle büyük veri kümeleri için uygun olmadığını ima eder. Bu yanıltıcı ve muhtemelen yanlıştır, ancak v1 için çarpışma olasılığını hesaplamak zordur çünkü uygulamaya çok bağlıdır.
Jazz

1
@BasilBourque Örneğin, düğüm-uuid projesi, saat sehpası sayaçlarının aynı olma olasılığını hesaplar (böylece iki işlem, 4.6e18'de 1 ile aynı v1 UUID dizisini oluşturur). Bu küçük, evet, ancak 5.3e36'da 1 olan v4'te hemen çarpışma olasılığından çok daha fazla. Açıkçası, v4 UUID'leri ne kadar uzun süre üretirseniz, bir çarpışma olasılığı o kadar artar, bu da v1 için doğru değildir, ancak çarpışma olasılığı düğümün v1 uygulamasınınkini aşmadan önce 1.52 milyar v4 UUID oluşturmanız gerekir. Çoğu insanın masa başına 1.52 milyar kaydı yoktur.
Jazz

61

pgcrypto Uzantı

Postgres 9.4'ten itibaren pgcryptomodül bu gen_random_uuid()işlevi içermektedir . Bu işlev, rastgele sayı tabanlı Sürüm 4 tip UUID'den birini oluşturur .

Henüz mevcut değilse katkıda bulunan modülleri alın.

sudo apt-get install postgresql-contrib-9.4

pgcryptoModülü kullanın .

CREATE EXTENSION "pgcrypto";

gen_random_uuid()Fonksiyon gerektiği anda mevcut;

Örnek kullanım.

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


Modülde Postgres doc'denuuid-ossp alıntı .

Not: Yalnızca rastgele oluşturulmuş (sürüm 4) UUID'lere ihtiyacınız varsa, bunun yerine pgcrypto modülünden gen_random_uuid () işlevini kullanmayı düşünün.


3
Evet, ama aynı zamanda bkz. Blog.starkandwayne.com/2015/05/23/… parçalanma konusunda uyarıyor ve bunun yerine uuid-ossp öneriyorlar.
Malik

3
Aslında, Postgres'deki uuid parçalanma sorununun
reddedildiği

Ancak postgres, en son sürümde kümelenmiş dizinlere sahip, yukarıdaki
yorumdaki gönderiyi

1
@MichaelGoldshteyn: hayır Postgrees yok değil (Postgres 12 itibariyle) kümelenmiş olan endeksler
a_horse_with_no_name

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

@ ZuzEL'in cevabını okuduktan sonra, yukarıdaki kodu sütun kimliğinin varsayılan değeri olarak kullandım ve iyi çalışıyor.


1

Yaklaşan PostgreSQL 13, herhangi bir uzantıyı etkinleştirmeye gerek kalmadan yerel olarak gen_random_uuid () yöntemini destekleyecektir :

PostgreSQL, bir UUID oluşturmak için bir işlev içerir:

gen_random_uuid ()  uuid

Bu işlev sürüm 4 (rastgele) UUID değerini döndürür. Bu, en yaygın kullanılan UUID türüdür ve çoğu uygulama için uygundur.

db <> keman demosu

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.