สร้าง UUID ใน Postgres สำหรับคำสั่งแทรก?


367

คำถามของฉันค่อนข้างง่าย ฉันตระหนักถึงแนวคิดของ UUID และฉันต้องการสร้างขึ้นเพื่ออ้างถึง 'รายการ' แต่ละรายการจาก 'ร้านค้า' ในฐานข้อมูลของฉันด้วย ดูเหมือนว่าเหมาะสมใช่ไหม

ปัญหาคือบรรทัดต่อไปนี้ส่งคืนข้อผิดพลาด:

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.

ฉันอ่านหน้านี้แล้วที่: http://www.postgresql.org/docs/current/static/uuid-ossp.html

ป้อนคำอธิบายรูปภาพที่นี่

ฉันใช้งาน Postgres 8.4 บน Ubuntu 10.04 x64


8
Postgres สนับสนุนUUIDในรูปแบบของข้อมูลได้เป็นอย่างดีแม้สามารถทำดัชนีและใช้เป็นคีย์หลักได้ แต่ในการสร้างค่า UUID เช่นการสร้างค่าเริ่มต้นสำหรับคอลัมน์คุณต้องมีส่วนเสริม Postgres (ปลั๊กอิน) บิวด์ (การกระจาย) จำนวนมากของ Postgres มีส่วนขยายดังกล่าว แต่ไม่เปิดใช้งานส่วนขยาย ดูคำตอบที่ถูกต้องโดย Craig Ringerเพื่อเรียนรู้วิธีเปิดใช้งาน
Basil Bourque

2
ถ้าคุณได้ uuid-ossp ติดตั้งและคุณยังได้รับข้อผิดพลาดนี้ลอง prefixing ฟังก์ชั่นที่มีชื่อสคีของคุณเช่นselect dbo.uuid_generate_v4()
ริชาร์ด

คำตอบ:


435

uuid-osspเป็นโมดูล contrib ดังนั้นจึงไม่โหลดลงในเซิร์ฟเวอร์ตามค่าเริ่มต้น คุณต้องโหลดลงในฐานข้อมูลของคุณเพื่อใช้งาน

สำหรับเวอร์ชัน PostgreSQL ที่ทันสมัย ​​(9.1 ขึ้นไป) ที่ง่าย:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

แต่สำหรับ 9.0 และต่ำกว่าคุณต้องรันสคริปต์ SQL เพื่อโหลดส่วนขยายแทน ดูเอกสารสำหรับโมดูล contrib ใน 8.4

สำหรับหน้า 9.1 และใหม่กว่าแทนอ่านเอกสาร contrib ปัจจุบันCREATE EXTENSIONและ คุณสมบัติเหล่านี้ไม่มีในเวอร์ชั่น 9.0 หรือเก่ากว่าเช่น 8.4 ของคุณ

หากคุณใช้ PostgreSQL รุ่นที่บรรจุคุณอาจต้องติดตั้งแพคเกจแยกต่างหากที่มีโมดูล contrib และส่วนขยาย ค้นหาฐานข้อมูลตัวจัดการแพ็กเกจของคุณสำหรับ 'postgres' และ 'contrib'


6
@advocate คุณกำลังใช้ PostgreSQL แบบ distro-packaged ดังนั้นคุณควรจะสามารถทำได้apt-get install postgresql-contribหรือคล้ายกัน ลองapt-cache search postgresql |grep contribค้นหาชื่อแพ็คเกจที่คุณต้องการ
Craig Ringer

2
sudo apt-get install postgresql-contrib ได้สำเร็จแล้ว จากนั้นฉันก็ต้องเรียกใช้ psql -d dbname -f SHAREDIR / contrib / module.sql และตอนนี้มันใช้งานได้ !!! เลือก uuid_generate_v1 (); ส่งคืน 1 ตอนนี้ ขอบคุณมาก!
anon58192932

5
โปรดทราบว่าหากคุณไม่ได้ติดตั้งpostgresql-contribแพคเกจคุณจะได้รับข้อผิดพลาด: ข้อผิดพลาด: ไม่สามารถเปิดไฟล์ควบคุมส่วนขยาย "/usr/share/postgresql/9.3/extension/uuid-ossp.control": ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
Drew Noakes

1
ฉันโพสต์ความคิดเห็นนั้นเป็นสตริงข้อผิดพลาดที่เกิดขึ้นบน Google นอกจากนี้ยังให้ชื่อแพ็คเกจเฉพาะสำหรับ Ubuntu อย่างน้อย
Drew Noakes

2
หากคุณนำเข้าฐานข้อมูลที่มี uuid-ossp ในส่วนขยายอยู่แล้ว uuid_generate_v4 () อาจไม่ทำงาน หากเป็นเช่นนั้นให้ลบส่วนขยายออกแล้วสร้างใหม่อีกครั้งและควรใช้งานได้
Dragos Rusu

302

ไม่มีส่วนขยาย (โกง)

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

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

(ทำงานอย่างน้อยใน 8.4)

  • ขอบคุณ @Erwin Brandstetter สำหรับclock_timestamp()คำอธิบาย

หากคุณต้องการ v4 UUID ที่ถูกต้อง

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

ป้อนคำอธิบายรูปภาพที่นี่ * ขอบคุณ@Denis Stafichuk @Karstenและ@autronix


นอกจากนี้ใน Postgres สมัยใหม่คุณสามารถเลือก:

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


5
วิธีติดตาม PS ของคุณ: เลือกuuid_in(md5(random()::text || now()::text)::cstring);
Blaskovicz

4
@MattDiPasquale อาจจะไม่ดีกว่า "ใช้uuid-ossp" แต่ฉันใช้อินสแตนซ์ที่ทำงานบนอินสแตนซ์ PostgreSQL ที่ฉันไม่มีสิทธิ์เพียงพอในการติดตั้งส่วนขยาย
Stefan Haberl

25
@JosephLennox: clock_timestamp()เป็นทางเลือกที่ดีกว่าในกรณีนี้ ต่างจากnow()หรือCURRENT_TIMESTAMPผันผวนและคืนค่าเวลาปัจจุบันตามจริง SELECT uuid_in(md5(random()::text || clock_timestamp()::text)::cstring);นอกจากนี้ใน Postgres สมัยใหม่คุณสามารถส่ง: SELECT md5(random()::text || clock_timestamp()::text)::uuid- ไม่จำเป็นต้องใช้เวทมนตร์มากขึ้น กรณีการใช้งาน: stackoverflow.com/a/8335376/939860
Erwin Brandstetter

17
Nope ถ้ามันใช้ได้ผลกับโชคที่แท้จริง UUID มีรูปแบบไม่ใช่แค่ตัวอักษรฐานสิบหกแบบสุ่มที่ถูกโยนเข้าด้วยกันหมายเลขแรกของกลุ่มที่ 3 คือเวอร์ชัน uuid สำหรับการแสดง (ปกติ 4 วันนี้) หากแอปพลิเคชันของคุณตรวจสอบตัวเลขนั้นเพื่อดูเวอร์ชันของ uuid ที่เกี่ยวข้องกับมันและทำบางสิ่งตามนั้นมันจะล้มเหลวในรหัสของคุณ
Tuncay Göncüoğlu

7
@Tuncay Göncüoğlu: มันค่อนข้างตรงไปตรงมาในการสร้าง v4 UUID ที่ถูกต้อง (วิธีการโอเวอร์เลย์ของสตริงทำให้เสียการสุ่ม 2 บิต):select overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing '8' from 17)::uuid;
Karsten

75

คำตอบโดยเครก Ringerถูกต้อง นี่คือข้อมูลเพิ่มเติมเล็กน้อยสำหรับ Postgres 9.1 และใหม่กว่า ...

นามสกุลใช้ได้หรือไม่

คุณสามารถติดตั้งส่วนขยายได้หากสร้างไว้แล้วสำหรับการติดตั้ง Postgres ของคุณ ( คลัสเตอร์ของคุณใน Postgres lingo) ตัวอย่างเช่นฉันพบส่วนขยายuuid-ossp ที่รวมเป็นส่วนหนึ่งของโปรแกรมติดตั้งสำหรับ Mac OS X กรุณาระบุโดย EnterpriseDB.com ส่วนขยายใด ๆไม่กี่โหลอาจใช้ได้

หากต้องการดูว่าส่วนขยายuuid-osspมีอยู่ในคลัสเตอร์ Postgres ของคุณหรือไม่ให้เรียกใช้ SQL นี้เพื่อสืบค้นpg_available_extensionsแค็ตตาล็อกระบบ:

SELECT * FROM pg_available_extensions;

ติดตั้งส่วนขยาย

ในการติดตั้งส่วนขยายที่เกี่ยวข้องกับUUIDนั้นให้ใช้คำสั่งCREATE EXTENSIONตามที่เห็นใน SQL นี้:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

ระวัง:ฉันพบอักขระเครื่องหมายคำพูดรอบชื่อส่วนขยายที่จำเป็นแม้ว่าจะมีเอกสารกำกับตรงกันข้าม

คณะกรรมการมาตรฐาน SQL หรือทีม Postgres เลือกชื่อแปลก ๆ สำหรับคำสั่งนั้น สำหรับความคิดของฉันพวกเขาควรเลือกบางสิ่งเช่น "ติดตั้งส่วนขยาย" หรือ "ใช้ส่วนขยาย"

ตรวจสอบการติดตั้ง

คุณสามารถตรวจสอบว่าติดตั้งส่วนขยายสำเร็จแล้วในฐานข้อมูลที่ต้องการโดยเรียกใช้ SQL นี้เพื่อสอบถามpg_extensionแคตตาล็อกระบบ:

SELECT * FROM pg_extension;

UUID เป็นค่าเริ่มต้น

สำหรับข้อมูลเพิ่มเติมดูคำถาม: ค่าเริ่มต้นสำหรับคอลัมน์ UUID ใน Postgres

วิธีเก่า ๆ

ข้อมูลข้างต้นใช้คุณสมบัติส่วนขยายใหม่ที่เพิ่มใน Postgres 9.1 ในเวอร์ชันก่อนหน้าเราต้องค้นหาและเรียกใช้สคริปต์ในไฟล์. sql คุณลักษณะส่วนขยายได้รับการเพิ่มเพื่อให้การติดตั้งง่ายขึ้นซื้อขายงานอีกเล็กน้อยสำหรับผู้สร้างส่วนขยายสำหรับการทำงานน้อยลงในส่วนของผู้ใช้ / ผู้บริโภคของส่วนขยาย ดูโพสต์บล็อกของฉันสำหรับการสนทนาเพิ่มเติม

ประเภทของ UUIDs

uuid_generate_v4()โดยวิธีการที่รหัสในคำถามที่เรียกฟังก์ชั่น สิ่งนี้สร้างประเภทที่เรียกว่าเวอร์ชัน 4ซึ่งเกือบ 128 บิตทั้งหมดจะถูกสร้างแบบสุ่ม แม้ว่าสิ่งนี้จะใช้ได้ดีสำหรับการใช้งานที่ จำกัด ในชุดของแถวที่มีขนาดเล็กลงหากคุณต้องการขจัดความเป็นไปได้ของการชนให้ใช้ UUID "version" อื่น

ตัวอย่างเช่นเวอร์ชันดั้งเดิม1รวมที่อยู่ MACของโฮสต์คอมพิวเตอร์กับวันที่และเวลาปัจจุบันตามอำเภอใจโอกาสของการชนจะไม่มีจริง

สำหรับการสนทนาเพิ่มเติมดูคำตอบของฉันในคำถามที่เกี่ยวข้อง


1
และคุณยังสามารถใช้CREATE EXTENSION IF NOT EXISTS ...ถ้าคุณไม่แน่ใจและไม่ต้องการที่จะตรวจสอบ (เช่นในสคริปต์)
Uwe Allner

2
UUID เวอร์ชัน 4 นั้นใช้ได้กับชุดข้อมูลเกือบทุกขนาดไม่เพียง แต่จะ "จำกัด การใช้งานบนแถวชุดเล็ก" คุณจะต้องสร้าง 1 พันล้าน UUID ต่อวินาทีเป็นเวลาประมาณ 85 ปี (หรือประมาณ 45 ล้านเทราไบต์ของข้อมูลซึ่งใหญ่กว่าฐานข้อมูลที่ใหญ่ที่สุดในปัจจุบันหลายพันเท่า) เพื่อให้มีโอกาสชนกัน 50% นอกจากคุณจะเป็น NSA แล้วเวอร์ชัน 4 ยังใช้ได้กับทุกวัตถุประสงค์ ในทางกลับกันเวอร์ชัน 1 ประสบกับความจริงที่ว่าที่อยู่ MAC นั้นได้รับการมอบหมายตามลำดับ (และมักจะถูกหลอกหรือไม่สามารถใช้งานได้) ซึ่งเป็นส่วนหนึ่งของสาเหตุที่แนะนำรุ่นที่ใหม่กว่า
แจ๊ส

1
@BasilBourque ปัญหาของ v1 ไม่ใช่ความน่าจะเป็นของการชนเมื่อมีการใช้อย่างถูกต้อง แต่เป็นความน่าจะเป็นของการใช้งานที่ไม่ถูกต้อง ตามที่วิกิพีเดียกล่าวไว้: "ความเป็นเอกลักษณ์ของ UUID รุ่นที่ 1 และ 2 ... ยังขึ้นอยู่กับผู้ผลิตการ์ดเครือข่ายที่กำหนดที่อยู่ MAC ที่ไม่ซ้ำกันให้กับการ์ดของพวกเขาเช่นเดียวกับกระบวนการผลิตอื่น ๆ ที่อาจเกิดข้อผิดพลาด" นอกจากนี้ในบางสภาพแวดล้อมที่จัดเก็บหรือจำลองเสมือนที่อยู่ MAC จริงจากฮาร์ดแวร์พื้นฐานไม่สามารถใช้ได้ หากคอนเทนเนอร์จำนวนมากมี MAC เดียวกัน แต่เป็น clockseq counters ของตนเอง UUIDs v1 ของพวกเขาอาจชนกัน
แจ๊ส

1
@BasilBourque Weaknesses ใน v1 ไม่ใช่ประเด็นหลักของความคิดเห็นของฉัน คำตอบเดิมของคุณหมายความว่า v4 ไม่เหมาะสำหรับชุดข้อมูลขนาดใหญ่เนื่องจากมีความน่าจะเป็นที่จะเกิดการชนมากกว่า v1 นี่เป็นความเข้าใจผิดและอาจเป็นเท็จแม้ว่ามันจะยากในการคำนวณความน่าจะเป็นของการชนสำหรับ v1 เพราะมันขึ้นอยู่กับการนำไปใช้
แจ๊ส

1
@BasilBourque ตัวอย่างเช่นโครงการ node-uuid คำนวณความน่าจะเป็นของตัวนับ clockseq ที่เหมือนกัน (เพื่อให้กระบวนการสองกระบวนการสร้างลำดับ UUID ที่ v1 เดียวกัน) เท่ากับ 1 ใน 4.6e18 นี่เป็นเรื่องเล็กใช่ แต่มีโอกาสมากกว่าที่จะเกิดการชนใน v4 ซึ่งเป็น 1 ใน 5.3e36 เห็นได้ชัดว่ายิ่งคุณสร้าง v4 UUID ได้นานเท่าใดการชนกันก็จะยิ่งมากขึ้นซึ่งไม่เป็นความจริงของ v1 แต่คุณจะต้องสร้าง 1.52 พันล้าน v4 UUIDs ก่อนที่ความน่าจะเป็นของการชนจะเกินกว่าการนำ v1 มาใช้ของโหนด คนส่วนใหญ่ไม่มีบันทึก 1.52 พันล้านต่อโต๊ะ
แจ๊ส

61

pgcrypto ส่วนขยาย

ในขณะที่ Postgres 9.4 pgcryptoโมดูลจะมีgen_random_uuid()ฟังก์ชั่น ฟังก์ชั่นนี้จะสร้างหนึ่งในจำนวนสุ่มตามรุ่นที่ 4 ประเภทของ UUID

รับโมดูล contrib หากยังไม่พร้อมใช้งาน

sudo apt-get install postgresql-contrib-9.4

ใช้ pgcryptoโมดูล

CREATE EXTENSION "pgcrypto";

gen_random_uuid()ฟังก์ชั่นในขณะนี้ควรจะใช้ได้;

ตัวอย่างการใช้งาน

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


อ้างอิงจากPostgres doc onuuid-osspโมดูล

หมายเหตุ: หากคุณต้องการเพียง UUID ที่สร้างขึ้นแบบสุ่มเท่านั้นให้พิจารณาใช้ฟังก์ชัน gen_random_uuid () จากโมดูล pgcrypto แทน


3
ใช่ แต่โปรดดูที่blog.starkandwayne.com/2015/05/23/…โดยที่พวกเขาเตือนเกี่ยวกับการแตกแฟรกเมนต์และแนะนำ uuid-ossp แทน
Malik A. Rumi

3
ที่จริงแล้วเห็นpostgresql.org/message-id/…โดยที่ปัญหาการกระจายตัวของ uuid ใน Postgres debunked
Bob Kocisko

แต่ postgres จะมีดัชนีกลุ่มในรุ่นล่าสุดทำให้การโพสต์ที่เชื่อมโยงในความคิดเห็นข้างต้นสรุปไม่ถูกต้องและไม่ถูกต้องและเราจะกลับไปที่ตาราง 1
Michael Goldshteyn

1
@MichaelGoldshteyn: ไม่มี Postgres ไม่ได้จัดทำดัชนีได้คลัสเตอร์ ( ณ Postgres 12)
a_horse_with_no_name

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

หลังจากอ่านคำตอบของ @ ZuzEL ฉันใช้โค้ดด้านบนเป็นค่าเริ่มต้นของ id คอลัมน์และทำงานได้ดี


1

PostgreSQL 13 ที่กำลังจะมีขึ้นจะสนับสนุนgen_random_uuid ()โดยไม่จำเป็นต้องเปิดใช้งานส่วนขยายใด ๆ :

PostgreSQL มีฟังก์ชั่นเดียวในการสร้าง UUID:

gen_random_uuid ()  uuid

ฟังก์ชันนี้ส่งคืน UUID เวอร์ชัน 4 (สุ่ม) นี่เป็นประเภท UUID ที่ใช้กันมากที่สุดและเหมาะสมสำหรับการใช้งานส่วนใหญ่

db <> การสาธิตซอ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.