Lar*_*rry 53 postgresql user-defined-types
假设我在DB中创建了一些用户定义的类型,
即 CREATE TYPE abc ...
那么可以确定用户定义的类型是否存在?也许,使用任何postgres信息表?
主要原因是因为PostgreSQL似乎不支持CREATE OR REPLACE TYPE ...,并且如果某个类型被多次创建,我希望能够先删除现有的类型,然后重新加载新的类型.
blu*_*ish 87
我在这里添加了在简单脚本中创建类型的完整解决方案,而无需为此目的创建函数.
--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$$;
Run Code Online (Sandbox Code Playgroud)
rog*_*rog 35
迄今为止我发现的最简单的解决方案是在@ Cromax的答案的启发下应对模式,这是:
DO $$ BEGIN
CREATE TYPE my_type AS (/* fields go here */);
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
Run Code Online (Sandbox Code Playgroud)
正是您可能期望的 - 我们只是将CREATE TYPE语句包装在异常处理程序中,因此它不会中止当前事务.
mu *_*ort 18
您可以查看pg_type表格:
select exists (select 1 from pg_type where typname = 'abc');
Run Code Online (Sandbox Code Playgroud)
如果这是真的那么abc存在.
实际上,Postgres没有CREATE OR REPLACE类型的功能.所以最好的办法是放弃它:
DROP TYPE IF EXISTS YOUR_TYPE;
CREATE TYPE YOUR_TYPE AS (
id integer,
field varchar
);
Run Code Online (Sandbox Code Playgroud)
简单的解决方案总是最好的.
-- 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();
-----------------------------------
Run Code Online (Sandbox Code Playgroud)
受@Cromax答案的启发,这里有一个使用系统目录信息函数的替代解决方案to_regtype,它避免了异常子句的额外开销,但仍然检查类型是否存在的正确模式:
DO $$ BEGIN
IF to_regtype('my_schema.abc') IS NULL THEN
CREATE TYPE my_schema.abc ... ;
END IF;
END $$;
Run Code Online (Sandbox Code Playgroud)
在使用默认模式的情况下public,它看起来像:
DO $$ BEGIN
IF to_regtype('abc') IS NULL THEN
CREATE TYPE abc ... ;
END IF;
END $$;
Run Code Online (Sandbox Code Playgroud)
为了解决@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 $$;
Run Code Online (Sandbox Code Playgroud)
PERFORM子句类似于SELECT,但它会丢弃结果,因此基本上我们正在检查是否有可能将其强制转换为'my_schema.my_type'(或只是'my_type'不关心特定于模式的)实际注册类型。如果确实存在该类型,则不会发生任何“错误”,并且由于RETURN整个块而将结束-由于该类型my_type已经存在,因此不会进行任何更改。但是,如果无法进行强制转换,则会抛出42704带有标记为的错误代码undefined_object。因此,在接下来的几行中,我们尝试捕获该错误,如果发生这种情况,我们只需创建新的数据类型。