Database-Design

DROP CONSTRAINT 後主鍵的索引會發生什麼變化?

  • January 27, 2022

我正在執行 PostgreSQL 9.1.4。

我有一個包含許多現有行的表,以及一堆帶有指向它的外鍵的其他表,我正在嘗試:

1 - 移除目前主鍵的 pkey 約束,因為它目前不是串列類型。

2 - 添加一個序列類型列並將該新列作為主鍵。

3 - 將步驟 #1 的舊列設置為 UNIQUE 並為所有具有指向我的表的外鍵的表重新創建外鍵。事實上,這些表都有兩個指向我的表的外鍵:一個指向目前是主鍵的舊列,另一個指向新的序列類型列

我已經成功創建了一個執行此操作的腳本,但我想知道:

a) 在上面的步驟 #1 中刪除 pkey 約束是否也會刪除與該主鍵關聯的索引?

b)如果沒有,有沒有辦法重用該索引?在第 3 步添加回 UNIQUE 約束後,是否會創建一個新索引,還是會使用之前存在的索引?除了創建的新列(序列主鍵)之外,表中沒有任何內容被更改。

編輯(一些澄清):

  • 我們將舊的 pk 列稱為 OLD_PK,將要由我的腳本創建的新 pk 列稱為 NEW_PK
  • OLD_PK 列的類型是 INT
  • OLD_PK 列不會也不能被刪除(它的資訊仍然有價值)因此它也不能將自己轉換為串列類型,現有數據必須保留。
  • 我知道串列是一條捷徑。就像我說的那樣,我想出了一個工作腳本,我不確定的部分是索引以及從那個角度來看它是如何工作的。
  • 以前有一個外鍵指向 OLD_PK 的所有表,在執行腳本後,將有一個外鍵指向 OLD_PK(比如“fkey_old_pk”)和另一個指向 NEW_PK 的外鍵(比如“fkey_new_pk”)

免責聲明

這是實驗性的,僅進行了初步測試。繼續需要您自擔風險。我自己不會使用它,只是使用標準 DDL 命令刪除/重新創建約束。如果您破壞了目錄表中的條目,您很容易弄亂您的數據庫。

PRIMARY KEY據我所知,目錄表中的 a和約束之間只有兩個區別UNIQUE(索引本身是相同的):

pg_index.indisprimary

PRIMARY KEY約束…true

UNIQUE約束…false

pg_constraint.contype

PRIMARY KEY約束…'p'

UNIQUE約束…'u'

可以將約束和索引從PRIMARY KEY約束轉換為UNIQUE約束,my_idx作為(可選的模式限定)索引名稱:

UPDATE pg_index SET indisprimary = false WHERE indexrelid = 'my_idx'::regclass;
UPDATE pg_constraint SET contype = 'u' WHERE conindid = 'my_idx'::regclass;

或從升級UNIQUEPRIMARY KEY

UPDATE pg_index SET indisprimary = true WHERE indexrelid = 'my_idx'::regclass;
UPDATE pg_constraint SET contype = 'p' WHERE conindid = 'my_idx'::regclass;

當然,每張桌子只能有一個PK。

是的,刪除主鍵約束將刪除索引。

但需要注意的是,serial不是真正的類型,它是 的快捷方式INT default nextval('some_sequence'),其中some_sequence是自動生成的。

您沒有說目前列類型是什麼,但由於您希望能夠重用串列列的索引,因此假設它是 INT。

如果您打算最終刪除舊列,則問題並不明顯,但如果您只想將其轉換為串列列,則不需要刪除和重新創建相關的約束。只需創建一個序列,將其初始化為主鍵的下一個值,並將其下一個值設為該列的預設值,如下所示:

CREATE SEQUENCE myseq START WITH 12345;

其中 12345 被目前替換max(pk)

然後:

ALTER TABLE tablename ALTER COLUMN pk_col SET DEFAULT nextval('myseq');

引用自:https://dba.stackexchange.com/questions/28808