0

我擁有分區表上的PostgreSQL 9.2每一個具有分區功能,看起來像這樣:功能/程序更新(ALTER)其他功能/程序

CREATE OR REPLACE FUNCTION myPartitionSelectionFunction() 
    RETURNS trigger AS 
$BODY$ 
BEGIN 
    IF (NEW.PartitionColumn < DATE '2010-08-08 00:00:00') THEN INSERT INTO MyPartitionedTable_Week_31_2010 VALUES (NEW.*); 
    ELSIF (NEW.PartitionColumn < DATE '2010-08-15 00:00:00' AND NEW.PartitionColumn >= DATE '2010-08-08 00:00:00') THEN INSERT INTO MyPartitionedTable_Week_32_2010 VALUES (NEW.*); 
    ELSE 
     RAISE EXCEPTION 'PartitionColumn out of range. Update myPartitionSelectionFunction()'; 
    END IF; 
    RETURN NULL; 
END; 
$BODY$ 
LANGUAGE plpgsql 

所以,每個星期是一個新的分區。問題是每週更新數百個函數。我必須自動化,每個插入的觸發器是不可行的。這個想法是創建一個由cron調用的函數,用於更新每個分區函數,在最後的ELSE之前添加另一個ELSIF。然而,我找不到一種方法來遍歷每個具有「分區」名稱的函數,然後檢索它的代碼(像\ d這樣的psql命令不會在函數中工作,對嗎?)來添加新的ELSIF和相應地更新(ALTER)每個功能,創建一個新的分區。

所以,我現在最大的問題是:

如何遍歷每個功能(?使用光標)曾在其上有「分區」的名稱,然後檢索它的代碼,之前添加另一個ELSIF ELSE和更新(ALTER)它的內容不會陷入無限循環?

任何幫助,非常感謝。謝謝。

+0

查詢:SELECT proname,prosrc FROM pg_catalog.pg_namespaceÑ JOIN pg_catalog.pg_proc p ON pronamespace = n.oid WHERE nspname = '公衆'; 得到我們的程序/功能的定義。 –

回答

2

雖然您可以從pg_proc檢索功能源,但試圖檢索它,編輯它並更新該功能是痛苦和折磨的祕訣。

而是編寫一個PL/PgSQL過程,生成整個函數文本。使用針對information_schemapg_catalog.pg_class的查詢來獲取所需的表列表,約束,繼承等。在查詢結果上循環,生成函數的主體,然後將其全部加入到單個文本塊中,並將其傳遞到EXECUTE

下面是一個函數生成另一玩具例如:

CREATE OR REPLACE FUNCTION very_meta(func_name text, message text) RETURNS void AS 
$$ 
DECLARE 
    func_lines text; 
BEGIN 
    -- In reality you'd build this iteratively, or preferably use `string_agg` over 
    -- a query, but I'm just going to supply a single line function body for this 
    -- example: 
    func_lines := format($LINE$RAISE NOTICE 'It works, message is %%!','%s';$LINE$, message); 
    -- Now, build the function creation statement and execute it: 
    EXECUTE format(
    $INNER$ 
     -- this is the SQL text we're going to execute, with the %%I placeholder 
     -- to be replaced by the format(...) function: 
     -- 
     CREATE OR REPLACE FUNCTION %I() RETURNS void AS 
     $INNERBODY$ 
     BEGIN 
      -- and this is the body of the function we're generating 
      -- in this case it's going to be substituted in as func_lines 
      -- by format(...) 
      %s 
     END; 
     $INNERBODY$ 
     LANGUAGE plpgsql; 
    $INNER$, func_name, func_lines); 
END; 
$$ LANGUAGE plpgsql; 

演示:

regress=> SELECT very_meta('lessmeta', 'Secret Message'); 
very_meta 
----------- 

(1 row) 

regress=> SELECT lessmeta(); 
NOTICE: It works, message is Secret Message! 
lessmeta 
---------- 

(1 row) 

這可以用針對information_schema和/或系統目錄適當的查詢組合以獲得表列出,創建一系列條件測試等。This answer I wrote a while ago details how to query the catalogs for inheritance relationships,這可能很有用,但您還需要確定使用中的約束條件CHECK。如果你有一個命名約定,那麼可以簡單地依靠這個和pg_class的搜索。

請記住,PostgreSQL的分區最多可以與最多數百個表一起使用,如果那樣的話。由於查詢計劃成本較高,表計數會大大降低性能。