我正在尝试在存储过程中测试序列是否已存在。
IF EXISTS SEQUENCE seq_name
RAISE EXCEPTION 'sequence % already exists!', seq_name
END IF;
我已经尝试了几个不同的上述代码段而没有运气。我必须向谷歌提供错误的条款,因为我似乎无法找到关于该主题的任何内容。任何帮助表示赞赏!
答案 0 :(得分:22)
您应该能够查询pg_class表以查看relname是否存在。
IF EXISTS (SELECT 0 FROM pg_class where relname = '<my sequence name here>' )
THEN
--stuff here
END IF;
答案 1 :(得分:18)
@rfusca的答案如果您确定该名称只对序列有效(即您确信它不会用于普通表,索引,视图,复合类型,TOAST),则有效表或外表),并且您不关心多个模式。换句话说,它适用于大多数常见情况,但并不完全严格。
如果要测试特定架构中是否存在该名称的序列,则应该可以这样做:
-- Clear the search path so that the regclass of the sequence
-- will be schema-qualified.
SET search_path = '';
-- Do your conditional code.
IF EXISTS (SELECT * FROM pg_class
WHERE relkind = 'S'
AND oid::regclass::text = 'public.' || quote_ident(seq_name))
THEN
RAISE EXCEPTION 'sequence public.% already exists!', seq_name
END IF;
-- Restore the normal search path.
RESET search_path;
答案 2 :(得分:12)
更新:在Postgres 9.4 中使用to_regclass()
简单地测试存在变得更加简单:
SELECT to_regclass('schema_name.table_name');
但请阅读详细信息:
您需要检查与名称冲突的任何表格式对象,而不仅仅是序列。
如果名称可用,此函数会创建一个新序列,并在其他情况下分别发出有意义的NOTICE
/ WARNING
/ EXCEPTION
:
CREATE OR REPLACE FUNCTION f_create_seq(_seq text, _schema text = NULL)
RETURNS void AS
$func$
DECLARE
_fullname text := format('%I.%I', COALESCE(_schema,current_schema),_seq);
_relkind "char" := (SELECT c.relkind
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
WHERE n.nspname = COALESCE(_schema, current_schema)
AND c.relname = _seq);
BEGIN
IF _relkind IS NULL THEN -- name is free
EXECUTE 'CREATE SEQUENCE ' || _fullname;
RAISE NOTICE 'New sequence % created.', _fullname;
ELSIF _relkind = 'S' THEN -- 'S' = sequence
IF has_sequence_privilege(_fullname, 'USAGE') THEN
RAISE WARNING 'Sequence % already exists.', _fullname;
ELSE
RAISE EXCEPTION
'Sequence % already exists but you have no USAGE privilege.'
, _fullname;
END IF;
ELSE
RAISE EXCEPTION 'A(n) "%" named % already exists.'
-- Table-like objects in pg 9.4:
-- www.postgresql.org/docs/current/static/catalog-pg-class.html
, CASE _relkind WHEN 'r' THEN 'ordinary table'
WHEN 'i' THEN 'index'
-- WHEN 'S' THEN 'sequence' -- impossible here
WHEN 'v' THEN 'view'
WHEN 'm' THEN 'materialized view'
WHEN 'c' THEN 'composite type'
WHEN 't' THEN 'TOAST table'
WHEN 'f' THEN 'foreign table'
ELSE 'unknown object' END
, _fullname;
END IF;
END
$func$ LANGUAGE plpgsql;
COMMENT ON FUNCTION f_create_seq(text, text) IS
'Create sequence if name is free.
RAISE NOTICE on successful creation.
RAISE WARNING if it already exists.
RAISE EXCEPTION if it already exists and current user lacks USAGE privilege.
RAISE EXCEPTION if object of a different kind occupies the name.
$1 _seq .. sequence name
$2 _schema .. schema name (optional; default is CURRENT_SCHEMA)';
呼叫:
SELECT f_create_seq('myseq', 'myschema');
或者:
SELECT f_create_seq('myseq1'); -- defaults to current schema
同时阅读代码末尾的函数注释。
适用于Postgres 9.1 + 。对于旧版本,您只需要替换format()
- 它可以防御SQL注入。详细说明:
两个独立的参数允许任何模式中的序列独立于当前search_path
,并允许quote_ident()
完成其工作。 <{1}}以模式限定名称失败 - 会有歧义。
schema参数有一个默认值,因此您可以在调用中省略它。如果未给出架构,则函数默认为quote_ident()
。 Per documentation:
current_schema
返回首先出现的架构名称 搜索路径(如果搜索路径为空,则为空值)。这是 将用于任何表或其他命名对象的模式 在没有指定目标模式的情况下创建。
答案 3 :(得分:6)
如何使用信息架构:
SELECT COUNT(*)
FROM information_schema.sequences
WHERE sequence_schema=? AND sequence_name=?
答案 4 :(得分:1)
select relname, relnamespace
from pg_class join pg_catalog.pg_namespace n ON n.oid = pg_class.relnamespace
where n.nspname='metastore_1' and relname='updater_state_id_seq';
结果:
relname | relnamespace
-------------------------------------
updater_state_id_seq | 32898
此查询可以检查模式中是否存在序列。
答案 5 :(得分:0)
我不确定为什么必须检查序列的存在的实际意图。如果目标是在创建序列之前检查序列是否存在,则可以使用PostgreSQL中的IF NOT EXISTS
条件:
CREATE SEQUENCE IF NOT EXISTS 'name'
请参阅https://www.postgresql.org/docs/9.5/static/sql-createsequence.html