I want to copy data from one table in schema "test" to another table in schema "public". Both tables are identical, but the field "type" is a custom type named "item_type". The types are defined within their schema. Both types are also the same, except they belong to two different schemas.
What I tried:
INSERT INTO public.item
SELECT itemid, collectionid, signature, CAST(type AS public.item_type), status
FROM test.item
WHERE status like 'OK%'
ON CONFLICT DO NOTHING;
However I get the following error:
ERROR: cannot cast type test.item_type to item_type
LINE 2: SELECT itemid, collectionid, signature, CAST(type AS pu...
How can I solve this?
Edit:
The custom type looks like this:
CREATE TYPE test.item_type AS ENUM
('image', 'audio', 'video', 'application', 'text');
2
Answers
Because
test.item_type
is a custom type, the PostgreSQL doesn’t have knowledge of how it should convert it to a different custom typepublic.item_type
.You must provide instructions for the PostgreSQL how to convert from one type to another.
One way is to create a function for that:
Later you can use it to provide a valid value for the
public.item
:To be able to simply cast, you must define a new CAST (see the Docs ).
That way define how the
test.item_type
should be converted topublic.item_type
.Now the query
runs without errors.
Feel free to explore full test case at db<>fiddle
Lastly I’d like to suggest of not using
private.item_type
at all. Why not create a tableprivate.item
with type ofpublic.item_type
?.. It seems unnecessary…Some additions to Julius‘ answer:
it seems most convenient if you just use the intermediate cast directly in your
insert
, whenever you deal with directly mappable types:Technically, there’s no difference if you do that or (re)define all your casts before copying the data over. If that’s a one-off job, those definitions only add extra steps.
If you do want to set them up, you can actually get away without (explicit) casting entirely, and save some (re)definitions thanks to a single, polymorphic function: demo
AS IMPLICIT
lets PostgreSQL detect and use the cast on its own, letting you simply