Створення UUID в Postgres для Insert оператора?


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 включають таке розширення, але не активують розширення. Дивіться правильну відповідь Крейга Рінгера, щоб дізнатися, як його активувати.
Василь Бурк

2
Якщо у вас встановлено uuid-ossp, і ви все-таки отримуєте цю помилку, спробуйте префіксувати функцію за назвою вашої схеми, наприкладselect dbo.uuid_generate_v4()
Річард

Відповіді:


435

uuid-osspє модулем contrib, тому він не завантажується на сервер за замовчуванням. Ви повинні завантажити його у свою базу даних, щоб використовувати його.

Для сучасних версій PostgreSQL (9.1 і новіших) це легко:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

але для версії 9.0 і нижче потрібно замість цього запустити скрипт SQL для завантаження розширення. Дивіться документацію для модулів внеску в 8.4 .

Для Pg 9.1 та новіших версій замість цього читайте документи поточного вкладу та CREATE EXTENSION. Ці функції не існують у версії 9.0 та старіших версій, як у вашій версії 8.4.

Якщо ви використовуєте упаковану версію PostgreSQL, можливо, вам знадобиться встановити окремий пакет, що містить модулі contrib та розширення. Шукайте у базі даних менеджера пакунків "postgres" та "contrib".


6
@advocate Ви використовуєте дистрибутив PostgreSQL, розроблений у дистрибутиві, тому ви маєте можливість просто apt-get install postgresql-contribчи подібне. Спробуйте apt-cache search postgresql |grep contribзнайти назву пакета, яку ви хочете.
Крейг Рінгер

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": такого файлу чи каталогу немає
Дрю Ноакс

1
Я написав цей коментар, коли рядок помилок виявився в Google. Також він дає конкретну назву пакета, принаймні для Ubuntu.
Дрю Ноакс

2
Якщо ви імпортували db, який вже має uuid-ossp у розширеннях, uuid_generate_v4 () може не працювати. Якщо це так, просто видаліть розширення та створіть його знову, і воно повинно працювати.
Драгос Русу

302

Без розширень (чіт)

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

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

(працює принаймні в 8.4)

  • Дякуємо @Erwin Brandstetter за clock_timestamp()пояснення.

Якщо вам потрібний дійсний U4 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: SELECTuuid_in(md5(random()::text || now()::text)::cstring);
Blaskovicz

4
@MattDiPasquale Напевно, не в жодному сенсі "кращого", ніж використання uuid-ossp, але я, наприклад, працюю над екземпляром PostgreSQL, де не маю достатніх привілеїв для встановлення розширення.
Стефан Хаберль

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- не потрібно більше магії. Приклад
Ервін Брандштеттер

17
Ні. Якщо це взагалі спрацює, то це сама удача. 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;
Карстен,

75

Відповідь на Крейга Рінгера правильно. Ось трохи більше інформації для 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";

Остерігайтеся: я знайшов символи QUOTATION MARK навколо імені розширення, незважаючи на те, що документація не суперечить.

Комітет зі стандартів SQL або команда Postgres вибрали непарне ім'я для цієї команди. На мій погляд, вони повинні були вибрати щось на кшталт "ВСТАНОВИТИ РОЗШИРЕННЯ" або "ВИКОРИСТИТИ РОЗШИРЕННЯ".

Перевірте встановлення

Ви можете переконатися, що розширення було встановлено в потрібній базі даних, запустивши цей SQL для запиту pg_extensionсистемного каталогу:

SELECT * FROM pg_extension;

UUID як значення за замовчуванням

Для отримання додаткової інформації див. Запитання: значення за замовчуванням для стовпця UUID у Postgres

Старий шлях

У наведеній вище інформації використовується нова функція розширень, додана до Postgres 9.1. У попередніх версіях нам довелося знайти і запустити скрипт у файлі .sql . Функція розширень була додана для полегшення встановлення, торгуючи трохи більшою роботою для творця розширення для меншої роботи з боку користувача / споживача розширення. Дивіться мій пост у блозі для більшого обговорення

Типи UUID

До речі, код у питанні викликає функцію uuid_generate_v4(). Це створює тип, відомий як Версія 4, де майже всі 128 біт генеруються випадковим чином. Хоча це нормально для обмеженого використання на менших наборах рядків, якщо ви хочете практично виключити будь-яку можливість зіткнення, використовуйте іншу "версію" UUID.

Наприклад, оригінальна версія 1 поєднує MAC-адресу хост-комп'ютера з поточним датою і часом і довільним номером, ймовірність зіткнення практично не дорівнює.

Для більш детальної дискусії дивіться мою відповідь на пов'язане запитання.


1
І ви також можете використовувати, CREATE EXTENSION IF NOT EXISTS ...якщо ви не впевнені і не хочете перевіряти (наприклад, у сценарії)
Uwe Allner

2
UUID версії 4 чудово підходять для будь-якого набору даних про розміри, а не лише для "обмеженого використання на менших наборах рядків". Вам доведеться генерувати 1 мільярд UUID в секунду протягом приблизно 85 років (або приблизно 45 мільйонів терабайт даних, в тисячі разів більше, ніж найбільші бази даних сьогодні), щоб навіть мати 50% шанс зіткнення. Якщо ви не представник АНБ, версія 4 прекрасна для будь-яких цілей. Версія 1, з іншого боку, страждала від того, що MAC адреси послідовно присвоюються (і часто підробляються або недоступні), що є частиною того, чому пізніші версії були введені.
Джаз

1
@BasilBourque Проблема з v1 - це не ймовірність зіткнення при правильній реалізації, це ймовірність неправильної реалізації. Як зазначає Вікіпедія: "Унікальність версій 1 та 2 UUID ... також залежить від того, щоб виробники мережевих карт належним чином призначили унікальні MAC-адреси своїм карткам, які, як і інші виробничі процеси, можуть піддаватися помилкам". Крім того, у деяких контейнерних або віртуалізованих середовищах справжні MAC-адреси з базового обладнання не доступні. Якщо багато контейнерів мають однаковий MAC, але свої власні лічильники годинника, їх v1 UUID можуть стикатися.
Джаз

1
@BasilBourque Слабкі місця в v1 - це не головний момент мого коментаря. Ваша оригінальна відповідь означає, що v4 не підходить для великих наборів даних через більш високу ймовірність зіткнення, ніж v1. Це вводить в оману і, можливо, помилково, хоча важко обчислити вірогідність зіткнення для v1, оскільки це так залежить від реалізації.
Джаз

1
@BasilBourque Наприклад, проект node-uuid обчислює ймовірність того, що їх лічильники тактових частот будуть однаковими (так що два процеси генерують ту саму послідовність v1 UUID), як 1 в 4.6e18. Це крихітно, так, але набагато частіше, ніж шанс негайного зіткнення в v4, який становить 1 на 5.3e36. Очевидно, що чим довше ви генеруєте v4 UUID, тим більша ймовірність зіткнення, що не відповідає дійсності v1, але вам доведеться генерувати 1,52 мільярда v4 UUID, перш ніж ймовірність зіткнення перевищить можливість реалізації v1 вузла. Більшість людей не мають 1,52 мільярда записів на стіл.
Джаз

61

pgcrypto Розширення

Станом на Postgres 9.4, pgcryptoмодуль включає gen_random_uuid()функцію. Ця функція генерує один з UUID типу на основі випадкових чисел .

Отримайте модулі для внеску, якщо вони ще відсутні.

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 наuuid-ossp модулі.

Примітка. Якщо вам потрібні лише випадково згенеровані UUID (версія 4) UUID, спробуйте скористатися функцією gen_random_uuid () з модуля pgcrypto.


3
Так, але дивіться також blog.starkandwayne.com/2015/05/23/…, де вони попереджають про фрагментацію і пропонують натомість uuid-ossp.
Малик А. Румі

3
Насправді, дивіться postgresql.org/message-id/… де випущено проблему фрагментації
уідів

Але постгреси мають кластеризовані індекси в останній версії, що робить публікацію, пов’язану з вищевказаним коментарем, непереконливою та некоректною, і ми повертаємося до площі 1.
Майкл Голдштейн

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, я використав наведений вище код як значення за замовчуванням ідентифікатора стовпця, і він працює нормально.


1

Майбутній PostgreSQL 13 підтримуватиме власний gen_random_uuid () без необхідності вмикати будь-які розширення:

PostgreSQL включає одну функцію для створення UUID:

gen_random_uuid ()  uuid

Ця функція повертає UUID версії 4 (випадковий). Це найбільш часто використовуваний тип UUID і підходить для більшості програм.

db <> скриптова демонстрація

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.