查询在函数 PostgreSQL 中没有结果数据的目的地

时间:2021-07-01 19:42:02

标签: sql postgresql plpgsql

我有一个函数可以将结果返回给我,但结果不是我所期望的,并且捕获了我收到的错误消息:

query has no destination for result data

这是我的代码 postgresql:

CREATE OR REPLACE FUNCTION teltonika_funelement(
    raw character varying,
    tipo integer)
    RETURNS TABLE(id integer, nombre character varying, value1 character varying) 
    LANGUAGE 'plpgsql'

AS $BODY$
DECLARE     i     INT=1;
            y     INT=1;
            Len1  INT;
    ---------------------------------------------------------------------------
    
BEGIN

     CREATE TEMP TABLE Elements(ID Integer, Nombre CHARACTER VARYING, Value2 CHARACTER VARYING);

    
    IF Tipo=1 THEN
    
        Len1    := LENGTH(Raw)/4;

        WHILE i<=Len1
        LOOP
            INSERT INTO Elements
            SELECT
                 hex_to_int(SUBSTRING(Raw FROM y FOR 2))
                ,NULL
                ,SUBSTRING(Raw FROM y+2 FOR 2);

                 y  :=  y+4;

                 i  :=  i+1;
        END LOOP;
    END IF;
    ---------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    IF Tipo = 2 THEN 
    
        Len1 := LENGTH(Raw)/6;
        
        WHILE i<=Len1
        LOOP
            INSERT INTO Elements
            SELECT
                 hex_to_int(SUBSTRING(Raw FROM y FOR 2))
                ,NULL
                ,SUBSTRING(Raw FROM y+2 FOR 4);

                y := y+6;

                i := i+1;
        END LOOP;
    END IF;
    ---------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    IF Tipo = 4 THEN
    
        Len1 := LENGTH(Raw)/10;
        
        WHILE i<=Len1
        LOOP
            INSERT INTO Elements
            SELECT
                 hex_to_int(SUBSTRING(Raw FROM y FOR 2))
                ,NULL
                ,SUBSTRING(Raw FROM y+2 FOR 8);

                y := y+10;

                i := i+1;
        END LOOP;
    END IF;
    ---------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    IF Tipo = 8 THEN
    
        Len1 := LENGTH(Raw)/18;
        
        WHILE i<=Len1
        LOOP
            INSERT INTO Elements
            SELECT
                 hex_to_int(SUBSTRING(Raw FROM y FOR 2))
                ,NULL
                ,SUBSTRING(Raw FROM y+2 FOR 16);

                y := y+18;

                i := i+1;
        END LOOP;
    END IF;
    ---------------------------------------------------------------------------

    SELECT
         E.ID
        ,PropertyName
        ,CASE
            WHEN (TypeParser = 'INT' AND Active=1) THEN (hex_to_int(Value2):: VARCHAR)
            WHEN (TypeParser = 'DECIMAL(18,1)/1000' AND Active=1)   THEN ((hex_to_int(Value2)/1000)::VARCHAR)
         ELSE 
            Value2
         END Value1
    FROM Elements E
    LEFT JOIN Teltonika_Tbl_ElementsConf TE ON TE.PropertyID=E.ID;
END;
$BODY$;

ALTER FUNCTION public.teltonika_funelement(character varying, integer)
    OWNER TO postgres;

这是错误信息:

query has no destination for result data 

我找不到错误的原因我尝试像这样更改返回:

RETURNS TEXT AS 

我该如何解决,非常感谢您的帮助

1 个答案:

答案 0 :(得分:0)

非 void 函数需要 RETURN 对应于在 RETURNS 处声明的数据类型(或结构)。在您的情况下,包含一个 integer 和两个 character varying 的表。考虑以下测试函数,它返回一个包含 inttext 列的表:

CREATE OR REPLACE FUNCTION myfunc(int)
RETURNS TABLE(val int, txt text)  LANGUAGE 'plpgsql'
AS $$
BEGIN
  CREATE TEMPORARY TABLE tmp(id int,res text) ON COMMIT DROP;

  IF $1=0 THEN 
    INSERT INTO tmp VALUES ($1,'Invalid');
  ELSE 
    FOR i IN 1..$1 LOOP
     INSERT INTO tmp VALUES (i,'txt '||i);
    END LOOP;
  END IF;

  RETURN QUERY SELECT id,res FROM tmp;
END;
$$;

测试

SELECT * FROM myfunc(2);
 val |  txt  
-----+-------
   1 | txt 1
   2 | txt 2
(2 rows)

演示:db<>fiddle

一些想法:

  • 在 plpgsql 中,可以有多个 RETURN 语句,以便代码的不同部分在不退出函数的情况下返回不同的内容。但是,如果您更喜欢有一个中间表来收集信息并最终只返回一次,请确保在函数完成后手动删除该表(或者如果它引发错误!)或者只是将其创建为ON COMMIT DROP。如果您更喜欢前者,请考虑UNLOGGED TABLES
  • 考虑使用 text 而不是 character varying
  • 您的 WHILE 循环使用增量值 1,直到达到某个限制。您可以使用 FOR 循环并去掉 i 子句中的变量 DECLARE。这没什么大不了的,但根据您的函数大小,它可能会让事情变得更简洁。
  • 您可以使用参数顺序而不是其名称,例如$1。这也没什么大不了的,但它可以避免与可能具有相同名称的列发生冲突和/或混淆。
相关问题