2016-04-21 22 views
2

我的數據庫使用Postgres模式爲用戶提供分離的多租戶環境。每個模式都有相同表格的副本。將模式名稱添加到動態Postgres查詢

我有一個特定的查詢,我需要跨模式連接,返回記錄列表(在這種情況下,children)。我通過一個動態的SQL查詢來完成這個工作,如下所示。但是,我想在列中添加每個指定行來自的模式的名稱的結果。

當前動態查詢

(架構的樣子:OPERATOR_SCHEMA_my-great-company

CREATE OR REPLACE FUNCTION all_children_dynamic() RETURNS SETOF children AS $$ 
DECLARE 
    schema RECORD; 
BEGIN 
    FOR schema IN EXECUTE 
    format(
     'SELECT schema_name FROM information_schema.schemata WHERE left(schema_name, 16) = %L', 
     'OPERATOR_SCHEMA_' 
    ) 
    LOOP 
    RETURN QUERY EXECUTE 
     format('SELECT * FROM %I.children', schema.schema_name); 
    END LOOP; 
END; 
$$ LANGUAGE plpgsql; 

-------- 

-- Usage: SELECT "id", "name" FROM all_children_dynamic(); 

這將返回類似:

------------- 
| id | name | 
| 1 | Bob | 
| 2 | Joe | 
------------- 

而我倒是喜歡它返回的東西如:

------------------------------- 
| id | name | schema_name  | 
| 1 | Bob | darcy's-store | 
| 2 | Joe | bob's-4th-store | 
------------------------------- 

應該注意的是,模式名稱是用戶定義的,並且可以在其中引用引號。

如何爲每個孩子添加相關模式名稱?

我曾嘗試以下幾個變化:

LOOP 
    RETURN QUERY EXECUTE 
    format('SELECT %s AS schema_name, * FROM %1$I.children', schema.schema_name); 
END LOOP; 

,但我有與格式等一些問題,有可能是一些quote_X的功能,我應該在這裏使用。

我不是很瞭解Postgres(和一般的數據庫),所以你的耐心感激!

最新通報

以下是我得到了一些變化精確的錯誤。

Input: 
format('SELECT %s AS schema_name, * FROM %1$I.children', schema.schema_name); 

ERROR: column "operator_schema_don" does not exist 
LINE 1: SELECT OPERATOR_SCHEMA_don-t-display-data AS schema_name, * ... 
QUERY: SELECT OPERATOR_SCHEMA_don-t-display-data AS schema_name, * FROM "OPERATOR_SCHEMA_don-t-display-data".children 

Input: 
format('SELECT %s AS schema_name, * FROM %I.children', quote_literal(schema.schema_name), schema.schema_name); 

ERROR: structure of query does not match function result type 
DETAIL: Returned type unknown does not match expected type uuid in column 1. 

更新2

我越來越近,但還沒有應用。

CREATE OR REPLACE FUNCTION all_children_dynamic() RETURNS TABLE (id uuid, schema_name varchar) AS $$ 
DECLARE 
    schema RECORD; 
BEGIN 
    FOR schema IN EXECUTE 
    format(
     'SELECT schema_name FROM information_schema.schemata WHERE left(schema_name, 16) = %L', 
     'OPERATOR_SCHEMA_' 
    ) 
    LOOP 
    RETURN QUERY EXECUTE 
     format('SELECT id, %L AS schema_name FROM %I.children', quote_literal(schema.schema_name), schema.schema_name); 
    END LOOP; 
END; 
$$ LANGUAGE plpgsql; 

ERROR: structure of query does not match function result type 
DETAIL: Returned type unknown does not match expected type character varying in column 2. 
CONTEXT: PL/pgSQL function all_children_dynamic() line 11 at RETURN QUERY 

爲什麼返回類型回到未知狀態?我預計它會插入一個字符串,並返回該類型。

+0

你得到了什麼確切的錯誤?由於您正在爲查詢添加新列(在本例中爲模式名稱),因此函數結果不是集合的子集。對?所以你可能需要看看返回的表類型,如[這裏](http://www.postgresql.org/docs/9.4/static/sql-createfunction.html) – cableload

+0

@cableload我添加了兩個錯誤的例子我一直在嘗試。請記住,我不知道我在做什麼:) – Brandon

+1

正如你所看到的基於錯誤,你不能返回SETOF兒童,因爲你正在添加另一列。嘗試返回預期返回的所有列的表格。你的SQL語法對我來說很好。 – cableload

回答

1

由於您要向查詢添加新列(在本例中爲模式名稱),因此函數結果不是集合的子集。所以需要返回一個表類型,並在其中包含附加列。語法可以看到here

事情是這樣的..

CREATE OR REPLACE FUNCTION all_children_dynamic() RETURNS 
TABLE(col1 col1type,col2 col2type,...., schema_name varchar) AS $$ 

第二個錯誤是由於不當的鑄造成postgres自9版已經真正具體的關於返回的數據類型。例如。如果在函數返回類型中返回varchar(8),則必須返回相同長度的varchar。因此鑄件是必需的。