【问题标题】:How to create sequence if not exists如果不存在如何创建序列
【发布时间】:2012-11-25 00:42:01
【问题描述】:

我尝试使用来自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;

【问题讨论】:

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


【解决方案1】:

序列信息可以从information_schema.sequences(reference)获取

试试这样的东西(未经测试):

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

【讨论】:

  • 没有信息“存储”在information_schema 的对象中。这只是系统目录上的一组(相当复杂的)视图,用于根据 SQL 标准提供信息。如果您需要保证跨不同 RDBMS 或跨版本的可移植性,请使用information_schema。使用系统目录中的对象 - 架构 pg_catalog,其中存储 实际 信息 - 通常快一个数量级。
  • @ErwinBrandstetter 你是对的,这是一个错误的选择。我已经编辑了我的答案。
【解决方案2】:

Postgres 9.5 或更高版本

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

CREATE SEQUENCE IF NOT EXISTS myschema.myseq;

但无论如何都要考虑过时答案的细节......
你知道serialIDENTITY 列,对吧?

Postgres 9.4 或更早版本

序列与其他几个类似表的对象共享名称空间。 The manual:

序列名称必须与任何其他的名称不同 序列、表、索引、视图或外部表在同一架构中。

我的大胆强调。所以分三种情况:

  1. 名称不存在。 -> 创建序列。
  2. 存在同名序列。 ->什么都不做?有输出吗?任何日志记录?
  3. 存在其他具有相同名称的冲突对象。 -> 做点什么?有输出吗?任何日志记录?

指定在任何一种情况下要做什么。 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 = 外部表

相关:

【讨论】:

  • 优秀的答案。 IIRC 序列过去在旧版本(9.1 之前?)中存在不完全模式限定的问题,导致它们“泄漏”到“全局命名空间”中。不过我不确定,这可能是我这边的一个小故障;-[
  • @wildplasser:这里没有响铃,也许它引起了我的注意。
  • 可能是一个小故障。太宽泛的 search_path 设置(加上缺乏明确的模式限定)可能是原因,例如......
【解决方案3】:

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

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;

希望这会有所帮助,

洛克

我使用的是 postgres 8.4,我看到你使用的是 9.2。可能会改变信息的存储位置。

【讨论】:

  • 问题似乎是关于创建一个序列,而不是重置它。另外,请考虑this [faq] posting on meta 关于签名和标语。
  • 我读到的问题主要是如何避免引起噪音。 Andrus 知道如何创建序列,因为他指出了一个关于此的问题。您的答案已经是整个问题的完美解决方案。我只是想友好并为他提供另一种方法。额外的信息表明它有效。我将很快阅读有关元等的帖子。
【解决方案4】:

我走了一条不同的路:只捕获异常:

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

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

【讨论】:

  • 唯一烦人的部分,是额外的依赖。我收到此错误。 PG::InternalError: ERROR: could not load library "/usr/lib/postgresql/plpgsql.so": /usr/lib/postgresql/plpgsql.so: undefined symbol: MakeExpandedObjectReadOnlyInternal
【解决方案5】:

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

DROP SEQUENCE IF EXISTS id_seq;
CREATE SEQUENCE id_seq;

【讨论】:

  • 除非它已经存在,它很可能正在使用中。 PG::DependentObjectsStillExist: ERROR: cannot drop sequence activities_id_seq because other objects depend on it DETAIL: default for table activities column id depends on sequence activities_id_seq HINT: Use DROP ... CASCADE to drop the dependent objects too.
【解决方案6】:

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>;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 2021-07-17
    • 2011-02-26
    • 2012-02-04
    • 2022-07-05
    • 2014-11-24
    • 2013-08-10
    相关资源
    最近更新 更多