2017-01-11 3 views
0

私はシナリオを持っていました。私はdbテーブル名とカラム名を格納するマスターテーブルを持っていました。それに基づいて動的クエリを構築する必要があります。Postgres Dynamic Query

CREATE TABLE MasterTable 
(
    Id int primary key, 
    caption varchar(100), 
    dbcolumnname varchar(100), 
    dbtablename varchar(100) 
); 

CREATE TABLE Engineers 
(
    Id int primary key, 
    Name varchar(100), 
    Salary BigInt 
); 

CREATE TABLE Executives 
(
    Id int primary key, 
    Name varchar(100), 
    Salary BigInt 
); 

CREATE TABLE Manager 
(
    Id int primary key, 
    Name varchar(100), 
    Salary BigInt 
); 

INSERT INTO Manager(Id, Name, Salary) 
VALUES(1, 'Manager 1', 6000000); 
INSERT INTO Executives(Id, Name, Salary) 
VALUES(1, 'Executive 1', 6000000); 
INSERT INTO Engineers(Id, Name, Salary) 
VALUES(1, 'Engineer 1', 6000000); 
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename) 
VALUES (1, 'Name', 'name', 'Engineers'); 
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename) 
VALUES (2, 'Name', 'name', 'Manager'); 
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename) 
VALUES (3, 'Name', 'name', 'Executives'); 
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename) 
VALUES (4, 'Salary', 'Salary', 'Engineers'); 
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename) 
VALUES (5, 'Salary', 'Salary', 'Manager'); 
INSERT INTO MasterTable(Id, caption, dbcolumnname, dbtablename) 
VALUES (6, 'Salary', 'Salary', 'Executives'); 

キャプションとIDを受け入れ、dbcolumnnameとdbtablenameに基づいて結果を返すストアドプロシージャを作成したいと考えています。たとえば、給与、名前をキャプション、IDを1とすると、ストアドプロシージャはdbcolumnとdbtableのクエリになります(以下のようになります)。

Select Id as ID, name as Value from Engineers 
UNION 
Select Id as ID, name as Value from Manager 
UNION 
Select Id as ID, name as Value from Executives 
UNION 
Select Id as ID, Salary as Value from Executives 
UNION 
Select Id as ID, Salary as Value from Engineers 
UNION 
Select Id as ID, Salary as Value from Manager 

ここでは動的SQLについて聞いたことがありますか?

Fiddle

EDITは::私は、出力を得るために労働組合文を作成する1つの動的問合せを得ました、しかし、問題は、私は二重引用符をエスケープすることはできませんしています。以下はクエリとエラーです

Query : 

DO 
$BODY$ 
BEGIN 

EXECUTE string_agg(
    format('SELECT %I FROM %I', dbcolumnname, dbtablename), 
    ' UNION ') 
    FROM MasterTable; 

END; 
$BODY$; 

Error: 
ERROR: relation "Engineers" does not exist 
LINE 1: SELECT name FROM "Engineers" UNION SELECT name FROM "Manager... 
+0

ダイナミッククエリは非常に簡単です。しかし、私はあなたのデータモデルを再考すべきだと思います。あなたが達成したいタスクのために少し複雑すぎるように見える... – JosMac

+0

@JosMacはいそれは複雑ですが、これは私のデータモデルではありません。私はフォーラムで元のデータを投稿できないので、ダミーモデルを作成しました。私は動的クエリで複数のテーブル名を使用することができますか、私は高価な私が信じるカーソルに行く必要があります。 –

+1

動的クエリで必要なクエリを使用できます。挿入/更新などを伴う複雑なCTEイベント。制限はありません。 – JosMac

答えて

0

希望するものを達成する別の方法を提案したいと思います。つまり、PostgreSQLの継承メカニズムを使用しています。例えば

:あなたが使用されるテーブルのセットを制限するためにMasterTableを使用したい場合は、次のように

CREATE TABLE ParentTable (
    Id int, 
    Name varchar(100), 
    Salary BigInt 
); 

ALTER TABLE Engineers INHERIT ParentTable; 
ALTER TABLE Executives INHERIT ParentTable; 
ALTER TABLE Manager INHERIT ParentTable; 

SELECT Id, Salary AS value FROM ParentTable 
UNION 
SELECT Id, Name AS value FROM ParentTable; 

は今、あなたはそれを行うことができます。

SELECT Id, Name AS value 
FROM ParentTable 
INNER JOIN pg_class ON parenttable.tableoid = pg_class.oid 
INNER JOIN MasterTable ON LOWER(dbtablename) = LOWER(relname) 
UNION 
SELECT Id, Salary AS value 
FROM ParentTable 
INNER JOIN pg_class ON parenttable.tableoid = pg_class.oid 
INNER JOIN MasterTable ON LOWER(dbtablename) = LOWER(relname) 

しかし、あなたがすることはできませんこの技法を使用してあるテーブルから別のテーブルに検索するために列のセットを任意に制限します。

0

テーブル名と列名は、彼らは二重引用符でを引用されていない限り、SQLで、小文字を区別しないケースです。 Postgresは引用符で囲まれていない識別子を小文字に変換することでこれを行います。


CREATE TABLE MasterTable 
(
    Id int primary key, 
    caption varchar(100), 
    dbcolumnname varchar(100), 
    dbtablename varchar(100) 
); 

あなたはqで折りたたみケースを回避することができます


CREATE TABLE mastertable 
(
    id int primary key, 
    caption varchar(100), 
    dbcolumnname varchar(100), 
    dbtablename varchar(100) 
); 

としてのPostgresによって解釈されます:だから、あなたのDDLが

名前をuoting:


CREATE TABLE "MasterTable" 
(
    "Id" int primary key, 
    caption varchar(100), 
    dbcolumnname varchar(100), 
    dbtablename varchar(100) 
); 

%Iフォーマット指定子は(内部的に使用していますquote_ident()が)その引数(必要な) に引用符を追加し、そのクエリが"MasterTable"を要求したときにのみ、 mastertableがスキーマに存在します。単なる文字列変数のすべてを構築し、あなたが機能でyourvariable`を実行 `使う -

しかし、それだけでMixedCase機能識別子を避けるためにeasyerで、