2017-02-10 32 views
2

如何確保新記錄包含引用數據庫中當前存在的模式,表和列的值?postgres 9.3+:確保數據庫中存在表和列的約束條件

例如,給定一個表:

CREATE TEMP TABLE "column_reference" (
     "gid" SERIAL PRIMARY KEY 
    , "val" INTEGER 
    , "schema" TEXT 
    , "table" TEXT 
    , "column" TEXT 
); 

我怎麼能保證schema.table.column存在?

我嘗試了一個fkey到information_schema.columns,但是,當然,不允許外部視圖。

它也出現在columns視圖定義中,我需要幾個表才能獲取模式,表和列名,所以我不能爲源表創建一個外鍵。

我目前的解決方法是從information_schema.columns視圖手動創建__columns表,並引用它。這項工作給予了我在這個時間點上對這個項目的控制權,但我正在尋找一個永久的,動態的解決方案。

我可以使用不同的約束或方法嗎?

回答

2

您可以創建一個trigger function,檢查你想要的東西,而這個函數與被INSERT或表格的更新之前發射的扳機相關聯:

這可能是你的觸發功能:

CREATE FUNCTION column_reference_check() 
    RETURNS trigger 
    LANGUAGE 'plpgsql' 
AS 
$BODY$ 
begin 
    /* Check for the existence of the required column */ 
    if EXISTS (
      SELECT * 
      FROM information_schema.columns 
      WHERE 
        table_schema = new.schema 
       AND table_name = new.table 
       AND column_name = new.column) 
    then 
     /* Everything Ok */ 
     return new ; 
    else 
     /* This is approx. what would happen if you had a constraint */ 
     RAISE EXCEPTION 'Trying to insert non-matching (%, %, %)', new.schema, new.table, new.column ; 

     /* As an alternative, you could also just return NULL 
      As a result, the row is *not* inserted, but execution continues */ 
     return NULL ; 
    end if ; 
end ; 
$BODY$; 

要與觸發該功能相關聯,你會使用:

CREATE TRIGGER column_reference_check_trg 
    BEFORE INSERT OR UPDATE OF "schema", "table", "column" 
    ON column_reference 
    FOR EACH ROW 
    EXECUTE PROCEDURE column_reference_check(); 

現在你可以試着進行下面INSERT,這應該會成功:

INSERT INTO column_reference 
    VALUES (2, 1, 'pg_catalog', 'pg_statistic', 'starelid'); 

但如果你試試這個:

INSERT INTO column_reference 
    VALUES (-1, 1, 'false_schema', 'false_table', 'false_column'); 

...你會得到一個異常:

ERROR: Trying to insert non-matching (false_schema, false_table, false_column) 
CONTEXT: PL/pgSQL function column_reference_check() line 16 at RAISE