添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
飘逸的企鹅  ·  python ...·  1 年前    · 
任性的紫菜汤  ·  使用“python -m pipx ...·  2 年前    · 
寂寞的烤红薯  ·  Bash ...·  2 年前    · 

Stack Exchange Network

Stack Exchange network consists of 182 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers. Visit Stack Exchange

Database Administrators Stack Exchange is a question and answer site for database professionals who wish to improve their database skills and learn from others in the community. It only takes a minute to sign up.

Sign up to join this community

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am working on a function that allows me to add an index if it does not exist. I am running into the problem that I cannot get a list of indexes to compare to. Any thoughts?

This is a similar issue to the column creation one that is solved with this code:
https://stackoverflow.com/a/12603892/368511

you can try: SELECT * from pg_indexes where schemaname = '[schemaname]' and indexname = '[indexname]'. Replace [schemaname] and [indexname] with proper values. Ref: postgresql.org/docs/9.1/static/view-pg-indexes.html jbarrameda May 16, 2016 at 20:49
  • Index names are unique across a single database schema.
  • Index names cannot be the same as any other index, (foreign) table, (materialized) view, sequence or user-defined composite type in the same schema.
  • Two tables in the same schema cannot have an index of the same name. (Follows logically.)
  • If you do not care about the name of the index, have Postgres auto-name it:

    CREATE INDEX ON tbl1 (col1);
    

    is (almost) the same as:

    CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);
    

    Except that Postgres will avoid a naming collisions and automatically pick the next free name:

    tbl1_col1_idx 
    tbl1_col1_idx2
    tbl1_col1_idx3
    

    Just try it. But, obviously, you would not want to create multiple redundant indexes. So it wouldn't be a good idea to just blindly create a new one.

    Test for existence

    Postgres 9.5 or newer

    Now available:

    CREATE INDEX IF NOT EXISTS ...

    Also works for CREATE INDEX CONCURRENTLY IF NOT EXISTS.

    However, the manual warns:

    Note that there is no guarantee that the existing index is anything like the one that would have been created.

    It's a plain check for the object name. (Applies to variants for older versions below, too.)
    To find existing indexes on the same table for the same column(s):

    SELECT pg_get_indexdef(indexrelid)
    FROM   pg_index
    WHERE  indrelid = 'public.big'::regclass
    AND   (indkey::int2[])[:] = ARRAY (
       SELECT attnum
       FROM   unnest('{usr_id, created_at}'::text[]) WITH ORDINALITY i(attname, ord)
       JOIN  (
          SELECT attname, attnum
          FROM   pg_attribute
          WHERE  attrelid = 'public.big'::regclass
          ) a USING (attname)
       ORDER BY ord
    

    Restrictions:

  • Only works for columns, not other index expressions.
  • Also reports partial indexes (with WHERE clause) and covering indexes (with INCLUDE clause).
  • Reports any type of index, not just B-tree indexes.
  • Study the results (if any) before proceeding, or refine the query to your needs ...

    Further reading:

  • Find tables with multiple indexes on same column
  • Normalize array subscripts for 1-dimensional array so they start with 1
  • Postgres 9.4

    You can use the new function to_regclass() to check without throwing an exception:

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

    Returns NULL if an index (or another object) of that name does not exist. See:

  • How to check if a table exists in a given schema
  • This doesn't work for CREATE INDEX CONCURRENTLY, since that variant cannot be wrapped in an outer transaction. See comment by @Gregory below.

    Postgres 9.3 or older

    Cast the schema-qualified name to regclass:

    SELECT 'myschema.myname'::regclass;
    

    If it throws an exception, the name is free.
    Or, to test the same without throwing an exception, use a DO statement:

    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;

    The DO statement was introduced with Postgres 9.0. In earlier versions you have to create a function to do the same.
    Details about pg_class in the manual.
    Basics about indexes in the manual.

    While being a great answer, do note that you can't add indexes CONCURRENTLY this way. You'll get ERROR: CREATE INDEX CONCURRENTLY cannot be executed from a function or multi-command string. – gregoltsov Aug 1, 2014 at 11:59

    It will be available in 9.5. Here is actual git commit https://github.com/postgres/postgres/commit/08309aaf74ee879699165ec8a2d53e56f2d2e947

    Discussion on pg hackers http://postgresql.nabble.com/CREATE-IF-NOT-EXISTS-INDEX-td5821173.html

    from the documentation, it's 9.6 postgresql.org/docs/9.2/sql-createindex.html, not the 9.5 as its mark as unsupported version – Adiii Apr 17, 2021 at 8:31