Tạo UUID trong Postgres cho câu lệnh Chèn?


368

Câu hỏi của tôi khá đơn giản. Tôi biết về khái niệm UUID và tôi muốn tạo một cái để tham khảo từng 'mặt hàng' từ một 'cửa hàng' trong DB của tôi với. Có vẻ hợp lý phải không?

Vấn đề là dòng sau trả về lỗi:

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.

Tôi đã đọc trang này tại: http://www.postgresql.org/docs/civerse/static/uuid-ossp.html

nhập mô tả hình ảnh ở đây

Tôi đang chạy Postgres 8.4 trên Ubuntu 10.04 x64.


8
Postgres vốn hỗ trợ UUID dưới dạng kiểu dữ liệu, thậm chí có khả năng được lập chỉ mục và sử dụng làm khóa chính. Nhưng để tạo giá trị UUID, chẳng hạn như để thiết lập giá trị mặc định cho cột, bạn cần có tiện ích mở rộng Postgres (plugin). Nhiều bản dựng (bản phân phối) của Postgres bao gồm một phần mở rộng như vậy nhưng không kích hoạt phần mở rộng. Xem câu trả lời đúng của Craig Ringer để tìm hiểu cách kích hoạt nó.
Basil Bourque

2
Nếu bạn đã cài đặt uuid-OSSP & bạn vẫn nhận được thử này lỗi tiền tố chức năng với tên giản đồ của bạn, ví dụ:select dbo.uuid_generate_v4()
Richard

Câu trả lời:


435

uuid-ossplà một mô-đun đóng góp, vì vậy nó không được tải vào máy chủ theo mặc định. Bạn phải tải nó vào cơ sở dữ liệu của bạn để sử dụng nó.

Đối với các phiên bản PostgreSQL hiện đại (9.1 trở lên) thật dễ dàng:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

nhưng đối với 9.0 trở xuống, bạn phải chạy tập lệnh SQL để tải phần mở rộng. Xem tài liệu cho các mô-đun đóng góp trong 8.4 .

Thay vào đó, đối với PG 9.1 và mới hơn, hãy đọc các tài liệu đóng góp hiện tạiCREATE EXTENSION. Các tính năng này không tồn tại trong phiên bản 9.0 trở lên, như phiên bản 8.4 của bạn.

Nếu bạn đang sử dụng phiên bản đóng gói của PostgreSQL, bạn có thể cần phải cài đặt một gói riêng có chứa các mô-đun và phần mở rộng đóng góp. Tìm kiếm cơ sở dữ liệu quản lý gói của bạn cho 'postgres' và 'contrib'.


6
@advocate Bạn đang sử dụng một PostgreSQL đóng gói để bạn có thể chỉ apt-get install postgresql-contribhoặc tương tự. Cố gắng apt-cache search postgresql |grep contribtìm tên gói bạn muốn.
Craig Ringer

2
sudo apt-get cài đặt postgresql-contrib đã chạy thành công. Sau đó, tôi đã phải chạy psql -d dbname -f SHAREDIR / contrib / module.sql và bây giờ nó hoạt động !!! chọn uuid_generate_v1 (); trả lại 1 bây giờ Cám ơn rất nhiều!
anon58192932

5
Lưu ý rằng nếu bạn không cài đặt postgresql-contribgói, bạn sẽ gặp lỗi: ERROR: không thể mở tệp kiểm soát tiện ích mở rộng "/usr/share/postgresql/9.3/extension/uuid-ossp.control": Không có tệp hoặc thư mục như vậy
Drew Noakes

1
Tôi đã đăng bình luận đó khi chuỗi lỗi xuất hiện trên Google. Ngoài ra, nó cung cấp một tên gói cụ thể, cho Ubuntu ít nhất.
Drew Noakes

2
Nếu bạn đã nhập một db đã có uuid-ossp trong Tiện ích mở rộng, uuid_generate_v4 () có thể không hoạt động. Nếu đó là trường hợp, chỉ cần loại bỏ phần mở rộng, và tạo lại nó và nó sẽ hoạt động.
Dragos Rusu

302

Không có phần mở rộng (gian lận)

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

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

(hoạt động ít nhất trong 8.4)

  • Cảm ơn @Erwin Brandstetter đã clock_timestamp()giải thích.

Nếu bạn cần một UUID v4 hợp lệ

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

nhập mô tả hình ảnh ở đây * Cảm ơn @Denis Stafichuk @Karsten@autronix


Ngoài ra, trong Postgres hiện đại, bạn có thể chỉ cần sử dụng:

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


5
Để theo dõi PS của bạn: CHỌNuuid_in(md5(random()::text || now()::text)::cstring);
Blaskovicz

4
@MattDiPasquale Có lẽ không có nghĩa là "tốt hơn" so với việc sử dụng uuid-ossp, nhưng tôi đang làm việc trên một cá thể PostgreQuery, nơi tôi không có đủ đặc quyền để cài đặt tiện ích mở rộng.
Stefan Haberl

25
@JosephLennox: clock_timestamp()là sự thay thế tốt hơn trong cả hai trường hợp cho việc này. Không giống như now()hoặc CURRENT_TIMESTAMPnó không ổn định và trả về thời gian hiện tại thực tế. SELECT uuid_in(md5(random()::text || clock_timestamp()::text)::cstring);Ngoài ra, trong Postgres hiện đại, bạn có thể chỉ cần sử dụng: SELECT md5(random()::text || clock_timestamp()::text)::uuid- không cần thêm phép thuật. Ca sử dụng: stackoverflow.com/a/8335376/939860
Erwin Brandstetter

17
Không. Nếu điều này không làm việc ở tất cả sự may mắn của nó. một UUID có một định dạng, nó không chỉ là các ký tự hex ngẫu nhiên được ghép lại với nhau. Số thứ nhất của nhóm thứ 3 là phiên bản uuid cho intance (thường là 4 ngày nay). Nếu ứng dụng của bạn kiểm tra chữ số đó để xem phiên bản nào của uuid đang xử lý và làm điều gì đó tương ứng, nó sẽ thất bại trong mã của bạn.
Tuncay Göncüoğlu

7
@Tuncay Göncüoğlu: Khá đơn giản để tạo UUID v4 hợp lệ (cách tiếp cận lớp phủ chuỗi lãng phí 2 bit ngẫu nhiên):select overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing '8' from 17)::uuid;
Karsten

75

Câu trả lời của Craig Ringer là chính xác. Dưới đây là một chút thông tin cho Postgres 9.1 trở lên

Có mở rộng không?

Bạn chỉ có thể cài đặt tiện ích mở rộng nếu nó đã được xây dựng để cài đặt Postgres ( cụm của bạn trong biệt ngữ Postgres). Ví dụ: tôi đã tìm thấy tiện ích mở rộng uuid-ossp được bao gồm như một phần của trình cài đặt cho Mac OS X do EnterpriseDB.com cung cấp . Bất kỳ một vài chục phần mở rộng có thể có sẵn.

Để xem phần mở rộng uuid-ossp có sẵn trong cụm Postgres của bạn không, hãy chạy SQL này để truy vấn pg_available_extensionsdanh mục hệ thống:

SELECT * FROM pg_available_extensions;

Cài đặt tiện ích mở rộng

Để cài đặt tiện ích mở rộng liên quan đến UUID đó , hãy sử dụng lệnh CREATE EXTENSION như đã thấy trong SQL này:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Chú ý: Tôi thấy các ký tự QUOTATION Mark xung quanh tên mở rộng là bắt buộc, mặc dù tài liệu ngược lại.

Ủy ban tiêu chuẩn SQL hoặc nhóm Postgres đã chọn một tên lẻ cho lệnh đó. Theo suy nghĩ của tôi, họ nên chọn một cái gì đó như "CÀI ĐẶT EXTENSION" hoặc "SỬ DỤNG EXTENSION".

Xác minh cài đặt

Bạn có thể xác minh tiện ích mở rộng đã được cài đặt thành công trong cơ sở dữ liệu mong muốn bằng cách chạy SQL này để truy vấn pg_extensiondanh mục hệ thống:

SELECT * FROM pg_extension;

UUID làm giá trị mặc định

Để biết thêm thông tin, hãy xem Câu hỏi: Giá trị mặc định cho cột UUID trong Postgres

Con đường cũ

Thông tin trên sử dụng tính năng Tiện ích mở rộng mới được thêm vào Postgres 9.1. Trong các phiên bản trước, chúng tôi đã phải tìm và chạy một tập lệnh trong tệp .sql . Tính năng Tiện ích mở rộng đã được thêm vào để giúp cài đặt dễ dàng hơn, giao dịch nhiều hơn một chút cho người tạo tiện ích mở rộng để làm việc ít hơn với người dùng / người tiêu dùng tiện ích mở rộng. Xem bài viết trên blog của tôi để thảo luận thêm.

Các loại UUID

Nhân tiện, mã trong Câu hỏi gọi hàm uuid_generate_v4(). Điều này tạo ra một loại được gọi là Phiên bản 4 trong đó gần như tất cả 128 bit được tạo ngẫu nhiên. Mặc dù điều này tốt cho việc sử dụng hạn chế trên các hàng nhỏ hơn, nhưng nếu bạn muốn loại bỏ hầu như mọi khả năng va chạm, hãy sử dụng một "phiên bản" khác của UUID.

Ví dụ, Phiên bản 1 gốc kết hợp địa chỉ MAC của máy tính chủ với thời gian hiện tại và số tùy ý, cơ hội va chạm thực tế là không.

Để thảo luận thêm, xem Câu trả lời của tôi về Câu hỏi liên quan.


1
Và bạn cũng có thể sử dụng CREATE EXTENSION IF NOT EXISTS ...nếu bạn không chắc chắn và không muốn kiểm tra (ví dụ trong tập lệnh)
Uwe Allner

2
UUID phiên bản 4 phù hợp với hầu hết mọi tập dữ liệu kích thước, không chỉ "sử dụng hạn chế trên các bộ hàng nhỏ hơn". Bạn sẽ phải tạo 1 tỷ UUID mỗi giây trong khoảng 85 năm (hoặc khoảng 45 triệu terabyte dữ liệu, lớn hơn hàng nghìn lần so với cơ sở dữ liệu lớn nhất hiện nay) để có khả năng va chạm 50%. Trừ khi bạn là NSA, Phiên bản 4 vẫn ổn cho mọi mục đích. Mặt khác, phiên bản 1 bị ảnh hưởng bởi thực tế là các địa chỉ MAC được gán liên tục (và thường bị giả mạo hoặc không có sẵn), đó là một phần lý do tại sao các phiên bản sau được giới thiệu.
Jazz

1
@BasilBourque Vấn đề với v1 không phải là xác suất va chạm khi được thực hiện đúng, đó là xác suất thực hiện không chính xác. Như Wikipedia đưa ra: "Tính duy nhất của UUID phiên bản 1 và 2 ... cũng phụ thuộc vào các nhà sản xuất card mạng gán đúng địa chỉ MAC duy nhất cho thẻ của họ, giống như các quy trình sản xuất khác có thể bị lỗi." Ngoài ra, trong một số môi trường được đóng gói hoặc ảo hóa, địa chỉ MAC thực từ phần cứng cơ bản không khả dụng. Nếu nhiều container có cùng MAC nhưng bộ đếm clockseq của riêng chúng, các UUID v1 của chúng có thể va chạm.
Jazz

1
@BasilBourque Điểm yếu trong v1 không phải là điểm chính trong nhận xét của tôi. Câu trả lời ban đầu của bạn ngụ ý rằng v4 không phù hợp với các bộ dữ liệu lớn do xác suất va chạm cao hơn v1. Điều này là sai lệch và có thể sai, mặc dù khó có thể tính xác suất va chạm cho v1 vì nó phụ thuộc vào việc thực hiện.
Jazz

1
@BasilBourque Ví dụ, dự án node-uuid tính toán xác suất của bộ đếm clockseq của chúng là như nhau (để hai quá trình tạo ra cùng một chuỗi v1 UUID) như 1 trong 4.6e18. Điều này rất nhỏ, đúng vậy, nhưng nhiều khả năng xảy ra va chạm ngay lập tức trong v4, là 1 trong 5.3e36. Rõ ràng bạn tạo v4 UUID càng lâu thì khả năng xảy ra va chạm càng không đúng với v1, nhưng bạn phải tạo 1,52 tỷ v4 UUID trước khi xác suất va chạm vượt quá khả năng thực hiện v1 của nút. Hầu hết mọi người không có 1,52 tỷ hồ sơ mỗi bảng.
Jazz

61

pgcrypto Sự mở rộng

Kể từ Postgres 9.4, pgcryptomô-đun bao gồm gen_random_uuid()chức năng. Hàm này tạo ra một trong các loại UUID dựa trên số ngẫu nhiên .

Nhận mô-đun đóng góp, nếu chưa có sẵn.

sudo apt-get install postgresql-contrib-9.4

Sử dụng pgcryptomô-đun.

CREATE EXTENSION "pgcrypto";

Các gen_random_uuid()chức năng nên có sẵn bây giờ;

Ví dụ sử dụng.

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


Trích dẫn từ tài liệu Postgres trênuuid-ossp mô-đun.

Lưu ý: Nếu bạn chỉ cần các UUID được tạo ngẫu nhiên (phiên bản 4), hãy xem xét sử dụng hàm gen_random_uuid () từ mô-đun pgcrypto thay thế.


3
Có, nhưng cũng xem blog.starkandwayne.com/2015/05/23/ Nơi mà họ cảnh báo về sự phân mảnh và đề nghị uuid-ossp thay thế.
Malik A. Rumi

3
Trên thực tế, hãy xem postgresql.org/message-id/ , nơi vấn đề phân mảnh uuid trong Postgres được gỡ lỗi
Bob Kocisko 2/218

Nhưng postgres đã phân cụm các chỉ mục trong phiên bản mới nhất, khiến bài đăng được liên kết trong nhận xét trên không có kết luận và không chính xác và chúng tôi quay lại quảng trường 1.
Michael Goldshteyn

1
@MichaelGoldshteyn: không, Postgres không có các chỉ mục được nhóm (kể từ Postgres 12)
a_horse_with_no_name

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

Sau khi đọc câu trả lời của @ ZuzEL, tôi đã sử dụng đoạn mã trên làm giá trị mặc định của id cột và nó hoạt động tốt.


1

Sắp tới PostgreQuery 13 sẽ hỗ trợ gen_random_uuid () mà không cần bật bất kỳ tiện ích mở rộng nào:

PostgreSQL bao gồm một chức năng để tạo UUID:

gen_random_uuid ()  uuid

Hàm này trả về UUID phiên bản 4 (ngẫu nhiên). Đây là loại UUID được sử dụng phổ biến nhất và phù hợp với hầu hết các ứng dụng.

db <> fiddle demo

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.