У меня есть не разветвляющийся игровой демон, написанный на Perl , который использует асинхронные запросы для записи статистики игрока в базу данных PostgreSQL 9.3. Но когда мне нужно что-то прочитать из базы данных (например, если игрок забанен или у игрока есть VIP-статус), тогда я использую синхронные запросы.
Это останавливает игру на короткое время, пока значение не будет считано из базы данных.
Я не могу переписать свой игровой демон, чтобы использовать асинхронные запросы для чтения значений (я пытался, но это потребовало слишком много изменений), поэтому мой вопрос : имеет ли смысл объединять несколько несвязанных запросов (что мне нужно сделать, когда новый игрок подключается) к 1 процедуре, и как я могу вернуть несколько значений одновременно моей программе Perl?
Все мои текущие запросы принимают идентификатор игрока в качестве параметра и возвращают 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;
Пожалуйста, помогите мне правильно описать вышеописанную процедуру.
источник
NULL
илиTRUE
в моейis_banned
переменной с этим утверждением:select true into is_banned from pref_ban where id=_id
. Есть ли способ изменить это наFALSE
илиTRUE
?is_banned := exists(select 1 from pref_ban where id=_id)
должно работать, но это другой вопрос.Вы должны определить составной тип. Вы можете использовать его как тип возвращаемого значения функции и для записи переменных внутри функции.
Пример:
На мой взгляд, использование таких функций вполне разумно с точки зрения как производительности, так и логики приложения.
Определяемые пользователем составные типы очень полезны, если вы хотите вернуть набор строк из вашей функции. Затем вы должны определить тип возвращаемого значения функции
setof composite-type
и использоватьreturn next
илиreturn query.
Пример:
источник
OUT
параметров позволяет достичь практически того же, но без создания пользовательских типов: postgresql.org/docs/current/static/…OUT
параметры - но какSELECT
их в моем случае 4 несвязанных запроса?drop type if exists user_type cascade; create type user_type as(...);
потому что мой Perl-скрипт вызывает операторы SQL каждый раз при запуске.