我有一個分區表(稱之爲A)和一個由另一個表(稱爲B)引用的串行主鍵。我知道我不能實際上創建一個外鍵從一個到另一個(因爲我不知道從哪個分區數據實際存儲),所以相反,我試圖模仿外鍵的行爲使用檢查約束。類似如下:如何將Postgres外鍵模仿到分區表中
CREATE TABLE A (
MyKey SERIAL PRIMARY KEY
);
CREATE TABLE B (
AKey INT, -- Should have: REFERENCES A (MyKey),
-- but can't due to Postgres limitations
);
CREATE TABLE APart1 (
Field1 INT,
PRIMARY KEY (MyKey)
) INHERITS (A);
CREATE TABLE APart2 (
Field2 INT,
PRIMARY KEY (MyKey)
) INHERITS (A);
CREATE FUNCTION ValidateKeyInA(aKey INT) RETURNS BOOL AS $$
BEGIN
PERFORM * FROM A WHERE MyKey = aKey;
IF FOUND THEN
RETURN TRUE;
END IF;
RETURN FALSE;
END;
$$ LANGUAGE PLPGSQL;
ALTER TABLE B ADD CHECK (ValidateKeyInA(AKey));
WITH aKey AS (INSERT INTO APart1 (Field1) VALUES (1) RETURNING MyKey)
INSERT INTO B (AKey) SELECT * FROM aKey;
WITH aKey AS (INSERT INTO APart2 (Field2) VALUES (2) RETURNING MyKey)
INSERT INTO B (AKey) SELECT * FROM aKey;
這工作得很好,直到我去轉儲和恢復數據庫。此時,Postgres不知道表B依賴於表A中的數據(及其分區),而B恰好在表A之前被轉儲。我嘗試將「DEFERRABLE」關鍵字添加到行I中添加約束,但Postgres不支持可延遲檢查約束。
我建議的方法是將我的檢查約束轉換爲約束觸發器,我可以推遲,然後在事務中導入我的數據庫轉儲。有沒有更直接的方法呢?例如,是否有某種方式讓我告訴Postgres不要轉儲表B,直到表A及其所有分區都被轉儲(例如,添加從B到A分區的依賴關係)?我應該使用其他一些模式嗎?謝謝。
我不明白你是如何實現表分區的。主表是哪一張?爲什麼你不使用繼承? Btw你的檢查函數可以更簡單:'CREATE FUNCTION ValidateKeyInA(aKey INT)RETURNS BOOL AS $$ SELECT count(*)> 0 FROM A WHERE Key = aKey; $$ LANGUAGE sql;' – 2015-03-03 07:22:53
@TommasoDiBucchianico我編輯了我的問題,明確顯示瞭如何創建A的分區。我不知道在PLPGSQL函數中編寫單個select語句會隱式返回結果。感謝您的建議(幾乎每次訪問SO頁面時我都會學到一些新東西)。 – 2015-03-03 12:51:54
只有sql函數隱式返回查詢的結果。我的函數是用sql語言編寫的,而不是plpgsql – 2015-03-03 12:59:40