สร้างดัชนีหากไม่มีอยู่


60

ฉันกำลังทำงานกับฟังก์ชั่นที่อนุญาตให้ฉันเพิ่มดัชนีหากไม่มีอยู่ ฉันพบปัญหาที่ฉันไม่สามารถรับรายการดัชนีเพื่อเปรียบเทียบได้ ความคิดใด ๆ

นี่เป็นปัญหาที่คล้ายคลึงกับการสร้างคอลัมน์ที่แก้ไขด้วยรหัสนี้:
https://stackoverflow.com/a/12603892/368511


คุณสามารถลอง: SELECT * จาก pg_indexes โดยที่ schemaname = '[schemaname]' และ indexname = '[indexname]' แทนที่ [schemaname] และ [indexname] ด้วยค่าที่เหมาะสม Ref: postgresql.org/docs/9.1/static/view-pg-indexes.html
jbarrameda

คำตอบ:


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

แค่ลองดู. แต่แน่นอนคุณไม่ต้องการสร้างดัชนีซ้ำซ้อนหลายรายการ ดังนั้นจึงไม่ใช่ความคิดที่ดีที่จะสร้างใหม่เพียงแค่สุ่มสี่สุ่มห้า

ทดสอบการมีอยู่

โพสต์ 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
พื้นฐานเกี่ยวกับการจัดทำดัชนีในคู่มือ

Postgres 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.