在PostgreSQL 8.4.9我有一个小游戏,用户可以购买一个VIP(“非常重要的人”)状态:验证时间戳为空或过去
# \d pref_users;
Table "public.pref_users"
Column | Type | Modifiers
------------+-----------------------------+---------------
id | character varying(32) | not null
vip | timestamp without time zone |
如果VIP从未购买它将是NULL。
如果贵宾已过期,它将是< CURRENT_TIMESTAMP。
我试图创建PL/pgSQL的程序,允许有足够的VIP身份的用户留下了一个星期给其他用户,作为“礼物”:
create or replace function pref_move_week(_from varchar,
_to varchar) returns void as $BODY$
declare
has_vip boolean;
begin
select vip > current_timestamp + interval '1 week'
into has_vip from pref_users where id=_from;
if (not has_vip) then
return;
end if;
update pref_users set vip = current_timestamp - interval '1 week' where id=_from;
update pref_users set vip = current_timestamp + interval '1 week' where id=_to;
end;
$BODY$ language plpgsql;
不幸的是这个过程不工作如果授予用户的vip值为NULL,则正确:
# update pref_users set vip=null where id='DE16290';
UPDATE 1
# select id,vip from pref_users where id in ('DE16290', 'DE1');
id | vip
---------+----------------------------
DE1 | 2012-01-05 17:35:17.772043
DE16290 |
(2 rows)
# select pref_move_week('DE16290', 'DE1');
pref_move_week
----------------
(1 row)
# select id,vip from pref_users where id in ('DE16290', 'DE1');
id | vip
---------+----------------------------
DE1 | 2012-01-05 17:43:11.589922
DE16290 | 2011-12-22 17:43:11.589922
(2 rows)
即IF - 上面的陈述似乎不起作用,并通过。
另外我不知道has_vip变量是否需要在这里呢?
和我如何能确保主键_from和_TO是在pref_users表确实存在,或者是这个已经照顾(因为UPDATE的一个语句将“抛出一个异常“并且交易将被回滚)?
UPDATE:
感谢您对所有的答复和我也有一个提示使用方法:
if (not coalesce(has_vip, false)) then
return;
end if;
但现在我有一个新的问题:
# select id,vip from pref_users where id in ('DE16290', 'DE1');
id | vip
---------+----------------------------
DE1 | 2012-01-05 17:43:11.589922
DE16290 |
(2 rows)
(即DE1有贵宾到五月,应该能够每周给DE16290,但):
# select pref_move_week('DE1', 'DE16290');
pref_move_week
----------------
(1 row)
# select id,vip from pref_users where id in ('DE16290', 'DE1');
id | vip
---------+----------------------------
DE1 | 2012-01-05 17:43:11.589922
DE16290 |
(2 rows)
(出于某种原因,一切都没有改变?)
更新2:最终的解决方案 -
create or replace function pref_move_week(_from varchar,
_to varchar) returns void as $BODY$
begin
select 1 from pref_users
where id=_from and
vip > current_timestamp + interval '1 week';
if not found then
return;
end if;
update pref_users set
vip = vip - interval '1 week'
where id=_from;
update pref_users set
vip = greatest(vip, current_timestamp) + interval '1 week'
where id=_to;
end;
$BODY$ language plpgsql;
谢谢 - 是的,我有Perl,PHP,Java,C的经验 - 但每当我必须使用SQL(除了基本的选择/更新/删除语句)之外,我非常努力并且不得不四处询问。有关我更新的问题的任何建议吗? – 2011-12-29 20:06:09
编辑我的答案......假设我已经遵循了这个逻辑,我认为如果VIP为空则返回else继续。有点有趣的是,如果(不是has_vip)让我对它应该返回的东西感到困惑。 – Twelfth 2011-12-29 20:38:02
你的方式更好,谢谢 – 2011-12-29 20:57:57