programing

사용자 정의 유형이 이미 PostgreSQL에 있는지 확인

copysource 2021. 1. 16. 20:41
반응형

사용자 정의 유형이 이미 PostgreSQL에 있는지 확인


DB에 사용자 정의 유형을 생성했다고 가정 해 보겠습니다.

CREATE TYPE abc ...

그러면 사용자 정의 유형이 존재하는지 여부를 판별 할 수 있습니까? 아마도 postgres 정보 테이블을 사용하고 있습니까?

그 주된 이유는 PostgreSQL이를 지원하지 않는 것 같고 CREATE OR REPLACE TYPE ...특정 유형이 두 번 이상 생성되면 기존 유형을 먼저 삭제 한 다음 새 유형을 다시로드 할 수 있기를 바랍니다.


이 목적을 위해 함수를 생성 할 필요없이 간단한 스크립트로 유형을 생성하기위한 완전한 솔루션을 여기에 추가합니다.

--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$$;

@Cromax의 답변에서 영감을 얻은 스키마에 대처하는 지금까지 찾은 가장 간단한 솔루션은 다음과 같습니다.

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

실제로 예상 할 수있는대로-CREATE TYPE 문을 예외 처리기에 래핑하여 현재 트랜잭션을 중단하지 않습니다.


pg_type에서 볼 수 있습니다 .

select exists (select 1 from pg_type where typname = 'abc');

그것이 사실이라면 abc존재합니다.


실제로 Postgres에는 CREATE OR REPLACE유형에 대한 기능 이 없습니다 . 따라서 가장 좋은 방법은 삭제하는 것입니다.

DROP TYPE IF EXISTS YOUR_TYPE;
CREATE TYPE YOUR_TYPE AS (
    id      integer,
    field   varchar
);

단순한 솔루션이 항상 최고의 솔루션입니다.


@bluish의 대답에 대한 @rog의 딜레마를 해결하려면 regtype데이터 유형 을 사용하는 것이 더 적절할 수 있습니다 . 이걸 고려하세요:

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절은 비슷 SELECT하지만 결과를 버리기 때문에 기본적으로 실제 등록 된 유형 으로 캐스트 할 수 있는지 'my_schema.my_type'(또는 'my_type'스키마에 특정하지 않은 경우) 확인합니다. 유형이 존재하면 "잘못된"일이 발생 RETURN하지 않으며 전체 블록이 종료되므로 유형 my_type이 이미 존재 하므로 변경 사항이 없습니다 . 그러나 캐스트가 불가능한 경우 42704레이블이있는 오류 코드가 발생합니다 undefined_object. 그래서 다음 줄에서 우리는 그 오류를 잡으려고 노력하고 만약 그럴 경우 우리는 단순히 새로운 데이터 유형을 생성합니다.


-- All of this to create a type if it does not exist
CREATE OR REPLACE FUNCTION create_abc_type() RETURNS integer AS $$
DECLARE v_exists INTEGER;

BEGIN
    SELECT into v_exists (SELECT 1 FROM pg_type WHERE typname = 'abc');
    IF v_exists IS NULL THEN
        CREATE TYPE abc AS ENUM ('height', 'weight', 'distance');
    END IF;
    RETURN v_exists;
END;
$$ LANGUAGE plpgsql;

-- Call the function you just created
SELECT create_abc_type();

-- Remove the function you just created
DROP function create_abc_type();
-----------------------------------

나는 똑같은 일을하려고 노력하고 있는데, 유형이 존재하는지 확인하십시오.

--echo-hidden( -E) 옵션으로 psql을 시작 하고 다음을 입력했습니다 \dT.

$ psql -E
psql (9.1.9)
testdb=> \dT
********* QUERY **********
SELECT n.nspname as "Schema",
  pg_catalog.format_type(t.oid, NULL) AS "Name",
  pg_catalog.obj_description(t.oid, 'pg_type') as "Description"
FROM pg_catalog.pg_type t
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))
  AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
      AND n.nspname <> 'pg_catalog'
      AND n.nspname <> 'information_schema'
  AND pg_catalog.pg_type_is_visible(t.oid)
ORDER BY 1, 2;
**************************
 List of data types
 Schema |       Name       | Description 
--------+------------------+-------------
 public | errmsg_agg_state | 
(1 row)

If you are using schemas and search_path (I am) then you'll probably need to keep the pg_catalog.pg_type_is_visible(t.oid) check. I don't know what all the conditions in the WHERE are doing, but they didn't seem relevant to my case. Currently using:

SELECT 1 FROM pg_catalog.pg_type as t
   WHERE typname = 'mytype' AND pg_catalog.pg_type_is_visible(t.oid);

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'')');

ReferenceURL : https://stackoverflow.com/questions/7624919/check-if-a-user-defined-type-already-exists-in-postgresql

반응형