Eğer yoksa indeks oluştur


60

Varsa, dizin eklememe izin veren bir işlev üzerinde çalışıyorum. Karşılaştıracağım endekslerin listesini bulamadığım sorunla karşılaşıyorum. Düşüncesi olan var mı?

Bu, bu kodla çözülen sütun oluşturma ile benzer bir sorundur:
https://stackoverflow.com/a/12603892/368511


deneyebilirsiniz: SELECT * pg_indexes adresinden schemaname = '[schemaname]' ve indexname = '[indexname]'. [Schemaname] ve [indexname] değerlerini uygun değerlerle değiştirin. Ref: postgresql.org/docs/9.1/static/view-pg-indexes.html
jbarrameda

Yanıtlar:


102

PostgreSQL'deki dizin adları

  • Dizin adları, tek bir veritabanı şeması genelinde benzersizdir.
  • Dizin adları, aynı şemadaki diğer dizin, (yabancı) tablo, (maddeleştirilmiş) görünüm, sıra veya kullanıcı tanımlı bileşik türlerle aynı olamaz.
  • Aynı şemadaki iki tablo aynı isimdeki bir dizine sahip olamaz. (Mantıksal olarak takip eder.)

Dizinin adını umursamıyorsanız, Postgres'in otomatik olarak adlandırılmasını sağlayın:

CREATE INDEX ON tbl1 (col1);

(neredeyse) aynıdır:

CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);

Bunun dışında Postgres, ad çarpışmalarından kaçınacak ve bir sonraki boş adı otomatik olarak seçecektir:

tbl1_col1_idx 
tbl1_col1_idx2
tbl1_col1_idx3
...

Sadece dene. Ama belli ki, olur değil birden gereksiz dizin oluşturmak istiyorum. Bu yüzden sadece kör bir şekilde yeni bir tane yaratmak iyi bir fikir olmazdı.

Varlık testi

Postgres 9.3 veya daha büyük

Test etmenin çok basit bir yolu şema nitelemeli adı şununa vermek regclass:

SELECT 'myschema.myname'::regclass;

Bir istisna atarsa, isim ücretsizdir.
Veya, aynı DOifadeyi kullanılan bir istisna atmadan sınamak için :

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

Bu işe yaramıyor CREATE INDEX CONCURRENTLY, çünkü bu değişken bir dış işleme dahil edilemiyor. Bkz @Gregory tarafından yorumunu aşağıda.

DOİfadesi Postgres 9.0 ile tanıtıldı. Daha önceki sürümlerde , aynısını yapmak için bir işlev oluşturmanız gerekir .
İlgili ayrıntılar pg_classkılavuzda . Kılavuzdaki indeksler
hakkında temel bilgiler .

Postgres 9.4

to_regclass()Bir istisna atmadan kontrol etmek için yeni işlevi kullanabilirsiniz :

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

END
$$;

Bu adın bir dizini (veya başka bir nesne) yoksa NULL döner. Görmek:

Postgres 9.5

Şuan müsait:

CREATE INDEX IF NOT EXISTS ...

Bu da işe yarıyor CREATE INDEX CONCURRENTLY IF NOT EXISTS.

Ancak, el kitabı uyarır :

Mevcut indeksin oluşturulmuş olana benzer bir şey olduğuna dair hiçbir garanti olmadığını unutmayın.

Nesne adı için basit bir kontrol. Buradaki tüm değişkenler için geçerlidir.


7
Harika bir cevap olurken, CONCURRENTLYbu şekilde dizin ekleyemeyeceğinizi unutmayın . Alacaksın ERROR: CREATE INDEX CONCURRENTLY cannot be executed from a function or multi-command string.
gregoltsov

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.