2016-03-02 66 views
0

我正在嘗試編寫一個循環遍歷表的plpgsql函數。在每個循環中,它從表中拉出一行,將其存儲在記錄中,然後在查詢的連接子句中使用該記錄。這裏是我的代碼:在函數中使用行作爲查詢中的表格PLpgSQL

CREATE OR REPLACE FUNCTION "testfncjh2"() RETURNS int 
    IMMUTABLE 
    SECURITY DEFINER 
AS $dbvis$ 
DECLARE 
     counter int; 
     tablesize int; 
     rec1 record; 
     tablename text; 
     rec2 record; 
BEGIN 
counter = 0; 
for rec1 in SELECT * FROM poilocations_sridconv loop 

raise notice 'here'; 
execute $$ select count(*) from $$||rec1||$$ $$ into tablesize; 

     while counter < tablesize loop 

       counter = counter + 1; 
       raise notice 'hi'; 
       execute $$ select count(*) from cities_sridconv $$ into tablesize; 
       end loop; 
    end loop; 
return counter; 
END; 
$dbvis$ LANGUAGE plpgsql; 

每次我跑,我得到了以下錯誤:

ERROR: could not find array type for data type record

是否有使用行作爲表查詢嵌套循環內的方法嗎?

我的最終目標是建立一個循環遍歷表的函數,在每個循環中從該表拉出一行。在每個循環中,使用該行計算COUNTER個數,然後根據行和COUNTER執行查詢。知道了這個代碼是目前非常有缺陷的,我下面張貼給的什麼,我試圖做一個想法:

CREATE OR REPLACE FUNCTION「testfncjh」()返回void IMMUTABLE SECURITY DEFINER AS $ dbvis $ DECLARE counter int; tablesize int; rec1記錄; tablename text; rec2記錄; BEGIN

for rec1 in SELECT * FROM poilocations_sridconv loop 
     counter = 0; 
     execute $$ select count(*) 
       from $$||rec1||$$ a 
       join 
         cities_srid_conv b 
       on  right(a.geom_wgs_pois,$$||counter||$$) = right(b.geom_wgs_pois,$$||counter||$$) $$ into tablesize; 

     raise notice 'got through first execute'; 
     while tablesize = 0 loop 

       counter = counter + 1; 
       execute $$ select count(*) 
       from '||rec1||' a 
       join 
         cities_srid_conv b 
       on  right(a.geom_wgs_pois,'||counter||') = right(b.geom_wgs_pois,'||counter||') $$ into tablesize; 
       raise notice 'hi'; 
       end loop; 

     EXECUTE 
       'select 
         poiname, 
         name as cityname, 
         postgis.ST_Distance(postgis.ST_GeomFromText(''POINT(poilat poilong)''), 
              postgis.ST_GeomFromText(''POINT(citylat citylong)'') 
              ) as distance 
       from (select a.poiname, 
           a.latitude::text as poilat, 
           a.longitude::text as poilong, 
           b.geonameid, 
           b.name, 
           b.latitude as citylat, 
           b.longitude as citylong 
         from '||rec1||' a 
         join cities_srid_conv b 
         on right(a.geom_wgs_pois,'||counter||') = right(b.geom_wgs_pois,'||counter||')) 
         ) x 
       order by distance 
     limit 1' 

     poi_cities_match (poiname, cityname, distance); ------SQL STATEMENT TO INSERT CLOSEST CITY TO TABLE POI_CITIES_MATCH 
    end loop; 

END; 
$dbvis$ LANGUAGE plpgsql; 

我一個PostgreSQL 8.2.15數據庫上運行。

此外,很抱歉轉貼。我不得不從原始數據中刪除一些數據。

回答

0

我認爲你應該能夠使用你想要的複合類型。我通過以下方式簡化了頂層示例並使用了複合類型。

CREATE OR REPLACE FUNCTION "testfncjh2"() RETURNS int 
    IMMUTABLE 
    SECURITY DEFINER 
AS $dbvis$ 
DECLARE 
     counter int; 
     tablesize int; 
     rec1 poilocations_sridconv; 
     tablename text; 
     rec2 record; 
BEGIN 
counter = 0; 
for rec1 in SELECT * FROM poilocations_sridconv loop 
    raise notice 'here'; 
    select count(*) FROM (select (rec1).*)theRecord into counter; 
end loop; 
return counter; 
END; 
$dbvis$ LANGUAGE plpgsql; 

主要的變化是在rec1 poilocations_sridconv;線,並使用(select (rec1).*)

希望它能幫助。

編輯:我應該注意,該函數並沒有做同樣的事情,因爲它在上面的問題。這只是您如何在查詢中將記錄用作表格的示例。

0

你有幾個問題與你的代碼(或許,除了你的邏輯)。

首先,您不應該使用record作爲JOIN中的表格源。相反,過濾第二張表的行匹配record中的某個字段。

其次,您應該使用format()函數,而不是使用||運算符裝配字符串。但是你不能,因爲你使用的是史前版本8.2。這是來自洞穴繪畫時代(是的,那很糟糕)。升級!

第三,不要過分複雜化您的查詢。子查詢在這裏沒有必要。

放在一起,從你的實際代碼的第二動態查詢會減少這樣的:

EXECUTE format(
    'SELECT b.name, 
      postgis.ST_Distance(postgis.ST_SetSRID(postgis.ST_MakePoint(%1$I.longitude, %1$I.latitude), 4326), 
           postgis.ST_SetSRID(postgis.ST_MakePoint(b.longitude, b.latitude), 4326)) 
    FROM cities_srid_conv b 
    WHERE right(%1$I.geom_wgs_pois, %2$L) = right(b.geom_wgs_pois, %2$L) 
    ORDER BY distance 
    LIMIT 1', rec1, counter) INTO cityname, distance; 

poi_cities_match (rec1.poiname, cityname, distance); ------SQL STATEMENT TO INSERT CLOSEST CITY TO TABLE POI_CITIES_MATCH 

這裏%1$I參照字符串後的第一個參數,這是一個idenifier:rec1; %2$L是第二個參數,是文字值:counter。我把它留給自己重新工作到8.4之前的字符串連接。查詢結果存儲在一些額外的變量中,然後您可以在以下函數調用中使用它們。

最後,你有longitudelatitude相反。在PostGIS longitude中總是排在第一位。

相關問題