假設我有:
CREATE TYPE compfoo AS (f1 int, f2 text);
并且我創建了一個foo包含兩列的表:fooid 和 fooname,對應于 compfoo 的欄位,稍后我插入一些記錄1, aa,,,2, bb3, cc
然后,我定義了一個 PL/pgSQL 函式(或多或少如下:)
create or replace function foo_query()
returns text
language plpgsql
as $$
declare
r compfoo;
arr compfoo [];
footemp compfoo;
result text;
begin
for r in
select * from foo where fooid = 1 OR fooid = 2
loop
arr := array_append(arr, r);
end loop;
foreach footemp in array arr
loop
select footemp.f1 into result where footemp.f1 = 1;
end loop;
return result;
end;
$$
我首先foo按列名查詢并將結果保存到arrcompfoo 陣列中。后來,我迭代arr并嘗試通過它們在 compfoo 中定義的欄位名來查詢元素。
我在 Postgres 中本身沒有收到錯誤,但我的函式的結果為空。
我究竟做錯了什么?
uj5u.com熱心網友回復:
RAISE NOTICE應該是你最好的朋友。您可以在代碼的某些點列印某些變數的結果。基本問題是沒有很好的初始化值。arr變數按值初始化,NULL任何操作NULL都NULL重新進行。
另一個問題是在select footemp.f1 into result where footemp.f1 = 1;宣告中。在 Postgres 中,當結果為空時,SELECT INTO按值覆寫目標變數。NULL在第二次迭代中,此查詢的結果為空集,并且result變數設定為 on NULL。
您的示例中最大的問題是編程風格。您使用ISAM 風格,您的代碼可能會非常緩慢。
- 不要
array_append在回圈中使用,當您可以array_agg在查詢中使用函式時,您不需要回圈, SELECT INTO不從表中讀取資料時不要使用,- 不要嘗試重復 Oracle 的模式BULK COLLECT和FOREACH讀取集合。PostgreSQL 不是 Oracle,使用非常不同的體系結構,并且這種模式不會提高性能(就像在 Oracle 上一樣),但您可能會損失一些性能。
您的固定代碼可能如下所示:
CREATE OR REPLACE FUNCTION public.foo_query()
RETURNS text
LANGUAGE plpgsql
AS $function$
declare
r compfoo;
arr compfoo [] default '{}'; --<<<
footemp compfoo;
result text;
begin
for r in
select * from foo where fooid = 1 or fooid = 2
loop
arr := array_append(arr, r);
end loop;
foreach footemp in array arr
loop
if footemp.f1 = 1 then --<<<
result := footemp.f1;
end if;
end loop;
return result;
end;
$function$
postgres-# ;
它回傳預期的結果。但它是如何不撰寫存盤程序的完美示例。不要試圖在存盤程序中替換 SQL。這個程序的所有代碼都可以被一個查詢替換。最后,這段代碼在更大的資料上可能會非常慢。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/522615.html
下一篇:為多個值生成單獨的結果
