Postgresql
pl/pgsql:從記錄中動態獲取列名
問候,我想從記錄中動態獲取列名。如下面的程式碼所示,我創建了一個游標,並使用循環來處理該游標中的每條記錄,方法是將每一行提取到記錄類型 r1。在我的表中,我有這些列
$$ dlq_2000,dlq_2001,…,dlq_2017,dlq_2017 $$. 我還在它之上創建了一個循環來單獨處理每一列。 我面臨的問題是從 r1 動態獲取欄位名稱,並且在執行程式碼時出現此錯誤:
$$ Err $$錯誤:記錄 “r1” 沒有欄位 “‘dlq_’||counter::text” 上下文:SQL 語句 “SELECT (r1."‘dlq_’||counter::text” = 1 )"
請建議如何解決這個問題。
謝謝,
CREATE OR REPLACE FUNCTION update() RETURNS VOID AS $$ DECLARE cur SCROLL CURSOR FOR select * from my_tbl; r1 RECORD; begin OPEN cur ; FOR counter IN 2000..2017 LOOP r1 := NULL; LOOP FETCH cur INTO r1; EXIT WHEN NOT FOUND; IF (r1."'dl_'||counter::text" = 1 ) THEN -- do some thing RAISE NOTICE 'processing year of : %', counter; END IF; END LOOP; END LOOP; CLOSE cur; END; $$ LANGUAGE plpgsql;
您沒有簡單的方法來檢查“變數列”。有一種(不是很優雅的)方法可以通過使用 a 來實現此結果
CASE
:CREATE OR REPLACE FUNCTION update() RETURNS VOID AS $$ DECLARE cur SCROLL CURSOR FOR select * from my_tbl; r1 RECORD; BEGIN OPEN cur ; FOR counter IN 2000..2017 LOOP r1 := NULL; LOOP FETCH cur INTO r1; EXIT WHEN NOT FOUND; IF (CASE counter WHEN 2000 THEN r1.dl_2000 WHEN 2001 THEN r1.dl_2001 WHEN 2002 THEN r1.dl_2002 WHEN 2003 THEN r1.dl_2003 WHEN 2004 THEN r1.dl_2004 WHEN 2005 THEN r1.dl_2005 WHEN 2006 THEN r1.dl_2006 WHEN 2007 THEN r1.dl_2007 WHEN 2008 THEN r1.dl_2008 WHEN 2009 THEN r1.dl_2009 WHEN 2010 THEN r1.dl_2010 WHEN 2011 THEN r1.dl_2011 WHEN 2012 THEN r1.dl_2012 WHEN 2013 THEN r1.dl_2013 WHEN 2014 THEN r1.dl_2014 WHEN 2015 THEN r1.dl_2015 WHEN 2016 THEN r1.dl_2016 WHEN 2017 THEN r1.dl_2017 END) = 1 THEN -- do some thing RAISE NOTICE 'processing year of : %', counter; END IF; END LOOP; END LOOP; CLOSE cur; END; $$ LANGUAGE plpgsql;
我假設所有列
dl_2000
..dl_2017
都定義為integer
(或bit
)。也就是說,表定義如下所示:CREATE TABLE t ( /* some columns */ dl_2000 integer, dl_2001 integer, dl_2002 integer, dl_2003 integer, /* ... */ dl_2017 integer, /* more columns */ ) ;
您可以使用
ARRAY
整數代替:CREATE TABLE t ( /* some columns */ dl integer[], /* more columns */ ) ;
(您可以使用 NOT NULL 約束,
dl
就像在列上使用它們一樣;儘管寫法不同。也就是說,如果需要,您可以使用CHECK (dl[2000] NOT NULL)
. 在這些情況下不能使用FOREIGN KEY
約束。然後,您的功能將是:
CREATE OR REPLACE FUNCTION update() RETURNS VOID AS $$ DECLARE cur SCROLL CURSOR FOR select * from my_tbl; r1 RECORD; BEGIN OPEN cur ; FOR counter IN 2000..2017 LOOP r1 := NULL; LOOP FETCH cur INTO r1; EXIT WHEN NOT FOUND; IF dl[counter] = 1 THEN -- do some thing RAISE NOTICE 'processing year of : %', counter; END IF; END LOOP; END LOOP; CLOSE cur; END; $$ LANGUAGE plpgsql;
注意:我沒有改變你函式中的邏輯,雖然我不確定我會這樣做。至少,我會交換這兩個循環。一個大的用於游標,然後在內部,一個用於列(或數組的索引)。