在Postgres 9.x中,对于UUID类型的列,我如何指定要自动生成的UUID作为任何行插入的默认值?

#1 楼

tl; dr

在定义列以调用OSSP uuid函数之一时调用DEFAULT。每次插入行时,Postgres服务器都会自动调用该函数。

CREATE TABLE tbl 
(
  pkey UUID NOT NULL DEFAULT uuid_generate_v1() , 
  CONSTRAINT pkey_tbl PRIMARY KEY ( pkey )
)


如果您已经使用pgcrypto扩展名,请考虑使用bpieck回答。

生成UUID所需的插件

Postgres开箱即用支持以其本机128位格式存储UUID(通用唯一标识符)值,从而生成UUID值需要一个插件。在Postgres中,一个插件称为extension

要安装扩展程序,请致电CREATE EXTENSION。为避免重新安装,请添加IF NOT EXISTS。有关更多详细信息,请参见我的博客文章。或在StackOverflow中查看此页面。

我们想要的扩展是一个用C内置的开放源代码库,用于处理UUID和OSSP uuid。这个用于Postgres的库的构建通常与Postgres的安装捆绑在一起,例如Enterprise DB提供的图形安装程序,或者包括诸如Amazon RDS for PostgreSQL的云提供商所包括的图形安装程序。

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";


生成各种UUID

请参阅扩展文档,以查看提供用于生成各种UUID值的多个命令的列表。要获取从计算机的MAC地址,当前日期时间以及一个较小的随机值构建的UUID的原始版本,请调用uuid_generate_v1()

SELECT uuid_generate_v1();



672124b6- 9894-11e5-be38-001d42e813fe


此主题的最新变化是为替代类型的UUID开发的。例如,出于安全性或隐私方面的考虑,有些人可能不想记录服务器的实际MAC地址。 Postgres扩展生成五种UUID,外加“无” UUID 00000000-0000-0000-0000-000000000000

UUID作为默认值

可以自动进行该方法调用以生成用于任何新插入的行。定义列时,请指定:


DEFAULT uuid_generate_v1()


请参阅以下示例表定义中使用的命令。

 CREATE TABLE public.pet_
(
  species_ text NOT NULL,
  name_ text NOT NULL,
  date_of_birth_ text NOT NULL,
  uuid_ uuid NOT NULL DEFAULT uuid_generate_v1(),  -- <====
  CONSTRAINT pet_pkey_ PRIMARY KEY (uuid_)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.pet_
  OWNER TO postgres;
 


UUID版本

uuid-ossp插件可以生成各种版本的UUID。



uuid_generate_v1()包含当前计算机的MAC地址+当前时刻。常用,但是请避免对透露数据库服务器的MAC或生成该值的时间敏感。由规范定义为版本1 UUID。

uuid_generate_v1mc()与版本1类似,但具有随机的多播MAC地址而不是实际MAC地址。显然,使用一种版本1的方法是,如果您对公开该事实敏感的话,可以用另一个MAC代替数据库服务器的实际MAC。什么是“随机多播MAC”?我不知道。在阅读了RFC 4122的4.1.6节之后,我怀疑这是一个代替MAC的随机数,但是它的位被设置为指示多播MAC地址而不是通常的单播,以便区分版本1与通常的这种变化。 real-MAC版本1 UUID。

uuid_generate_v3( namespace uuid, name text )包含您提供的文本的MD5哈希。由规范定义为版本3 UUID,基于名称空间的UUID。

uuid_generate_v4()基于128位中121-122位的随机生成数据。六或七位用于指示版本和变体。仅当使用具有加密强度的随机生成器实现时,这种UUID才是实用的。由规范定义为版本4 UUID。

uuid_generate_v5( namespace uuid, name text )与版本3相同,但使用SHA1哈希。由规范定义为版本5 UUID。

uuid_nil()一种特殊情况,所有位均设置为零00000000-0000-0000-0000-000000000000。用作未知UUID值的标志。

要比较类型,请参阅问题,使用哪个UUID版本?

如果您仅对版本4(随机生成)感兴趣,并且已经使用pgcrypto,请参阅bpieck的答案。

如果您对版本3和5感到好奇,请参阅此问题,生成v5 UUID。名称和名称空间是什么?。

有关更多讨论,请参见我对类似问题的解答以及我的博客文章JDBC到Postgres的UUID值。

评论


如何创建UUID类型的列,在Google中有1,000,000次点击。零命中率如何使该pk成为查询行! :-@

–克林特·伊斯特伍德
18年7月9日在17:31

@ClintEastwood对类似问题的“我的答案”,以及我的博客文章,从JDBC到Postgres的UUID值都可以为您提供帮助。如果证明不足,请发布新问题。我很乐意再试一次。我了解您的无奈!

–罗勒·布尔克
18年7月9日在19:30



@ClintEastwood:将UUID列与值进行比较的语法遵循手册中记录的常量的语法:postgresql.org/docs/current/static/…,并键入强制类型转换:postgresql.org/docs/current/static/…

– a_horse_with_no_name
18年7月9日在19:51

@BasilBourque:不必强制转换getObject()的结果,也可以使用UUID id = rs.getObject(“ uuid_”,UUID.class);

– a_horse_with_no_name
18年7月9日在19:53



@Rokit要验证随机数生成器的强度,请查看由此Postgres扩展包装的底层开源实现,这是我的答案中提到的OSSP uuid库项目。请记住,如果出于某些原因您不能选择其他类型,则只能将第四版UUID用作最后的手段。通常,通过调用uuid_generate_v1或uuid_generate_v1mc,您的首选应该是Version 1。

–罗勒·布尔克
19年1月19日在1:11



#2 楼


pgcrypto扩展

对Basil的非常详细的答案仅作了一点补充。

由于当前大多数人都在使用pgcrypto,因此您可以将uuid_generate_v4()用作版本4,而不是gen_random_uuid() UUID值。

首先,在Postgres中启用pgcrypto。

CREATE EXTENSION "pgcrypto";


只需将列的默认值设置为

DEFAULT gen_random_uuid()