2017-01-11 7 views
0

Ich habe Szenario, wo ich eine Master-Tabelle haben, die Db-Tabellenname und Spaltenname speichert, muss ich dynamische Abfrage basierend darauf erstellen.Dynamische Postgres Abfrage

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'); 

Ich möchte eine gespeicherte Prozedur bauen, die auf Basis von dbcolumnname und dbtablename zurück Beschriftung und Kennzeichnung und geben Ergebnis akzeptiert. Zum Beispiel, wenn ich Gehalt, Name als Überschrift und Id als 1 übergebe, sollte die gespeicherte Prozedur eine Abfrage von dbcolumn und dbtable sein, etwas wie unten.

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 

Ich habe von dynamischen sql gehört, kann das hier verwendet werden?

Fiddle

EDIT :: Ich habe eine dynamische Abfrage, die Union-Anweisung erstellt die Ausgabe zu erhalten, aber Problem ist, ich nicht in der Lage bin doppelte Anführungszeichen zu entkommen. Nachstehend ist die Abfrage und Fehler

+0

Dynamische Abfrage ist sehr einfach - einfach alles in String-Variablen konstruieren und verwenden 'ausführen yourvariable' in Sie funktionieren. Aber ich denke, Sie sollten Ihr Datenmodell überdenken. Sieht für mich etwas zu kompliziert aus für die Aufgabe, die Sie erreichen wollen ... – JosMac

+0

@JosMac Ja, es ist kompliziert, aber das ist nicht mein Datenmodell. Ich habe ein Dummy-Modell erstellt, da ich keine Originaldaten in Foren veröffentlichen kann. Kann ich mehrere Tabellennamen in der dynamischen Abfrage verwenden, oder ich muss für den Cursor gehen, was teuer wäre, glaube ich. –

+1

Sie können jede beliebige Abfrage in der dynamischen Abfrage verwenden. Kompliziertes CTE-Ereignis mit Einfügungen/Aktualisierungen usw. Es gibt keine Einschränkungen. – JosMac

Antwort

0

Ich möchte einen alternativen Weg vorschlagen, was Sie wollen. Das heißt, den PostgreSQL-Vererbungsmechanismus zu verwenden.

Zum Beispiel:

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; 

Nun, wenn Sie MasterTable zu beschränken, um den Satz von Tabellen verwenden möchten, können Sie es wie folgt tun:

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) 

, können Sie jedoch nicht Mit dieser Technik können Sie die Spaltenmenge willkürlich einschränken, um sie von einer Tabelle auf eine andere zu übertragen.

0

Tabellennamen und Spaltennamen sind Groß- und Kleinschreibung in SQL, es sei denn, sie in doppelten Anführungszeichen notiert sind. Postgres tut dies, indem nicht-angebene Identifikatoren in Kleinbuchstaben gefaltet werden.

So, Ihre DDL:


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

Wird von Postgres als


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

Sie Fall von q Falten vermeiden kann interpretiert werden uoting die Namen:


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

Die %I Format-Angabe (intern verwendet quote_ident()) fügt Anführungszeichen ihr Argument (wenn erforderlich) , so fragt die Abfrage "MasterTable" für, wenn nur mastertable ist im Schema vorhanden.

Aber es ist easyer nur Mixedcase Kennungen zu vermeiden,