假设我在数据库中创建了一些用户定义的类型,
即。 CREATE TYPE abc ...
是否可以确定用户定义的类型是否存在?也许,使用任何postgres信息表?
主要原因是因为PostgreSQL似乎不支持CREATE OR REPLACE TYPE ...
,并且如果某个类型被多次创建,我希望能够首先删除现有类型,然后重新加载新的。
答案 0 :(得分:73)
我在这里添加了在简单脚本中创建类型的完整解决方案,而无需为此目的创建函数。
--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$$;
答案 1 :(得分:24)
到目前为止,我发现的最简单的解决方案是在@ Cromax的答案的启发下应对模式:
DO $$ BEGIN
CREATE TYPE my_type AS (/* fields go here */);
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
正是您可能期望的 - 我们只是将CREATE TYPE语句包装在异常处理程序中,因此它不会中止当前事务。
答案 2 :(得分:16)
答案 3 :(得分:8)
事实上,Postgres没有类型的CREATE OR REPLACE
功能。所以最好的方法就是放弃它:
DROP TYPE IF EXISTS YOUR_TYPE;
CREATE TYPE YOUR_TYPE AS (
id integer,
field varchar
);
简单的解决方案始终是最好的解决方案。
答案 4 :(得分:3)
-- 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();
-----------------------------------
答案 5 :(得分:3)
要解决@ 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
。因此,在下一行中,我们尝试捕获该错误,如果发生这种情况,我们只需创建新的数据类型。
答案 6 :(得分:1)
我正在尝试做同样的事情,确保存在一种类型。
我使用--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);
答案 7 :(得分:0)
更通用的解决方案
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'')');
答案 8 :(得分:0)
另一种选择
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);
答案 9 :(得分:0)
这与模式配合得很好,并避免了异常处理:
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
$$;
答案 10 :(得分:0)
你应该试试这个:
SELECT * from pg_enum WHERE enumlabel='WHAT YOU WANT';