Postgresql

使用 PL/pgSQL 函式返回記錄 - 加快查詢速度

  • January 19, 2018

我有一個用 Perl 編寫的非分叉遊戲守護程序,它使用 acync 查詢將玩家統計數據寫入 PostgreSQL 9.3 數據庫。但是當我需要從數據庫中讀取某些內容時(例如玩家被禁止或玩家具有 VIP 身份),我會使用同步查詢。

這會使遊戲暫停片刻,直到從數據庫中讀取該值。

我無法重寫我的遊戲守護程序以使用非同步查詢來讀取值(我嘗試過,但它需要太多更改),所以我的問題是:組合幾個不相關的查詢是否有意義(當我需要做一個新玩家時連接)到 1 個過程,我怎樣才能同時將多個值返回到我的 Perl 程序?

我目前的查詢都以玩家 ID 作為參數並返回 1 個值:

-- Has the player been banned?
select true from pref_ban where id=?

-- What is the reputation of this player?
select
count(nullif(nice, false)) -
count(nullif(nice, true)) as rep
from pref_rep where id=?

-- Is he or she a special VIP player?
select vip > now() as vip from pref_users where id=?

-- How many games has the player played to the end?
select completed from pref_match where id=?

要結合上述查詢,我可能需要一個像這樣的過程:

create or replace function get_user_info(_id varchar) returns XXX as $BODY$
   declare
       is_banned boolean;
       reputation integer;
       is_vip boolean;
       completed_games integer;
   begin

       select 1 into is_banned from pref_ban where id=_id;

       select
       count(nullif(nice, false)) -
       count(nullif(nice, true)) 
       into reputation
       from pref_rep where id=_id;

       select vip > now() into is_vip from pref_users where id=_id;

       select completed into completed_games from pref_match where id=_id;

       return XXX; /* How to return 4 values here? */

   end;
$BODY$ language plpgsql;

請幫我正確申報上述程序。

使用OUT參數與@klin 的答案基本相同,但沒有創建使用者定義的類型。只需將聲明塊中的所有變數作為OUT參數移動到參數列表中:

create or replace function get_user_info(
   IN  _id varchar,
   OUT is_banned boolean,
   OUT reputation integer,
   OUT is_vip boolean,
   OUT completed_games integer
)
-- no returns clause necessary, output structure controlled by OUT parameters
-- returns XXX
as $BODY$
begin
   select true into is_banned from pref_ban where id=_id;

   select
   count(nullif(nice, false)) -
   count(nullif(nice, true)) 
   into reputation
   from pref_rep where id=_id;

   select vip > now() into is_vip from pref_users where id=_id;

   select completed into completed_games from pref_match where id=_id;

   -- no return statement necessary, output values already stored in OUT parameters
   -- return XXX;
end
$BODY$ language plpgsql;

這將返回一條記錄(正好是一條),因此您可以選擇它的值作為普通記錄:

-- this will return all properties (columns) from your function:
select * from get_user_info();

-- these will return one property (column) from your function:
select is_banned from get_user_info();
select (get_user_info()).is_banned;

引用自:https://dba.stackexchange.com/questions/67875