Postgresql:错误:使用列表对象值创建临时表时

问题描述

我正在编写一个Postgresql函数(使用pgAdmin GUI),它将使用Java列表对象作为参数从Spring Boot应用程序中调用

提到了我的实际需求here,并提出了创建带有列表值以优化查询的临时表的建议,以下是我尝试从here引用的Postgres函数

CREATE FUNCTION public."getInventory"("vals1Arg" character varying[],"vals2Arg" character varying[])
    RETURNS "INVENTORY"
    LANGUAGE 'sql'      
    
AS 
$BODY$
 
// I assume the below two lines create two temp tables and populate the table 
   with my list object values
CREATE TEMP TABLE t1 AS 
          SELECT * FROM VALUES(vals1Arg)

CREATE TEMP TABLE t2 AS 
          SELECT * FROM VALUES(vals2Arg)

SELECT * FROM "INVENTORY"
    where "COLUMN_1" in (select * from t1)
    and "COLUMN_2" in (Select * from t2);  
   
 $BODY$;

以下是我调用postgres函数代码片段

@Query(nativeQuery = true,value = "select \"getInventory\" (:vals1Arg,:vals2Arg)")
    List<Inventory> getInventoryInfo(List<String> vals1Arg,List<String> vals2Arg);

由于列表将很大,因此我将使用列表对象参数的值创建一个临时表,并将其用于我的选择查询

提前谢谢!

解决方法

有几个问题:

  1. CREATE TABLE ... AS的语法应为

    CREATE TABLE ... AS
       SELECT * FROM (VALUES (...)) AS alias;
    

    代替

    CREATE TABLE ... AS
       SELECT * FROM VALUES (...);
    

    您需要这些括号和别名。

  2. 查询中的子选择不起作用,因为它会将varcharCOLUMN_1)与varchar[](临时表的列)进行比较。>

    要使其正常工作,您必须

    SELECT * FROM "INVENTORY"
       WHERE "COLUMN_1" = ANY (SELECT * FROM t1);
    

如果您要创建临时表而不是直接在SELECT中使用数组,则最好

CREATE TEMP TABLE t1 AS
   SELECT * FROM unnest(vals1Arg) AS u(c);
CREATE TEMP TABLE t2 AS
   SELECT * FROM unnest(scomoIdList) AS u(c);

ANALYZE t1,t2;

RETURN QUERY SELECT * FROM "INVENTORY"
                JOIN t1 ON "INVENTORY"."COLUMN_1" = t1.c
                JOIN t2 ON "INVENTORY"."COLUMN_2" = t2.c;

这假定列表中没有重复的条目。