Postgresql
如果不存在則創建索引
我正在開發一個功能,如果它不存在,我可以添加它。我遇到了無法獲得要比較的索引列表的問題。有什麼想法嗎?
這與使用此程式碼解決的列創建問題類似:
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.5 或更高版本
現在可用:
CREATE INDEX **IF NOT EXISTS** ...
也適用於
CREATE INDEX CONCURRENTLY IF NOT EXISTS
.但是,手冊警告:
請注意,不能保證現有索引與已創建的索引相同。
這是對對象名稱的簡單檢查。(也適用於下面舊版本的變體。)
要在同一個表上為相同的列查找現有索引:
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 );
限制:
- 僅適用於列,不適用於其他索引表達式。
- 還報告部分索引(帶
WHERE
子句)和覆蓋索引(帶INCLUDE
子句)。- 報告任何類型的索引,而不僅僅是 B 樹索引。
在繼續之前研究結果(如果有),或根據您的需要細化查詢…
進一步閱讀:
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。看:
這不適用於
CREATE INDEX CONCURRENTLY
,因為該變體不能包裝在外部事務中。請參閱下面@Gregory 的評論。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 $$;