609

My question is rather simple. I'm aware of the concept of a UUID and I want to generate one to refer to each 'item' from a 'store' in my DB with. Seems reasonable right?

The problem is the following line returns an error:

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.

I've read the page at: http://www.postgresql.org/docs/current/static/uuid-ossp.html

I'm running Postgres 8.4 on Ubuntu 10.04 x64.

fIwJlxSzApHEZIl
  • 11,861
  • 6
  • 62
  • 71
  • 17
    Postgres natively supports [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) as a data type, even capable of being indexed and used as primary key. But to *generate* a UUID value, such as to establish a default value for a column, you need a Postgres extension (a plugin). Many builds (distributions) of Postgres include such an extension but do not activate the extension. See the [correct answer by Craig Ringer](http://stackoverflow.com/a/12505220/642706) to learn how to activate it. – Basil Bourque Mar 12 '14 at 06:27
  • 4
    If you have uuid-ossp installed & you still get this error try prefixing the function with your schema name, e.g. `select dbo.uuid_generate_v4()` – Richard Jun 15 '16 at 15:59
  • Just in case you want Postgres to generate the UUID for a column OUTSIDE the PK (Primary Key), I finally found a specific way to do so: https://stackoverflow.com/a/75900798/501113 – chaotic3quilibrium Mar 31 '23 at 16:32
  • 2
    if you use Postgres 13+, no extension needed, just call `gen_random_uuid()`. Courtesy of https://stackoverflow.com/a/61970869/316343 – Jahan Zinedine Jun 16 '23 at 13:10

12 Answers12

654

uuid-ossp is a contrib module, so it isn't loaded into the server by default. You must load it into your database to use it.

For modern PostgreSQL versions (9.1 and newer) that's easy:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

but for 9.0 and below you must instead run the SQL script to load the extension. See the documentation for contrib modules in 8.4.

For Pg 9.1 and newer instead read the current contrib docs and CREATE EXTENSION. These features do not exist in 9.0 or older versions, like your 8.4.

If you're using a packaged version of PostgreSQL you might need to install a separate package containing the contrib modules and extensions. Search your package manager database for 'postgres' and 'contrib'.

Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
  • I'm supposed to type: pg_config --sharedir to find out my shared directory in order to import the module but the command isn't working in either shell or inside the psql command prompt. – fIwJlxSzApHEZIl Sep 20 '12 at 19:01
  • So I had to run sudo apt-get install libpq-dev in order to run pg_config --sharedir but now I don't have a 'contrib' folder inside my sharedir which is supposed to exist according to http://www.postgresql.org/docs/8.4/static/contrib.html – fIwJlxSzApHEZIl Sep 20 '12 at 19:12
  • 7
    @advocate You're using a distro-packaged PostgreSQL so you should be able to just `apt-get install postgresql-contrib` or similar. Try `apt-cache search postgresql |grep contrib` to find the package name you want. – Craig Ringer Sep 20 '12 at 22:53
  • 2
    sudo apt-get install postgresql-contrib has successfully run. Then I had to run psql -d dbname -f SHAREDIR/contrib/module.sql and now it works!!! select uuid_generate_v1(); returns 1 now now. Thanks so much! – fIwJlxSzApHEZIl Sep 29 '12 at 22:13
  • CREATE EXTENSION "uuid-ossp"; is not working in postgresql-9.1 too , Error: could not open extension control file "/usr/pgsql-9.1/share/extension/uuid-ossp.control": No such file or directory is coming while creating extension. can u help me what I am lacking ,my version of postgresql is 9.1. – Satish Sharma Jan 16 '13 at 12:13
  • @SatishSharma Please post a new question. Link back to this one if you think it's relevant. Include details like how you installed Pg, your OS, etc. – Craig Ringer Jan 16 '13 at 14:05
  • 6
    Note that if you don't install the `postgresql-contrib` package, you'll get the error: _ERROR: could not open extension control file "/usr/share/postgresql/9.3/extension/uuid-ossp.control": No such file or directory_ – Drew Noakes Jan 29 '14 at 16:27
  • @DrewNoakes Yep, hence the last paragraph. – Craig Ringer Jan 29 '14 at 23:11
  • 1
    I posted that comment as the error string struck out on Google. Also it gives a specific package name, for Ubuntu at least. – Drew Noakes Jan 29 '14 at 23:29
  • 2
    If you imported a db that has the uuid-ossp in the Extensions already, uuid_generate_v4() might not work. If that's the case, just remove the extension, and create it again and it should work. – Dragos Rusu Jul 27 '15 at 10:51
  • 2
    Using `IF NOT EXISTS` is good practice, especially in any sql scripts - it prevents an error from being issued if, say, you re-run the script, or transfer it to another system where it is already loaded. (I just added it to the answer.) – Randall Nov 19 '15 at 15:30
498

Without extensions (cheat)

If you need a valid v4 UUID

SELECT uuid_in(overlay(overlay(md5(random()::text || ':' || random()::text) placing '4' from 13) placing to_hex(floor(random()*(11-8+1) + 8)::int)::text from 17)::cstring);

enter image description here

  • Thanks to @Denis Stafichuk @Karsten and @autronix

Or you can simply get UUID-like value by doing this (if you don't care about the validity):

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

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

(works at least in 8.4)

ZuzEL
  • 12,768
  • 8
  • 47
  • 68
  • 1
    Is this better than `uuid-ossp`? `uuid_in` seems to return the same outputs for identical inputs. So, if you use it to create two UUIDs at the same exact time (or with the same results from `random()`), they'll be equal. – ma11hew28 Feb 10 '14 at 16:51
  • 6
    To follow up your PS: SELECT `uuid_in(md5(random()::text || now()::text)::cstring);` – Blaskovicz Jul 24 '14 at 21:38
  • 6
    @MattDiPasquale Probably not in any sense "better" than using `uuid-ossp`, but I'm for instance working on a PostgreSQL instance where I don't have the sufficient privileges to install an extension. – Stefan Haberl Dec 04 '14 at 08:18
  • 1
    The clear issue with just time is "What if the time hasn't changed yet?" Put that statement two into a select and you'll get the same result twice. – Joseph Lennox Apr 01 '15 at 19:03
  • 29
    @JosephLennox: [`clock_timestamp()`](http://www.postgresql.org/docs/current/interactive/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT) is the better alternative in either case for this. Unlike `now()` or `CURRENT_TIMESTAMP` it is volatile and returns the actual current time. `SELECT uuid_in(md5(random()::text || clock_timestamp()::text)::cstring);` Also, in modern Postgres, you can simply cast: `SELECT md5(random()::text || clock_timestamp()::text)::uuid` - no need for more magic. Use-case: http://stackoverflow.com/a/8335376/939860 – Erwin Brandstetter Apr 24 '15 at 02:02
  • 30
    Nope. If this does work at all its sheer luck. a UUID has a format, its not just random hex chars thrown together.The first number of 3rd group is the uuid version for intance (usually 4 these days). If your application checks that digit to see what version of uuid its dealing with, and do something accordingly, it will fail in your code. – Tuncay Göncüoğlu May 09 '16 at 08:58
  • 8
    @Tuncay Göncüoğlu: It's fairly straightforward to generate a valid v4 UUID (the string overlay approach wastes 2 bits of randomness though): `select overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing '8' from 17)::uuid;` – Karsten Mar 09 '17 at 13:21
  • 2
    @Karsten, I've improved your sample by getting back those 2 bits of randmoness: `overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing floor(random()*(11-8+1) + 8)::text from 17)::uuid;` this should compensate for both version and variant while still retaining the 2 LSB `10xx` from the variant part. – autronix Aug 25 '17 at 16:04
  • 3
    @autronix, actually you've broken it. You need to convert `floor(random()*(11-8+1) + 8)` to hex to make it right. Here's the corrected version: `select 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)::uuid;` – Denis Stafichuk Aug 22 '18 at 15:14
  • 1
    @ZuzEL: you should remove your top answer because we have a high probability for collisions if use now() which is effectively error-prone when being in a transaction while generating multiple uuids. Use clock_timestamp instead to avoid this. – John Rumpel Sep 26 '18 at 20:36
  • 1
    @JohnRumpel I edited. Thanks for your attention to that collision problem. – ZuzEL Sep 28 '18 at 11:46
  • 1
    When trying to parse the UUID generated from this in Java, and then calling `uuid.timestamp()` it complains that the uuid is not a time-based uuid, so something is fishy by using this. – Robin Jonsson Mar 04 '19 at 15:04
  • 2
    @RobinJonsson nothing fishy. Version 4 of UUID is not time based. https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address) – ZuzEL Mar 04 '19 at 16:50
  • 3
    I see no sense in using `clock_timestamp` in any of the approaches mentioned in the answer because the data is fed into `md5` anyway and therefore is lost. Thus we can simply use `md5(random()::text || random()::text)::uuid`: using `random` (returns `double precision`, i.e. 64bits) twice gives us 128bit of random information which is converted to a hexadecimal representation of a different (but still random) 128bit number by `md5`. – Valentin Kovalenko Oct 03 '19 at 06:08
  • 1
    There are strict requirements about how a UUID is **generated** that are undetectable until you accidentally get a duplicate. Just because it looks like a UUID and smells like a UUID does not mean it's a valid UUID. [UUID4 is not supposed to be clock based](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) – Philip Couling Jun 15 '22 at 10:53
253

PostgreSQL 13 supports natively gen_random_uuid ():

PostgreSQL includes one function to generate a UUID:

gen_random_uuid () → uuid

This function returns a version 4 (random) UUID. This is the most commonly used type of UUID and is appropriate for most applications.

db<>fiddle demo

Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275
  • 9
    I don't undertstand why there are so much other (non working) answer, it's as simple as this! should be the accepted answer – pdem Sep 06 '21 at 14:24
  • 9
    @pdem because PostgreSQL 13 is rather new. For instance, I am still working on server version 10. This seems the best alternative for version 13, though. – borellini Sep 08 '21 at 12:29
  • 5
    @borellini I understand, I actually have a production server in 12, I had to create this patch function to make it work `create function gen_random_uuid() RETURNS uuid as $$ SELECT md5(random()::text || clock_timestamp()::text)::uuid $$ LANGUAGE SQL;` – pdem Sep 08 '21 at 15:59
  • 1
    I like this polyfill, easy to upgrade with. – Ben Longo Apr 13 '22 at 21:01
  • Which version of UUID does it generate? – TheRealChx101 Feb 08 '23 at 02:35
  • 1
    @TheRealChx101 "This function returns a version 4 (random) UUID." – Lukasz Szozda Feb 08 '23 at 15:19
108

The answer by Craig Ringer is correct. Here's a little more info for Postgres 9.1 and later…

Is Extension Available?

You can only install an extension if it has already been built for your Postgres installation (your cluster in Postgres lingo). For example, I found the uuid-ossp extension included as part of the installer for Mac OS X kindly provided by EnterpriseDB.com. Any of a few dozen extensions may be available.

To see if the uuid-ossp extension is available in your Postgres cluster, run this SQL to query the pg_available_extensions system catalog:

SELECT * FROM pg_available_extensions;

Install Extension

To install that UUID-related extension, use the CREATE EXTENSION command as seen in this this SQL:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Beware: I found the QUOTATION MARK characters around extension name to be required, despite documentation to the contrary.

The SQL standards committee or Postgres team chose an odd name for that command. To my mind, they should have chosen something like "INSTALL EXTENSION" or "USE EXTENSION".

Verify Installation

You can verify the extension was successfully installed in the desired database by running this SQL to query the pg_extension system catalog:

SELECT * FROM pg_extension;

UUID as default value

For more info, see the Question: Default value for UUID column in Postgres

The Old Way

The information above uses the new Extensions feature added to Postgres 9.1. In previous versions, we had to find and run a script in a .sql file. The Extensions feature was added to make installation easier, trading a bit more work for the creator of an extension for less work on the part of the user/consumer of the extension. See my blog post for more discussion.

Types of UUIDs

By the way, the code in the Question calls the function uuid_generate_v4(). This generates a type known as Version 4 where nearly all of the 128 bits are randomly generated. While this is fine for limited use on smaller set of rows, if you want to virtually eliminate any possibility of collision, use another "version" of UUID.

For example, the original Version 1 combines the MAC address of the host computer with the current date-time and an arbitrary number, the chance of collisions is practically nil.

For more discussion, see my Answer on related Question.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    And you can also use `CREATE EXTENSION IF NOT EXISTS ...` if you are not sure and don't want to check (in a script e.g.) – Uwe Allner Jan 08 '15 at 10:40
  • 5
    Version 4 UUIDs are fine for nearly any size data set, not only "limited use on smaller sets of rows." You would have to generate 1 billion UUIDs per second for about 85 years (or about 45 million terabytes of data, thousands of times larger than the biggest databases today) to even have a 50% chance of collision. Unless you're the NSA, Version 4 is fine for about any purpose. Version 1, on the other hand, suffered from the fact that MAC addresses are sequentially-assigned (and are often spoofed or unavailable), which is part of why later versions were introduced. – Jazz Feb 06 '19 at 20:08
  • @Jazz I do not see how sequentially-assigned MACs or spoofed MACs are relevant to generating UUIDs, Unless a MAC you were using were being spoofed on another machine in same context where you were using the UUIDs, the spoofed MAC is irrelevant. – Basil Bourque Feb 07 '19 at 00:04
  • @Jazz As for random-based UUIDs, there is enough misinformation and misunderstanding about UUIDs being unreliable that I wanted to allay any concerns. While I agree that for most practical purposes a version 4 UUID from a properly constructed generator is sufficient, there is still *some* chance of collisions. Using the other versions such as version 1 virtually eliminates any chance of collision. That's why it was invented first. – Basil Bourque Feb 07 '19 at 00:07
  • @Jazz As for other versions being created after version 1, I have only heard that the motivation was for concerns over the privacy and security implications of disclosing the MAC (which could be useful to a network hacker), the location implied by the MAC, and the date-time. – Basil Bourque Feb 07 '19 at 00:10
  • 2
    @BasilBourque The issue with v1 isn't the probability of collision when correctly implemented, it's the probability of incorrect implementation. As Wikipedia puts it: "The uniqueness of version 1 and 2 UUIDs ... also depends on network card manufacturers properly assigning unique MAC addresses to their cards, which like other manufacturing processes is subject to error." Also, in some containerized or virtualized environments, true MAC addresses from the underlying hardware are not available. If many containers have the same MAC but their own clockseq counters, their v1 UUIDs may collide. – Jazz Feb 07 '19 at 19:40
  • 2
    @BasilBourque Weaknesses in v1 are not the main point of my comment, though. Your original answer implies that v4 is not suitable for large datasets due to a higher probability of collision than v1. This is misleading and possibly false, though it is hard to calculate the collision probability for v1 because it is so implementation-dependent. – Jazz Feb 07 '19 at 19:53
  • 2
    @BasilBourque For example, the node-uuid project calculates the probability of their clockseq counters being the same (so that two processes would generate the same sequence of v1 UUIDs) as 1 in 4.6e18. This is tiny, yes, but much more likely than the chance of immediate collision in v4, which is 1 in 5.3e36. Obviously the longer you generate v4 UUIDs the more likely a collision becomes, which is not true of v1, but you'd have to generate 1.52 billion v4 UUIDs before the probability of collision exceeded that of node's v1 implementation. Most people don't have 1.52 billion records per table. – Jazz Feb 07 '19 at 19:59
86

pgcrypto Extension

As of Postgres 9.4, the pgcrypto module includes the gen_random_uuid() function. This function generates one of the random-number based Version 4 type of UUID.

Get contrib modules, if not already available.

sudo apt-get install postgresql-contrib-9.4

Use pgcrypto module.

CREATE EXTENSION "pgcrypto";

The gen_random_uuid() function should now available;

Example usage.

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


Quote from Postgres doc on uuid-ossp module.

Note: If you only need randomly-generated (version 4) UUIDs, consider using the gen_random_uuid() function from the pgcrypto module instead.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
brillout
  • 7,804
  • 11
  • 72
  • 84
  • 3
    Yes, but see also https://blog.starkandwayne.com/2015/05/23/uuid-primary-keys-in-postgresql/ where they warn about fragmentation and suggest uuid-ossp instead. – Malik A. Rumi Feb 04 '16 at 19:11
  • 4
    Actually, see https://www.postgresql.org/message-id/20151222124018.bee10b60b3d9b58d7b3a1839%40potentialtech.com where the uuid fragmentation issue in Postgres is debunked – Bob Kocisko Feb 02 '18 at 19:21
  • But postgres does have clustered indexes in the latest version, making the post linked in the above comment inconclusive and incorrect and we are right back to square 1. – Michael Goldshteyn Jul 05 '18 at 18:07
  • 2
    @MichaelGoldshteyn: no, Postgres does **not** have clustered indexes (as of Postgres 12) –  Aug 27 '19 at 11:31
  • The article in the first comment has moved [here](https://www.starkandwayne.com/blog/uuid-primary-keys-in-postgresql/). TLDR, though, the second link about debunking the "fragmentation" issue found the article that started the myth, and it is based on databases with clustered indexes, which as @a_horse_with_no_name has said, postgres does not have. It has a function to do a one-time reordering of data so the keys are clustered, but it is not the same as SQL Server. SQL Server can store rows ordered by a key, and shuffles things around as new records are added to keep the keys in order. – ps2goat Nov 23 '21 at 22:28
65

Update from 2021, There is no need for a fancy trick to auto generate uuid on insert statement.

Just do one thing:

  1. Set default value of DEFAULT gen_random_uuid () to your uuid column. That is all.

Say, you have a table like this:

CREATE TABLE table_name (
    unique_id UUID DEFAULT gen_random_uuid (),
    first_name VARCHAR NOT NULL,
    last_name VARCHAR NOT NULL,
    email VARCHAR NOT NULL,
    phone VARCHAR,
    PRIMARY KEY (unique_id)
);

Now you need NOT to do anything to auto insert uuid values to unique_id column. Because you already defined a default value for it. You can simply focus on inserting onto other columns, and postgresql takes care of your unique_id. Here is a sample insert statement:

INSERT INTO table_name (first_name, last_name, email, phone) 
VALUES (
    'Beki',
    'Otaev',
    'beki@bekhruz.com',
    '123-456-123'
)

Notice there is no inserting into unique_id as it is already taken care of.

About other extensions like uuid-ossp, you can bring them on if you are not satisfied with postgres's standard gen_random_uuid () function. Most of the time, you should be fine without them on

labulaka
  • 48
  • 8
Beki
  • 1,344
  • 1
  • 12
  • 22
  • 2
    As Lukasz Szozda noted in https://stackoverflow.com/a/61970869/13950739, `gen_random_uuid()` is available in _core_ PostgreSQL (so don't need to install any extension) as of PostgreSQL *13*. – Vainstein K Nov 13 '21 at 01:10
  • At the bottom of this article: https://www.starkandwayne.com/blog/uuid-primary-keys-in-postgresql/ there is a discussion on a possible con of gen_random_uuid(). Any comment as to the validity of the statement? – Jacolack Dec 07 '21 at 01:00
  • 1
    if you mean `negative side effect with respect to keyspace fragmentation`, then: No, that is not an issue: https://www.postgresql.org/message-id/20151222124018.bee10b60b3d9b58d7b3a1839%40potentialtech.com – as mentioned in a comment on brillout's answer – ctholho Jan 04 '22 at 23:06
5

The uuid-ossp module provides functions to generate universally unique identifiers (UUIDs)

uuid_generate_v1() This function generates a version 1 UUID.

  1. Add Extension

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

  1. Verify Extension

SELECT * FROM pg_extension;

  1. Run Query

INSERT INTO table_name(id, column1, column2 , column3, ...) VALUES (uuid_generate_v1(), value1, value2, value3...);

Verify table data

Satish Mali
  • 61
  • 1
  • 3
4
ALTER TABLE table_name ALTER COLUMN id SET DEFAULT uuid_in((md5((random())::text))::cstring);

After reading @ZuzEL's answer, i used the above code as the default value of the column id and it's working fine.

Paolo Fernandes
  • 113
  • 1
  • 7
3

Postgres v13+

INSERT INTO your_table
VALUES (gen_random_uuid(), 'value column 2', 'value column 3')
Pablo
  • 643
  • 9
  • 12
1

first, you need to add extension

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

0

On postgres version less than 13:

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- gives:

SELECT gen_random_uuid();

On postgres version 13+:

SELECT gen_random_uuid();

In context when you don't know the postgres version but presume it's at least 9, and it matters to you not to enable the extension unnecessarily:

DO
$do$
BEGIN
  IF current_setting('server_version_num')::integer < 130000 THEN
    CREATE EXTENSION IF NOT EXISTS "pgcrypto";
  END IF;
END
$do$

SELECT gen_random_uuid();
d-ph
  • 572
  • 4
  • 17
-3
SELECT uuid_generate_v5(uuid_ns_url (), 'test');
skyho
  • 1,438
  • 2
  • 20
  • 47