在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