web-dev-qa-db-ja.com

PostgreSQLにユーザー定義型が既に存在するかどうかを確認します

DBにユーザー定義型をいくつか作成したとします。

すなわちCREATE TYPE abc ...

ユーザー定義型が存在するかどうかを判断することは可能ですか?おそらく、postgres情報テーブルのいずれかを使用していますか?

これの主な理由は、PostgreSQLがCREATE OR REPLACE TYPE ...をサポートしていないようであり、特定のタイプが複数回作成された場合、最初に既存のタイプを削除してから新しいタイプを再ロードできるようにするためです。

52
Larry

ここに、単純なスクリプトで型を作成するための完全なソリューションを追加します。この目的のためだけに関数を作成する必要はありません。

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

@Cromaxの答えに触発され、スキーマに対処するこれまでに見つけた最も簡単な解決策は次のとおりです。

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

まさにあなたが本当に期待するかもしれないこと-現在のトランザクションを中止しないように、例外ハンドラーでCREATE TYPEステートメントをラップするだけです。

31
rog

pg_type テーブル:

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

それが当てはまる場合、abcが存在します。

18
mu is too short

実際、PostgresにはCREATE OR REPLACE型の機能。したがって、最善のアプローチはそれをドロップすることです:

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

シンプルなソリューションが常に最適です。

9
Nulik
-- 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();
-----------------------------------
4
Eloy Zuniga Jr.

@rogのジレンマを@bluishの答えに解決するには、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がスローされます。そのため、次の行ではそのエラーをキャッチしようとし、それが発生した場合は、新しいデータ型を作成します。

4
Cromax

私は同じことをしようとしています、型が存在することを確認してください。

_--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)
_

スキーマとsearch_path(私は)を使用している場合、おそらくpg_catalog.pg_type_is_visible(t.oid)チェックを保持する必要があります。 WHEREのすべての条件が何をしているのかはわかりませんが、それらは私のケースに関連しているようには見えませんでした。現在使用中:

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

より一般的なソリューション

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

そして、次のように呼び出すことができます:

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

0
Feki Zied