将文本数组转换为 UUID 数组

Sig*_*Sig 5 postgresql join cast array uuid

如何将texts 数组转换为UUIDs数组?

我需要join在两个表之间做一个:usersprojects

users表有一个名为的数组字段,project_ids其中包含作为文本的项目 ID。

projects表有一个名为 的 UUID 字段id

我最初的想法是一个查询看起来像:

SELECT * FROM projects
JOIN users ON
projects.id = ANY(users.project_ids)
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为users.project_ids不是,UUID所以我试过:

projects.id = ANY(users.project_ids::uuid[])
Run Code Online (Sandbox Code Playgroud)

乃至:

projects.id = ANY(ARRAY[users.project_ids]::uuid[])
Run Code Online (Sandbox Code Playgroud)

但没有一个有效:

ERROR: invalid input syntax for type uuid: ""
Run Code Online (Sandbox Code Playgroud)

更新

@a_horse_with_no_name 绝对正确。最好的选择应该是使用一组 UUID。

现在的问题是我如何可以改变的阵列text到阵列uuid

users表当前为空(0 条记录)。

我试过了

ALTER TABLE "users" ALTER COLUMN "project_ids" SET DATA TYPE UUID USING "project_ids"::uuid[];
Run Code Online (Sandbox Code Playgroud)

这产生

错误:无法将列“product_ids”的 USING 子句的结果自动转换为类型 uuid 提示:您可能需要添加显式转换。

ALTER TABLE "users" ALTER COLUMN "product_ids" SET DATA TYPE UUID USING "product_ids"::UUID;

我也试过

ALTER TABLE "users" ALTER COLUMN "project_ids" SET DATA TYPE UUID[] USING "project_ids"::uuid[];
Run Code Online (Sandbox Code Playgroud)

这产生

错误:列“project_ids”的默认值无法自动转换为类型 uuid[]

该列默认设置为空数组。

我正在运行 PG 10.4 版,project_ids目前是text[] nullable.

Erw*_*ter 9

正如已评论的那样,该列project_ids应该是uuid[],这可以排除该问题。这也会更加高效。

要更改(如您所断言的列中没有非法数据):

ALTER TABLE users ALTER COLUMN project_ids DROP DEFAULT;

ALTER TABLE users
ALTER COLUMN project_ids SET DATA TYPE uuid[] USING project_ids::uuid[];
Run Code Online (Sandbox Code Playgroud)

你有uuid而不是uuid[]错误。

和这个:

错误:列“product_ids”的默认值无法自动转换为 uuid[] 类型

.. 意味着您为该列设置了默认值。该表达式无法自动转换。在更改类型之前将其删除。您可以稍后添加新的DEFAULT

修复原来的问题

在原始情况下,有效的解决方法是在转换之前从数组中删除空字符串(需要 Postgres 9.3+):array_remove()

SELECT *
FROM   users    u
JOIN   projects p ON p.id = ANY(array_remove(u.project_ids, '')::uuid[]);
Run Code Online (Sandbox Code Playgroud)

...调查了为什么该列中可能有空刺之后text[]

有关的:

细点

[INNER] JOIN查询中的 会从结果中删除没有有效项目的用户projects_ids。通常,您也想保留这些:使用LEFT [OUTER] JOIN替代(与users第一个)。

无论哪种方式,折叠JOIN都会重复条目,这可能会或可能不会如您所愿。如果您想表示重复的条目,请在连接之前取消嵌套。

如果您的目标只是将 ID 数组解析为项目名称数组,您还需要保留数组元素的原始顺序:

SELECT *
FROM   users u
LEFT   JOIN LATERAL (
   SELECT ARRAY(
      SELECT project_name  -- use the actual column(s) of your case
      FROM   unnest (array_remove(u.project_ids, '')::uuid[]) WITH ORDINALITY AS p(id, ord)
      JOIN   projects USING (id)
      ORDER  BY ord
      )
   ) p(projects) ON true;
Run Code Online (Sandbox Code Playgroud)

db<>fiddle这里(松散地基于McNets 的 fiddle

有关的:


归档时间:

查看次数:

19640 次

最近记录:

5 年,6 月 前