2016-05-12 49 views
0

我的公司將開始使用我們數據庫中的數據生成文檔,並且我正在設計將會吐出文檔文本的功能。這些文件將需要包含從多個表中取得的數據,有數百個列,並且總是有些記錄會丟失數據。動態查詢的結果作爲表?

我想做一個函數,將採取空字段並將其替換爲一個小錯誤消息,使最終用戶清楚,一塊數據丟失。由於最終用戶完全不熟悉後端,我希望這些消息能夠引用可理解的內容。

我的解決方案很簡單,但我對我的生活無法得到它的工作。記錄標識符,表名被設置爲函數中的參數。該函數然後遍歷指定表中每個列的名稱,構建一個包含大量case語句的查詢。循環完成後,將追加標識符,然後執行查詢,將結果返回給調用函數。

儘管閱讀相當多,但我可以最好的是包含所有結果的單個列/行 - 對我來說根本沒用,因爲我需要能夠輕鬆地引用父查詢中的特定數據段。我是Postgres的初學者,文檔太複雜,我不明白,任何幫助,將不勝感激。

-- Function: data_handler(text, text) 

-- DROP FUNCTION data_handler(text, text); 

CREATE OR REPLACE FUNCTION data_handler(target_uri text, target_table TEXT) 
    RETURNS SETOF record AS 
$BODY$ 
DECLARE 
c text; 
strSQL text; 
site_only text; 
result record; 

BEGIN 
--We need the schema for strSQL but the loop needs just the table name. 
site_only = split_part(target_table, '.', 2); 

FOR c IN 
SELECT column_name 
FROM information_schema.columns 
WHERE table_name = site_only 
LOOP 

    strSQL = concat(strSQL, chr(10), '(SELECT CASE WHEN ', c::text, '::text IS NULL THEN concat(', chr(39), '<Error:', chr(39), ', (SELECT lkp_value FROM alb_cr.lkp_field_values WHERE column_name = ', chr(39), c::text, chr(39), ')::text, ', chr(39), ' value not found>', chr(39), ')::text ELSE ', 
    c::text, '::text END AS ', c::text, '_convert) AS ', c::text, ','); 

END LOOP; 
strSQL = LEFT(strSQL, character_length(strSQL) - 1); 
strSQL = concat('SELECT ', strSQL, ' FROM ', target_table, ' WHERE nm_site_id = ', chr(39), target_uri, chr(39)); 

RETURN QUERY EXECUTE strSQL; 

RAISE NOTICE 'strSQL: %', strSQL; 
--RETURN strSQL; 
--RETURN QUERY EXECUTE format('SELECT ' || strSQL || 'FROM %s WHERE nm_site_id = $1', pg_typeof(target_table)) USING target_uri; 

END 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
ALTER FUNCTION data_handler(text, text) 
    OWNER TO inti; 
+0

如果你想向用戶展示什麼,而不是空轉到爲什麼這麼多的麻煩?在您使用的任何平臺的視圖中做這件事情要容易得多 – e4c5

回答

0

您可以創建視圖只爲爲好,在下面的示例架構nullsbegone:

-- create the schema to hold the views 
create schema if not exists nullsbegone; 

-- create a function to create the views (any and all that you might need) 
create or replace function nullsbegone.f_make_view_of(p_tablename text) returns void as $f$ 
begin 
    execute ($$ 
create or replace view nullsbegone.$$||(select relname from pg_class where oid = $1::regclass)||$$ 
    returns void as 
    select $$||array_to_string(array(
select case when not attnotnull then 'COALESCE('||quote_ident(attname)||$$::text, (SELECT '<Error:'''||lkp_value||''' value not found>' FROM alb_cr.lkp_field_values 
                        WHERE column_name = $$||quote_literal(attname)||$$)) AS $$ 
     else '' end || quote_ident(attname) 
from pg_attribute 
where attrelid = $1::regclass and attnum > 0 order by attnum 
), E', \n')||$$ 
from $$||$1); 
end;$f$ language plpgsql; 

-- create the view based on a given table 
select nullsbegone.f_make_view_of('yourschema.yourtable'); 

-- select from your view as if you were selecting from the actual table 
select * from nullsbegone.yourtable 
where nm_site_id = 'yoursite';