我的表格每年都包含相同類型的數據,但收集的數據略有不同,因爲它們可能沒有相同的字段。嘗試在PL/PgSQL中創建動態查詢字符串以在PostgreSQL中創建DRY函數9.6
d_abc_2016
d_def_2016
d_ghi_2016
d_jkl_2016
有用於每個表中的某些常數:company_id
,employee_id
,salary
。
但是,每個人可能有也可能沒有這些字段用於計算總激勵:bonus
,commission
,cash_incentives
。還有很多,但只是以這些爲例。全部numeric
我應該注意,在這一點上,用戶只有能力運行SELECT
報表。
我希望能夠做的是這樣的:
- 給用戶在
SELECT
調用,並指定自己的領域,除了通話 - 傳遞表名的能力正在使用進入功能在條件邏輯用於確定查詢字符串應該如何構造,爲最終
total_incentives
計算除了傳遞整個表,這樣一噸的參數沒有被傳遞到函數
基本上這:
SELECT employee_id, salary, total_incentives(t, 'd_abc_2016')
FROM d_abc_2016 t;
所以被稱爲將計算total_incentives
這是numeric
該功能employee_id
,也表明他們salary
。但用戶可能會選擇添加其他字段來查看。
對於函數,因爲total_incentives
函數中使用的字段會因表而異,所以我需要創建邏輯來動態構造查詢字符串。
CREATE OR REPLACE FUNCTION total_incentives(ANYELEMENT, t text)
RETURNS numeric AS
$$
DECLARE
-- table name lower case in case user typed wrong
tbl varchar(255) := lower($2;
-- parse out the table code to use in conditional logic
tbl_code varchar(255) := split_part(survey, '_', 2);
-- the starting point if the query string
base_calc varchar(255) := 'salary + '
-- query string
query_string varchar(255);
-- have to declare this to put computation INTO
total_incentives_calc numeric;
BEGIN
IF tbl_code = 'abc' THEN
query_string := base_calc || 'bonus';
ELSIF tbl_code = 'def' THEN
query_string := base_calc || 'bonus + commission';
ELSIF tbl_code = 'ghi' THEN
-- etc...
END IF;
EXECUTE format('SELECT $1 FROM %I', tbl)
INTO total_incentives_calc
USING query_string;
RETURN total_incentives_calc;
END;
$$
LANGUAGE plpgsql;
這導致:
ERROR: invalid input syntax for type numeric: "salary + bonus"
CONTEXT: PL/pgSQL function total_incentives(anyelement,text) line 16 at EXECUTE
因爲它應該返回一組numeric
值。將其更改爲以下內容:
CREATE OR REPLACE FUNCTION total_incentives(ANYELEMENT, t text)
RETURNS SETOF numeric AS
$$
...
RETURN;
獲取相同的錯誤。
好吧,也許它是一個表格,它試圖返回。
CREATE OR REPLACE FUNCTION total_incentives(ANYELEMENT, t text)
RETURNS TABLE(tot_inc numeric) AS
$$
...
獲取相同的錯誤。
真的,任何變化都會產生這樣的結果。所以真的不知道如何讓這個工作。
看RESULT QUERY
,RESULT NEXT
或RESULT QUERY EXECUTE
。
https://www.postgresql.org/docs/9.6/static/plpgsql-control-structures.html
RESULT QUERY
將無法工作,因爲它從我可以告訴一個硬編碼查詢,不會在變量取。
RESULT NEXT
遍歷每個記錄,我不認爲會適合我的需求和看起來這將是很慢...它需要從我可以告訴一個硬編碼查詢。
RESULT QUERY EXECUTE
聽起來很有希望。
-- EXECUTE format('SELECT $1 FROM %I', tbl)
-- INTO total_incentives_calc
-- USING query_string;
RETURN QUERY
EXECUTE format('SELECT $1 FROM %I', tbl)
USING query_string;
並獲得:
ERROR: structure of query does not match function result type
DETAIL: Returned type character varying does not match expected type numeric in column 1.
CONTEXT: PL/pgSQL function total_incentives(anyelement,text) line 20 at RETURN QUERY
應該返回numeric
。
最後,我可以得到這個工作,但它不會幹。我寧願不使用重複代碼爲每個表創建一堆單獨的函數。大部分時間我都看到了工作的例子有一個函數整個查詢,被稱爲像這樣:
SELECT total_incentives(d_abc_2016, 'd_abc_2016');
因此,任何附加列必須在功能作爲指定:鑑於
EXECUTE format('SELECT employee_id...)
用戶將只能在查詢中運行SELECT
,這實在不是一種選擇。他們需要指定他們希望在查詢中看到的任何附加列。
我已經發布了一個類似的問題,但被告知它不清楚,所以希望這個更長的版本將更清楚地解釋我正在嘗試做什麼。
很酷,得到了查詢運行。謝謝您的幫助!現在整理並防止它將返回的記錄數量乘以總記錄數量。 – sockpuppet