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ステートメントをラップするだけです。
実際、PostgresにはCREATE OR REPLACE
型の機能。したがって、最善のアプローチはそれをドロップすることです:
DROP TYPE IF EXISTS YOUR_TYPE;
CREATE TYPE YOUR_TYPE AS (
id integer,
field varchar
);
シンプルなソリューションが常に最適です。
-- 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();
-----------------------------------
@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
がスローされます。そのため、次の行ではそのエラーをキャッチしようとし、それが発生した場合は、新しいデータ型を作成します。
私は同じことをしようとしています、型が存在することを確認してください。
_--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);
_
より一般的なソリューション
_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'')');