web-dev-qa-db-ja.com

テキストの配列をUUIDの配列にキャストする

textsの配列をUUIDsの配列にキャストするにはどうすればよいですか?

2つのテーブルjoinusersの間でprojectsを実行する必要があります。

usersテーブルには、プロジェクトIDをテキストとして含むproject_idsという名前の配列フィールドがあります。

projectsテーブルには、idという名前のUUIDフィールドがありました。

私の最初のアイデアは次のようなクエリでした。

SELECT * FROM projects
JOIN users ON
projects.id = ANY(users.project_ids)

しかし、users.project_idsUUIDsではないため、これは機能しません。

projects.id = ANY(users.project_ids::uuid[])

そして:

projects.id = ANY(ARRAY[users.project_ids]::uuid[])

しかしどちらも機能しません:

ERROR: invalid input syntax for type uuid: ""

更新

@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[];

生成する

エラー:列 "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[];

生成する

エラー:列「project_ids」のデフォルトは、タイプuuid []に自動的にキャストできません

列はデフォルトで空の配列に設定されます。

PGバージョン10.4を実行していますが、project_idsは現在text[] nullableです。

5
Sig

コメントされたように、列_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[];
_

誤って_uuid[]_ではなくuuidがありました。

この:

_ERROR: default for column "product_ids" cannot be cast automatically to type uuid[]
_

..は、列にデフォルト値が設定されていることを意味します。その式は自動的に変換できません。タイプを変更する前に削除してください。新しいDEFAULTは後で追加できます。

元の問題を修正

元の状況で効率的な修正は、空の文字列を配列から削除することです array_remove()beforeキャスト(Postgres 9.3以降が必要):

_SELECT *
FROM   users    u
JOIN   projects p ON p.id = ANY(array_remove(u.project_ids, '')::uuid[]);
_

...afterその_text[]_列に空の文字列が含まれる理由を調査します。

関連:

細かい点

  • クエリの_[INNER] JOIN_は、_projects_ids_に有効なプロジェクトがないユーザーを結果から削除します。通常は、これらもkeepしたいです。代わりに_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;
_

db <> fiddle here(大まかに基づいて McNetsのフィドル

関連:

3
create table users (user_id int, projects text[]);

insert into users values
(1, (array['a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
           'b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11'])::text[]);

insert into users values
(2, (array['a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
           'b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11',
           'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'])::text[]);

insert into users values
(3, (array['f0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
           '',
           'e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'])::text[]);
create table projects (project_id uuid);

insert into projects values
('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid),
('d0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid),
('e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid);

a_horse_with_no_name が指摘したように、配列要素に値がない場合は失敗します。変換できません。

select user_id, project_id
from   projects
join   users
on     project_id = any(projects::uuid[])
エラー:タイプuuidの無効な入力構文: "" 
 

ただし、project_idこのようにテキストとして:

select user_id, project_id
from   projects
join   users
on     project_id::text = any(projects);
 user_id | project_id 
 ------:| :----------------------------------- 
 1 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 
 2 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 
 3 | e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 

db <> fiddle ここ

または、配列を展開し(ネストを解除)、空/ null値を回避できます。

with usr as
(
    select user_id, unnest(projects) as project_id
    from   users
)
select user_id, projects.project_id
from   projects
join   usr
on     coalesce(usr.project_id, '') <> ''
and    usr.project_id::uuid = projects.project_id;
 user_id | project_id 
 ------:| :----------------------------------- 
 2 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 
 1 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 
 3 | e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 

db <> fiddle ここ

3
McNets