Check if a user-defined type already exists in PostgreSQL

后端 未结 10 1531
离开以前
离开以前 2020-12-29 01:43

Say I have created some user-defined types in the DB,

i.e. CREATE TYPE abc ...

Is it then possible to determine if the user-defined type exists

相关标签:
10条回答
  • 2020-12-29 02:21

    I add here the complete solution for creating types in a simple script, without the need of creating a function just for this purpose.

    --create types
    DO $$
    BEGIN
        IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'my_type') THEN
            CREATE TYPE my_type AS
            (
                --my fields here...
            );
        END IF;
        --more types here...
    END$$;
    
    0 讨论(0)
  • 2020-12-29 02:24

    To solve @rog's dilemma to @bluish's answer it could be more appropriate to make use of regtype data type. Consider this:

    DO $$ BEGIN
        PERFORM 'my_schema.my_type'::regtype;
    EXCEPTION
        WHEN undefined_object THEN
            CREATE TYPE my_schema.my_type AS (/* fields go here */);
    END $$;
    

    PERFORM clause is like SELECT, but it discards results, so basically we're checking if it is possible to cast 'my_schema.my_type' (or just 'my_type' if you don't care to be schema specific) to actual registered type. If the type does exist, then nothing "wrong" will happen and because of RETURN whole block will end—no changes, since the type my_type is already there. But if the cast is not possible, then there will be thrown error code 42704 which has label of undefined_object. So in the next lines we try to catch that error and if that happens, we simply create our new data type.

    0 讨论(0)
  • 2020-12-29 02:27

    Another alternative

    WITH namespace AS(
        SELECT oid 
            FROM pg_namespace 
            WHERE nspname = 'my_schema'
    ),
    type_name AS (
        SELECT 1 type_exist  
            FROM pg_type 
            WHERE typname = 'my_type' AND typnamespace = (SELECT * FROM namespace)
    )
    SELECT EXISTS (SELECT * FROM type_name);
    
    0 讨论(0)
  • 2020-12-29 02:37

    This plays well with schemas, and avoids exception handling:

    DO $$
    BEGIN
        IF NOT EXISTS (
          SELECT 1 FROM pg_type t
          LEFT JOIN pg_namespace p ON t.typnamespace=p.oid
          WHERE t.typname='my_type' AND p.nspname='my_schema'
        ) THEN
            CREATE TYPE my_schema.my_type AS (/* fields go here */);
        END IF;
    END
    $$;
    
    0 讨论(0)
  • 2020-12-29 02:39

    The simplest solution I've found so far that copes with schemas, inspired by @Cromax's answer, is this:

    DO $$ BEGIN
        CREATE TYPE my_type AS (/* fields go here */);
    EXCEPTION
        WHEN duplicate_object THEN null;
    END $$;
    

    Just what you might expect really - we just wrap the CREATE TYPE statement in an exception handler so it doesn't abort the current transaction.

    0 讨论(0)
  • 2020-12-29 02:39

    A more generic solution

    CREATE OR REPLACE FUNCTION create_type(name text, _type text) RETURNS 
    integer AS $$
    DECLARE v_exists INTEGER;
    
    BEGIN
        SELECT into v_exists (SELECT 1 FROM pg_type WHERE typname = name);
        IF v_exists IS NULL THEN
                EXECUTE format('CREATE TYPE %I AS %s', name, _type);
        END IF;
        RETURN v_exists;
    END;
    $$ LANGUAGE plpgsql;
    

    and then you can call it like this:

    select create_type('lwm2m_instancetype', 'enum (''single'',''multiple'')');

    0 讨论(0)
提交回复
热议问题