创建索引(如果不存在)


60

我正在开发一个函数,该函数可以添加不存在的索引。我遇到了无法获取要比较的索引列表的问题。有什么想法吗?

这与使用以下代码解决的列创建问题类似:https :
//stackoverflow.com/a/12603892/368511


您可以尝试:从pg_indexes中选择*,其中schemaname ='[schemaname]'和indexname ='[indexname]'。用适当的值替换[schemaname]和[indexname]。参考:postgresql.org/docs/9.1/static/view-pg-indexes.html
jbarrameda '16

Answers:


102

PostgreSQL中的索引名称

  • 索引名称在单个数据库模式中是唯一的。
  • 索引名称不能与同一架构中的任何其他索引,(外部)表,(物化)视图,序列或用户定义的复合类型相同。
  • 同一模式中的两个表不能具有相同名称的索引。(按照逻辑顺序。)

如果您不关心索引的名称,请让Postgres自动为其命名:

CREATE INDEX ON tbl1 (col1);

(几乎)与:

CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);

除了Postgres会避免命名冲突并自动选择下一个免费名称:

tbl1_col1_idx 
tbl1_col1_idx2
tbl1_col1_idx3
...

去尝试一下。但是,很明显,你会不会想创建多个冗余索引。因此,盲目创建一个新的想法不是一个好主意。

测试存在

Postgres 9.3或更旧版本

一种非常简单的测试方法是将模式限定的名称强制转换为regclass

SELECT 'myschema.myname'::regclass;

如果抛出异常,则名称是免费的。
或者,为了在不引发异常的情况下进行测试,请在DO语句中使用:

DO
$$
BEGIN
   IF NOT EXISTS (
      SELECT
      FROM   pg_class c
      JOIN   pg_namespace n ON n.oid = c.relnamespace
      WHERE  c.relname = 'mytable_mycolumn_idx'
      AND    n.nspname = 'myschema'
   ) THEN

        CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
    END IF;
END
$$;

这不适用于CREATE INDEX CONCURRENTLY,因为该变体不能包装在外部事务中。请参阅下面@Gregory的评论

DO声明是在Postgres 9.0中引入的。在早期版本中,您必须创建一个函数来执行相同的操作。
有关详细信息,请pg_class参见手册手册中
有关索引的基础。

PostgreSQL 9.4

您可以使用新功能to_regclass()进行检查而不会引发异常:

DO
$$
BEGIN
   IF to_regclass('myschema.mytable_mycolumn_idx') IS NULL THEN
      CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
   END IF;

END
$$;

如果该名称的索引(或另一个对象)不存在,则返回NULL。看到:

Postgres 9.5

现在可用:

CREATE INDEX IF NOT EXISTS ...

也适用CREATE INDEX CONCURRENTLY IF NOT EXISTS

但是,手册警告

请注意,不能保证现有索引类似于将要创建的索引。

这是对对象名称的简单检查。适用于此处的所有变体。


7
虽然这是一个很好的答案,但请注意,您不能以CONCURRENTLY这种方式添加索引。你会得到ERROR: CREATE INDEX CONCURRENTLY cannot be executed from a function or multi-command string
gregoltsov

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.