如果不存在,如何创建序列

时间:2012-12-06 21:24:53

标签: sql postgresql database-design plpgsql postgresql-9.2

我尝试使用Check if sequence exists in Postgres (plpgsql)中的代码。

如果序列不存在,则创建序列。两次运行此代码会导致异常:

  

序列......已经存在。

如果序列不存在,如何创建序列?

如果序列不存在,则不应写入任何消息且不应发生错误,因此我不能在此问题的其他答案中使用存储过程,因为如果序列存在,它每次都会将消息写入日志文件。

do $$
begin

SET search_path = '';
IF not EXISTS (SELECT * FROM pg_class
             WHERE relkind = 'S'
               AND oid::regclass::text = 'firma1.' || quote_ident('myseq'))
  THEN

SET search_path = firma1,public;

create sequence myseq;

END IF;

SET search_path = firma1,public;

end$$;

select nextval('myseq')::int as nr;

6 个答案:

答案 0 :(得分:25)

Postgres 9.5 +

Postgres 9.5中的

IF NOT EXISTS was added to CREATE SEQUENCE。这就是现在的简单解决方案:

CREATE SEQUENCE IF NOT EXISTS myschema.myseq;

但是无论如何都要考虑过时答案的细节...... 您知道serial列,对吗?


Postgres 9.4或更早

序列的名称与几种类型的对象的名称冲突,而不仅仅是序列。 The manual:

  

序列名称必须与任何其他名称不同   同一模式中的序列,表,索引,视图或外表

大胆强调我的 所以你有三种情况:

  1. 名称不存在。 - >创建序列。
  2. 存在具有相同名称的序列。 - >没做什么?任何输出?任何记录?
  3. 存在具有相同名称的其他冲突对象。 - >做一点事?任何输出?任何记录?
  4. 您需要在上述任何一种情况下指定要执行的操作。 DO语句可能如下所示:

    DO
    $do$
    DECLARE
       _kind "char";
    BEGIN
       SELECT relkind
       FROM   pg_class
       WHERE  oid = 'myschema.myseq'::regclass  -- sequence name, optionally schema-qualified
       INTO  _kind;
    
       IF NOT FOUND THEN       -- name is free
          CREATE SEQUENCE myschema.myseq;
       ELSIF _kind = 'S' THEN  -- sequence exists
          -- do nothing?
       ELSE                    -- object name exists for different kind
          -- do something!
       END IF;
    END
    $do$;
    

    Object types (relkind) in pg_class according to the manual

      

    r =普通表
      i =指数
      S =序列
      v =观看
      m =物化视图
      c =复合型
      t = TOAST表
      f =外国表

    相关:

答案 1 :(得分:13)

我走了另一条路线:抓住异常:

DO
$$
BEGIN
        CREATE SEQUENCE myseq;
EXCEPTION WHEN duplicate_table THEN
        -- do nothing, it's already there
END
$$ LANGUAGE plpgsql;

这样做的一个好处是,您无需担心当前的架构是什么。

答案 2 :(得分:10)

如果您不需要保留可能存在的序列,您可以删除它然后重新创建它:

largestString

答案 3 :(得分:2)

Postgres没有CREATE SEQUENCE IF NOT EXISTS,如果您只是删除序列,如果表使用序列具有默认值,则可能会出错:

  

错误:无法删除序列(sequence_name),因为其他对象依赖于它SQL状态:2BP01

对我来说,这个可以提供帮助:

ALTER TABLE <tablename> ALTER COLUMN id DROP DEFAULT;
DROP SEQUENCE IF EXISTS <sequence_name>;
CREATE sequence <sequence_name>;

答案 4 :(得分:0)

可以从information_schema.sequencesreference

中检索有关序列的信息

尝试这样的事情(未经测试):

...
IF not EXISTS (SELECT * FROM information_schema.sequences
    WHERE sequence_schema = 'firma1' AND sequence_name = 'myseq') THEN
...

答案 5 :(得分:0)

我有一个函数可以随时清理我的数据库应用程序中的所有表。它是动态构建的,但实质是它会删除每个表中的所有数据并重置序列。 这是重置其中一个表序列的代码:

perform relname from pg_statio_all_sequences where relname = 'privileges_id_seq';
if found then
  select setval ('privileges_id_seq',1, false) into i_result;
end if;

希望这有帮助,

Loek

我正在使用postgres 8.4,我看到你使用9.2。可以在存储信息的地方有所作为。