Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql Postgres动态查询_Postgresql_Dynamicquery - Fatal编程技术网

Postgresql Postgres动态查询

Postgresql Postgres动态查询,postgresql,dynamicquery,Postgresql,Dynamicquery,我有一个场景,如果我有一个主表,它存储db表名和列名,我需要在此基础上构建动态查询 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(1

我有一个场景,如果我有一个主表,它存储db表名和列名,我需要在此基础上构建动态查询

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返回结果。例如,若我传递Salary,Name作为标题,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,这里可以使用吗

我得到了一个动态查询,它构建union语句来获取输出,但问题是我无法转义双引号。下面是查询和错误

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...

我想建议一种实现你想要的东西的替代方法。也就是说,使用PostgreSQL继承机制

例如:

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;
现在,如果要使用MasterTable来限制所使用的表集,可以按如下方式执行:

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)

但是,您不能使用此技术任意限制要从一个表检索到另一个表的列集。

表名和列名在SQL中不区分大小写,除非用双引号引起来。Postgres通过将不带引号的标识符折叠成小写来实现这一点

因此,您的DDL:



博士后将解释为



您可以通过引用以下名称来避免大小写重叠:



%I
格式说明符(内部使用quote_ident())在其参数中添加引号(如果需要) ,因此,当模式中仅存在
主表时,查询会询问
“主表”


但是,更容易避免混用case标识符,

动态查询非常简单-只需在字符串变量中构造所有内容,并在函数中使用
执行变量。但我认为你应该重新考虑你的数据模型。在我看来,对于您想要完成的任务来说,有点太复杂了…@JosMac是的,它很复杂,但这不是我的数据模型。我创建了一个虚拟模型,因为我无法在论坛上发布原始数据。我可以在动态查询中使用多个表名吗?或者我必须使用游标,我相信这会很昂贵。您可以在动态查询中使用任何您想要的查询。带有插入/更新等的复杂CTE事件。没有限制。
s/CREATE TABLE Executives/CREATE TABLE“Executives”/
以及其他表的类似内容。或者,更好的方法是:避免表和列的混合大小写名称。
CREATE TABLE MasterTable
(
    Id int primary key,
    caption varchar(100),
    dbcolumnname varchar(100),
    dbtablename varchar(100)
);
CREATE TABLE mastertable
(
    id int primary key,
    caption varchar(100),
    dbcolumnname varchar(100),
    dbtablename varchar(100)
);
CREATE TABLE "MasterTable"
(
    "Id" int primary key,
    caption varchar(100),
    dbcolumnname varchar(100),
    dbtablename varchar(100)
);