跳到主要内容
跳到主要内容

处理UUID的函数

UUIDv7生成

生成的UUID包含一个48位的Unix毫秒时间戳,后跟版本“7”(4位),一个计数器(42位)以区分同一毫秒内的UUID(包括一个变体字段“2”,2位)和一个随机字段(32位)。 对于任何给定的时间戳(unix_ts_ms),计数器从一个随机值开始,并在时间戳变化之前每生成一个新的UUID时递增1。如果计数器溢出,时间戳字段会增加1,并且计数器重置为一个随机的新起始值。 UUID生成函数确保在并发运行的线程和查询中,时间戳内的计数器字段在所有函数调用中单调递增。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|                           unix_ts_ms                          |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|          unix_ts_ms           |  ver  |   counter_high_bits   |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|var|                   counter_low_bits                        |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|                            rand_b                             |
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

雪花ID生成

生成的雪花ID包含当前Unix时间戳(以毫秒为单位,41 + 1位高零位),后跟机器ID(10位)和一个计数器(12位)以区分同一毫秒内的ID。对于任何给定的时间戳(unix_ts_ms),计数器从0开始,并在时间戳变化之前每生成一个新的雪花ID时递增1。如果计数器溢出,时间戳字段会增加1,计数器重置为0。

备注

生成的雪花ID基于UNIX纪元1970-01-01。虽然没有标准或推荐的雪花ID纪元,但其他系统中的实现可能使用不同的纪元,例如Twitter/X(2010-11-04)或Mastodon(2015-01-01)。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|0|                         timestamp                           |
├─┼                 ┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|                   |     machine_id    |    machine_seq_num    |
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

generateUUIDv4

生成一个版本4UUID

语法

generateUUIDv4([expr])

参数

  • expr — 一个任意的表达式,用于绕过常见子表达式消除在查询中多次调用该函数时。表达式的值对返回的UUID没有影响。可选。

返回值

UUIDv4类型的值。

示例

首先,创建一个包含UUID类型列的表,然后将生成的UUIDv4插入到表中。

CREATE TABLE tab (uuid UUID) ENGINE = Memory;

INSERT INTO tab SELECT generateUUIDv4();

SELECT * FROM tab;

结果:

┌─────────────────────────────────uuid─┐
│ f4bf890f-f9dc-4332-ad5c-0c18e73f28e9 │
└──────────────────────────────────────┘

每行生成多个UUID的示例

SELECT generateUUIDv4(1), generateUUIDv4(2);

┌─generateUUIDv4(1)────────────────────┬─generateUUIDv4(2)────────────────────┐
│ 2d49dc6e-ddce-4cd0-afb8-790956df54c1 │ 8abf8c13-7dea-4fdf-af3e-0e18767770e6 │
└──────────────────────────────────────┴──────────────────────────────────────┘

generateUUIDv7

生成一个版本7UUID

有关UUID结构、计数器管理和并发保证的详细信息,请参阅"UUIDv7生成"

备注

截至2024年4月,版本7 UUID处于草案状态,其布局可能会在未来发生变化。

语法

generateUUIDv7([expr])

参数

  • expr — 一个任意的表达式,用于绕过常见子表达式消除在查询中多次调用该函数时。表达式的值对返回的UUID没有影响。可选。

返回值

UUIDv7类型的值。

示例

首先,创建一个包含UUID类型列的表,然后将生成的UUIDv7插入到表中。

CREATE TABLE tab (uuid UUID) ENGINE = Memory;

INSERT INTO tab SELECT generateUUIDv7();

SELECT * FROM tab;

结果:

┌─────────────────────────────────uuid─┐
│ 018f05af-f4a8-778f-beee-1bedbc95c93b │
└──────────────────────────────────────┘

每行生成多个UUID的示例

SELECT generateUUIDv7(1), generateUUIDv7(2);

┌─generateUUIDv7(1)────────────────────┬─generateUUIDv7(2)────────────────────┐
│ 018f05c9-4ab8-7b86-b64e-c9f03fbd45d1 │ 018f05c9-4ab8-7b86-b64e-c9f12efb7e16 │
└──────────────────────────────────────┴──────────────────────────────────────┘

dateTimeToUUIDv7

将给定时间的DateTime值转换为UUIDv7

有关UUID结构、计数器管理和并发保证的详细信息,请参阅"UUIDv7生成"

备注

截至2024年4月,版本7 UUID处于草案状态,其布局可能会在未来发生变化。

语法

dateTimeToUUIDv7(value)

参数

  • value — 日期和时间。 DateTime

返回值

UUIDv7类型的值。

示例

SELECT dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai'));

结果:

┌─dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai'))─┐
│ 018f05af-f4a8-778f-beee-1bedbc95c93b                                   │
└─────────────────────────────────────────────────────────────────────────┘

对于相同时间戳生成多个UUID的示例

SELECT dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56'));
SELECT dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56'));

结果

   ┌─dateTimeToUUIDv7(t⋯08-15 18:57:56'))─┐
1. │ 017b4b2d-7720-76ed-ae44-bbcc23a8c550 │
   └──────────────────────────────────────┘

   ┌─dateTimeToUUIDv7(t⋯08-15 18:57:56'))─┐
1. │ 017b4b2d-7720-76ed-ae44-bbcf71ed0fd3 │
   └──────────────────────────────────────┘

该函数确保对相同时间戳的多次调用生成唯一的、单调递增的UUID。

empty

检查输入的UUID是否为空。

语法

empty(UUID)

如果UUID全部为零(零UUID),则认为其为空。

该函数也适用于数组字符串

参数

  • x — 一个UUID。 UUID

返回值

  • 对于空UUID返回1,对于非空UUID返回0UInt8

示例

要生成UUID值,ClickHouse提供了generateUUIDv4函数。

查询:

SELECT empty(generateUUIDv4());

结果:

┌─empty(generateUUIDv4())─┐
│                       0 │
└─────────────────────────┘

notEmpty

检查输入的UUID是否非空。

语法

notEmpty(UUID)

如果UUID全部为零(零UUID),则认为其为空。

该函数也适用于数组字符串

参数

  • x — 一个UUID。 UUID

返回值

  • 对于非空UUID返回1,对于空UUID返回0UInt8

示例

要生成UUID值,ClickHouse提供了generateUUIDv4函数。

查询:

SELECT notEmpty(generateUUIDv4());

结果:

┌─notEmpty(generateUUIDv4())─┐
│                          1 │
└────────────────────────────┘

toUUID

将字符串类型的值转换为UUID。

toUUID(string)

返回值

UUID类型值。

使用示例

SELECT toUUID('61f0c404-5cb3-11e7-907b-a6006ad3dba0') AS uuid

结果:

┌─────────────────────────────────uuid─┐
│ 61f0c404-5cb3-11e7-907b-a6006ad3dba0 │
└──────────────────────────────────────┘

toUUIDOrDefault

参数

  • string — 36个字符或FixedString(36)的字符串。字符串
  • default — 如果第一个参数无法转换为UUID类型,则用作默认值的UUID。UUID

返回值

UUID

toUUIDOrDefault(string, default)

返回值

UUID类型值。

使用示例

第一个示例返回可以转换为UUID类型的第一个参数:

SELECT toUUIDOrDefault('61f0c404-5cb3-11e7-907b-a6006ad3dba0', cast('59f0c404-5cb3-11e7-907b-a6006ad3dba0' AS UUID));

结果:

┌─toUUIDOrDefault('61f0c404-5cb3-11e7-907b-a6006ad3dba0', CAST('59f0c404-5cb3-11e7-907b-a6006ad3dba0', 'UUID'))─┐
│ 61f0c404-5cb3-11e7-907b-a6006ad3dba0                                                                          │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

第二个示例返回第二个参数(提供的默认UUID),因为第一个参数无法转换为UUID类型:

SELECT toUUIDOrDefault('-----61f0c404-5cb3-11e7-907b-a6006ad3dba0', cast('59f0c404-5cb3-11e7-907b-a6006ad3dba0' AS UUID));

结果:

┌─toUUIDOrDefault('-----61f0c404-5cb3-11e7-907b-a6006ad3dba0', CAST('59f0c404-5cb3-11e7-907b-a6006ad3dba0', 'UUID'))─┐
│ 59f0c404-5cb3-11e7-907b-a6006ad3dba0                                                                               │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

toUUIDOrNull

接受一个字符串类型的参数,并尝试将其解析为UUID。如果失败,则返回NULL。

toUUIDOrNull(string)

返回值

Nullable(UUID)类型的值。

使用示例

SELECT toUUIDOrNull('61f0c404-5cb3-11e7-907b-a6006ad3dba0T') AS uuid

结果:

┌─uuid─┐
│ ᴺᵁᴸᴸ │
└──────┘

toUUIDOrZero

接受一个字符串类型的参数,并尝试将其解析为UUID。如果失败,则返回零UUID。

toUUIDOrZero(string)

返回值

UUID类型值。

使用示例

SELECT toUUIDOrZero('61f0c404-5cb3-11e7-907b-a6006ad3dba0T') AS uuid

结果:

┌─────────────────────────────────uuid─┐
│ 00000000-0000-0000-0000-000000000000 │
└──────────────────────────────────────┘

UUIDStringToNum

接受一个包含36个字符的string,格式为xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,并返回一个FixedString(16)作为其二进制表示,可以选择性地通过variant指定格式(默认是Big-endian)。

语法

UUIDStringToNum(string[, variant = 1])

参数

  • string — 一种字符串,包含36个字符或FixedString
  • variant — 整数,表示按照RFC4122指定的变体。1 = Big-endian(默认),2 = Microsoft

返回值

FixedString(16)

使用示例

SELECT
    '612f3c40-5d3b-217e-707b-6a546a3d7b29' AS uuid,
    UUIDStringToNum(uuid) AS bytes

结果:

┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ a/<@];!~p{jTj={) │
└──────────────────────────────────────┴──────────────────┘
SELECT
    '612f3c40-5d3b-217e-707b-6a546a3d7b29' AS uuid,
    UUIDStringToNum(uuid, 2) AS bytes

结果:

┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ @</a;]~!p{jTj={) │
└──────────────────────────────────────┴──────────────────┘

UUIDNumToString

接受一个包含UUID二进制表示的binary,可以选择性地通过variant指定格式(默认是Big-endian),并返回一个包含36个字符的字符串。

语法

UUIDNumToString(binary[, variant = 1])

参数

  • binaryFixedString(16),作为UUID的二进制表示。
  • variant — 整数,表示按照RFC4122指定的变体。1 = Big-endian(默认),2 = Microsoft

返回值

字符串。

使用示例

SELECT
    'a/<@];!~p{jTj={)' AS bytes,
    UUIDNumToString(toFixedString(bytes, 16)) AS uuid

结果:

┌─bytes────────────┬─uuid─────────────────────────────────┐
│ a/<@];!~p{jTj={) │ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │
└──────────────────┴──────────────────────────────────────┘
SELECT
    '@</a;]~!p{jTj={)' AS bytes,
    UUIDNumToString(toFixedString(bytes, 16), 2) AS uuid

结果:

┌─bytes────────────┬─uuid─────────────────────────────────┐
│ @</a;]~!p{jTj={) │ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │
└──────────────────┴──────────────────────────────────────┘

UUIDToNum

接受一个UUID,并返回其二进制表示,作为FixedString(16),可以选择性地通过variant指定格式(默认是Big-endian)。该函数替代了对两个单独函数的调用UUIDStringToNum(toString(uuid)),因此无需将UUID转换为字符串以提取字节。

语法

UUIDToNum(uuid[, variant = 1])

参数

  • uuidUUID
  • variant — 整数,表示按照RFC4122指定的变体。1 = Big-endian(默认),2 = Microsoft

返回值

UUID的二进制表示。

使用示例

SELECT
    toUUID('612f3c40-5d3b-217e-707b-6a546a3d7b29') AS uuid,
    UUIDToNum(uuid) AS bytes

结果:

┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ a/<@];!~p{jTj={) │
└──────────────────────────────────────┴──────────────────┘
SELECT
    toUUID('612f3c40-5d3b-217e-707b-6a546a3d7b29') AS uuid,
    UUIDToNum(uuid, 2) AS bytes

结果:

┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ @</a;]~!p{jTj={) │
└──────────────────────────────────────┴──────────────────┘

UUIDv7ToDateTime

返回UUID版本7的时间戳组件。

语法

UUIDv7ToDateTime(uuid[, timezone])

参数

返回值

  • 带有毫秒精度的时间戳。如果UUID不是有效的版本7 UUID,则返回1970-01-01 00:00:00.000。 DateTime64(3)

使用示例

SELECT UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'))

结果:

┌─UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'))─┐
│                                          2024-04-22 15:30:29.048 │
└──────────────────────────────────────────────────────────────────┘
SELECT UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'), 'America/New_York')

结果:

┌─UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'), 'America/New_York')─┐
│                                                              2024-04-22 08:30:29.048 │
└──────────────────────────────────────────────────────────────────────────────────────┘

serverUUID

返回在ClickHouse服务器首次启动时生成的随机UUID。该UUID存储在ClickHouse服务器目录(例如/var/lib/clickhouse/)中的文件uuid中,并在服务器重启之间保留。

语法

serverUUID()

返回值

  • 服务器的UUID。 UUID

generateSnowflakeID

生成一个雪花ID。 该函数确保在并发运行的线程和查询中,时间戳内的计数器字段在所有函数调用中单调递增。

有关实现的详细信息,请参阅"雪花ID生成"

语法

generateSnowflakeID([expr, [machine_id]])

参数

  • expr — 一个任意的表达式,用于绕过常见子表达式消除在查询中多次调用该函数时。表达式的值对返回的雪花ID没有影响。可选。
  • machine_id — 一个机器ID,使用最低的10位。Int64。可选。

返回值

UInt64类型的值。

示例

首先,创建一个包含UInt64类型列的表,然后将生成的雪花ID插入到表中。

CREATE TABLE tab (id UInt64) ENGINE = Memory;

INSERT INTO tab SELECT generateSnowflakeID();

SELECT * FROM tab;

结果:

┌──────────────────id─┐
│ 7199081390080409600 │
└─────────────────────┘

每行生成多个雪花ID的示例

SELECT generateSnowflakeID(1), generateSnowflakeID(2);

┌─generateSnowflakeID(1)─┬─generateSnowflakeID(2)─┐
│    7199081609652224000 │    7199081609652224001 │
└────────────────────────┴────────────────────────┘

带有表达式和机器ID的示例

SELECT generateSnowflakeID('expr', 1);

┌─generateSnowflakeID('expr', 1)─┐
│            7201148511606784002 │
└────────────────────────────────┘

snowflakeToDateTime

Deprecated feature
警告

该函数已弃用,仅在启用设置allow_deprecated_snowflake_conversion_functions时可用。 该函数将在未来某个时刻被移除。

请改用函数snowflakeIDToDateTime

提取Sowflake ID的时间戳组件,格式为DateTime

语法

snowflakeToDateTime(value[, time_zone])

参数

  • value — 雪花ID。 Int64
  • time_zone时区。该函数根据时区解析time_string。可选。 字符串

返回值

  • value的时间戳组件,格式为DateTime值。

示例

查询:

SELECT snowflakeToDateTime(CAST('1426860702823350272', 'Int64'), 'UTC');

结果:


┌─snowflakeToDateTime(CAST('1426860702823350272', 'Int64'), 'UTC')─┐
│                                              2021-08-15 10:57:56 │
└──────────────────────────────────────────────────────────────────┘

snowflakeToDateTime64

Deprecated feature
警告

该函数已弃用,仅在启用设置allow_deprecated_snowflake_conversion_functions时可用。 该函数将在未来某个时刻被移除。

请改用函数snowflakeIDToDateTime64

提取Sowflake ID的时间戳组件,格式为DateTime64

语法

snowflakeToDateTime64(value[, time_zone])

参数

  • value — 雪花ID。 Int64
  • time_zone时区。该函数根据时区解析time_string。可选。 字符串

返回值

  • value的时间戳组件,格式为DateTime64,其比例 = 3,即毫秒精度。

示例

查询:

SELECT snowflakeToDateTime64(CAST('1426860802823350272', 'Int64'), 'UTC');

结果:


┌─snowflakeToDateTime64(CAST('1426860802823350272', 'Int64'), 'UTC')─┐
│                                            2021-08-15 10:58:19.841 │
└────────────────────────────────────────────────────────────────────┘

dateTimeToSnowflake

Deprecated feature
警告

该函数已弃用,仅在启用设置allow_deprecated_snowflake_conversion_functions时可用。 该函数将在未来某个时刻被移除。

请改用函数dateTimeToSnowflakeID

DateTime值转换为给定时间的第一个雪花ID

语法

dateTimeToSnowflake(value)

参数

  • value — 日期和时间。DateTime

返回值

  • 输入值转换为Int64数据类型,作为该时间的第一个雪花ID。

示例

查询:

WITH toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai') AS dt SELECT dateTimeToSnowflake(dt);

结果:

┌─dateTimeToSnowflake(dt)─┐
│     1426860702823350272 │
└─────────────────────────┘

dateTime64ToSnowflake

Deprecated feature
警告

该函数已弃用,仅在启用设置allow_deprecated_snowflake_conversion_functions时可用。 该函数将在未来某个时刻被移除。

请改用函数dateTime64ToSnowflakeID

DateTime64转换为给定时间的第一个雪花ID

语法

dateTime64ToSnowflake(value)

参数

返回值

  • 输入值转换为Int64数据类型,作为该时间的第一个雪花ID。

示例

查询:

WITH toDateTime64('2021-08-15 18:57:56.492', 3, 'Asia/Shanghai') AS dt64 SELECT dateTime64ToSnowflake(dt64);

结果:

┌─dateTime64ToSnowflake(dt64)─┐
│         1426860704886947840 │
└─────────────────────────────┘

snowflakeIDToDateTime

返回Sowflake ID的时间戳组件,类型为DateTime

语法

snowflakeIDToDateTime(value[, epoch[, time_zone]])

参数

  • value — 雪花ID。 UInt64
  • epoch - 雪花ID的纪元,以毫秒为单位,自1970-01-01起计算。默认为0(1970-01-01)。对于Twitter/X纪元(2015-01-01),提供1288834974657。可选。UInt*
  • time_zone时区。该函数根据时区解析time_string。可选。字符串

返回值

  • value的时间戳组件类型为DateTime的值。

示例

查询:

SELECT snowflakeIDToDateTime(7204436857747984384) AS res

结果:

┌─────────────────res─┐
│ 2024-06-06 10:59:58 │
└─────────────────────┘

snowflakeIDToDateTime64

返回Sowflake ID的时间戳组件,类型为DateTime64

语法

snowflakeIDToDateTime64(value[, epoch[, time_zone]])

参数

  • value — 雪花ID。 UInt64
  • epoch - 雪花ID的纪元,以毫秒为单位,自1970-01-01起计算。默认为0(1970-01-01)。对于Twitter/X纪元(2015-01-01),提供1288834974657。可选。UInt*
  • time_zone时区。该函数根据时区解析time_string。可选。字符串

返回值

  • value的时间戳组件,类型为DateTime64,其精度为3,即毫秒精度。

示例

查询:

SELECT snowflakeIDToDateTime64(7204436857747984384) AS res

结果:

┌─────────────────res─┐
│ 2024-06-06 10:59:58 │
└─────────────────────┘

dateTimeToSnowflakeID

DateTime值转换为给定时间的第一个雪花ID

语法

dateTimeToSnowflakeID(value[, epoch])

参数

  • value — 日期和时间。DateTime
  • epoch - 雪花ID的纪元,以毫秒为单位,自1970-01-01起计算。默认为0(1970-01-01)。对于Twitter/X纪元(2015-01-01),提供1288834974657。可选。UInt*

返回值

  • 输入值转换为UInt64,作为该时间的第一个雪花ID。

示例

查询:

SELECT toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai') AS dt, dateTimeToSnowflakeID(dt) AS res;

结果:

┌──────────────────dt─┬─────────────────res─┐
│ 2021-08-15 18:57:56 │ 6832626392367104000 │
└─────────────────────┴─────────────────────┘

dateTime64ToSnowflakeID

DateTime64转换为给定时间的第一个雪花ID

语法

dateTime64ToSnowflakeID(value[, epoch])

参数

  • value — 日期和时间。DateTime64
  • epoch - 雪花ID的纪元,以毫秒为单位,自1970-01-01起计算。默认为0(1970-01-01)。对于Twitter/X纪元(2015-01-01),提供1288834974657。可选。UInt*

返回值

  • 输入值转换为UInt64,作为该时间的第一个雪花ID。

示例

查询:

SELECT toDateTime('2021-08-15 18:57:56.493', 3, 'Asia/Shanghai') AS dt, dateTime64ToSnowflakeID(dt) AS res;

结果:

┌──────────────────────dt─┬─────────────────res─┐
│ 2021-08-15 18:57:56.493 │ 6832626394434895872 │
└─────────────────────────┴─────────────────────┘

另请参阅