0

我創建了以下存儲過程,該存儲過程應返回與多邊形組具有交集的所有位置名稱(沒有獨立...交集3個多邊形=> 3名)語法錯誤在DECLARE部分的「VARCHAR」'處或附近嘗試創建函數時

CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time TIMESTAMP, 
                     end_time TIMESTAMP, 
                     polygon_group_id INTEGER) 
RETURNS TABLE(name_name_name_name VARCHAR(12)) AS $$ 
DECLARE 
    name VARCHAR(12); 
    poly_id INTEGER; 
BEGIN 
    FOR poly_id IN (SELECT polygon_id 
        FROM polygon_group_members 
        WHERE group_id = poly_id) 
    LOOP 
     FOR name IN (SELECT DISTINCT name 
        FROM location, polygons 
        WHERE location.timestamp BETWEEN start_time AND end_time 
         AND poly_id = polygons.id 
         AND st_intersects(location.polygon, polygons.polygon)) 
     LOOP 
     RETURN NEXT name; 
     END LOOP; 
    END LOOP; 
    RETURN; 
END; 

$$ LANGUAGE SQL; 

當我試圖創建這個功能我得到了以下錯誤:

[42601] ERROR: syntax error at or near "VARCHAR" Position: 356

基於PostgreSQL的declaration documentation似乎OK ......

我試過到目前爲止:

  • 我改變name VARCHAR(12);name location.mac%TYPE

  • 我改變name VARCHAR(12);name RECORD

  • 我改變了申報的範圍,然後我得到了同樣的錯誤on poly_id INTEGER;

  • 我將LANGUAGE SQL更改爲postgressql

  • 我GOOGLE了它,並根據任何示例/問題,我發現這個過程應該工作。

+0

[有沒有 「存儲過程」,在Postgres的,只是功能(HTTP://stackov erflow.com/a/33896307/939860)。你是否鏈接到Postgres 9.1文檔,因爲這是你的實際版本? –

回答

1

你帶來答案仍然有幾個問題。你可以很好地使用RETURNS TABLE()。比較:

CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time timestamp, 
                     end_time timestamp, 
                     polygon_group_id int) 
    RETURNS TABLE(name_name_name_name VARCHAR(12)) AS 
$func$ 
DECLARE 
    
             
  
    name VARCHAR(12); 
   -- possible naming conflict! 
    poly_id int; 
BEGIN 
    FOR poly_id IN -- no parentheses needed 
     SELECT polygon_id 
     FROM polygon_group_members 
     WHERE group_id = poly_id -- I suspect you really want polygon_group_id here 
    LOOP 
     FOR name_name_name_name IN -- assign directly 
     SELECT DISTINCT name -- l.name or p.name?? 
     FROM polygons p 
     JOIN location l ON st_intersects(l.polygon, p.polygon) 
     WHERE p.id = poly_id 
     AND l.timestamp BETWEEN start_time AND end_time 
     LOOP 
     RETURN NEXT; -- already assigned 
     END LOOP; 
    END LOOP; 
    RETURN; 
END 
$func$ LANGUAGE plpgsql;

注意可能的命名衝突。所有聲明的變量和參數(包括RETURNS TABLE()子句中的字段在plpgsql或SQL函數體內的SQL查詢中都是可見的)普遍的約定是在_前面加上變量名,並對查詢中的所有列進行表限定。從今天:

整體功能很可能與單個SELECT語句來代替

1

你不需要PL/pgSQL。循環是不必要的,並會使一切都非常緩慢。

至於我可以告訴大家這個應該這樣做:

CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time TIMESTAMP, 
                     end_time TIMESTAMP, 
                     polygon_group_id INTEGER) 
    RETURNS TABLE(name_name_name_name VARCHAR(12)) 
AS 
$$ 
    SELECT DISTINCT name 
    FROM location, polygons 
    WHERE location.timestamp BETWEEN start_time AND end_time 
    AND poly_id IN (SELECT polygon_id FROM polygon_group_members WHERE group_id = polygon_group_id) 
    AND st_intersects(location.polygon, polygons.polygon)); 
$$ 
LANGUAGE SQL; 

我也覺得條件WHERE group_id = poly_id是錯了,因爲你使用的是應該將結果存儲在where子句中的變量。我想你的意思是使用WHERE group_id = polygon_group_id(我改變了上面的代碼)


當使用language sql不能使用程序代碼像begin ... end或聲明變量。

錯誤ERROR: syntax error at or near "VARCHAR" Position: 356是由使用language sql引起的,但在函數體內使用了PL/pgSQL。如果在您的定義中將language sql更改爲language plpgsql,它應該可以工作(但同樣具有兩個嵌套循環的解決方案效率不高)。

+0

你說得對'LANGUAGE plpgsql'(在你已刪除的評論中...),然後我得到了一個新的錯誤,我正在處理它......但是,正如我在問題中寫的,沒有明顯的名稱(BTW位置名稱不是主鍵)。第一個循環給了我組中所有的多邊形。第二個循環給我所有與多邊形相交的名稱。該程序將返回所有名稱,但沒有明顯區別,因此如果某個位置與3個多邊形相交(在一段時間內,位置不固定),則結果中會有3個名稱... –

1

感謝@ a_horse_with_no_name的評論我指出$$ LANGUAGE SQL應該是$$ LANGUAGE plpgsql我找到了解決方案。 後,我改變爲$$ LANGUAGE plpgsql我得到了一個新的錯誤有關丟失OUT PARAMETER,但OUT PARAMETER不允許與RETURN NEXT所以我只好回到SETOF而不是TABLE

CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time TIMESTAMP, 
                     end_time TIMESTAMP, 
                     polygon_group_id INTEGER) 
RETURNS SETOF VARCHAR(12) AS $$ 
DECLARE 
    name VARCHAR(12); 
    poly_id INTEGER; 
BEGIN 
    FOR poly_id IN (SELECT polygon_id 
        FROM polygon_group_members 
        WHERE group_id = poly_id) 
    LOOP 
     FOR name IN (SELECT DISTINCT name 
        FROM location, polygons 
        WHERE location.timestamp BETWEEN start_time AND end_time 
         AND poly_id = polygons.id 
         AND st_intersects(location.polygon, polygons.polygon)) 
     LOOP 
     RETURN NEXT name; 
     END LOOP; 
    END LOOP; 
    RETURN; 
END; 

$$ LANGUAGE plpgsql; 
+0

如果a_horse的答案對您有用你說,考慮實際投票 - 就像工具提示建議「這個答案很有用」。 –

+0

@ErwinBrandstetter其實我贊成他的評論。他對已刪除的問題發表了評論......他的回答根本沒有幫助......但是,您的答案比我的解決方案更好(+1並接受)。我只是等待測試.... –

相關問題