【发布时间】:2014-08-10 07:09:38
【问题描述】:
在 PostgreSQL 9.3 中,我有以下带有 2 个时间戳的表格:
create table pref_users (
id varchar(32) primary key,
first_name varchar(64) not null,
last_name varchar(64),
female boolean,
avatar varchar(128),
city varchar(64),
mobile varchar(64),
login timestamp default current_timestamp,
logout timestamp,
last_ip inet,
vip timestamp, /* XXX can be NULL */
grand timestamp, /* XXX can be NULL */
mail varchar(256),
green integer,
red integer,
medals integer not null default 0
);
时间戳vip 和grand 表明我的游戏用户是否已经支付了某些特权 - 直到这些日期。
当用户连接到我的游戏服务器时,我使用OUT 参数调用以下过程:
create or replace function pref_get_user_info(
IN _id varchar,
OUT is_banned boolean,
OUT is_grand boolean,
OUT is_vip boolean,
OUT rep integer
) as $BODY$
begin
is_banned := exists(select 1 from pref_ban where id=_id);
if is_banned then
return;
end if;
select
grand > current_timestamp,
vip > current_timestamp,
into is_grand is_vip
from pref_users where id=_id;
if is_grand or is_vip then
return;
end if;
select
count(nullif(nice, false)) -
count(nullif(nice, true))
into rep
from pref_rep where id=_id;
end;
$BODY$ language plpgsql;
这确实很好用,但有时会将 NULL 值传递给我的游戏守护进程(到 Perl 脚本):
# select * from pref_get_user_info('OK674418426646');
is_banned | is_grand | is_vip | rep
-----------+----------+--------+-----
f | | | 126
(1 row)
虽然我不需要NULL(它会在我的 Perl 脚本中打印一个警告)——我只需要一个“真”或“假”值。
所以我试过了:
select
coalesce(grand, 0) > current_timestamp,
coalesce(vip, 0) > current_timestamp,
into is_grand is_vip
from pref_users where id=_id;
但这给了我错误:
# select * from pref_get_user_info('OK674418426646');
ERROR: COALESCE types timestamp without time zone and integer cannot be matched
LINE 2: coalesce(grand, 0) > current_timesta...
^
QUERY: select
coalesce(grand, 0) > current_timestamp,
coalesce(vip, 0) > current_timestamp,
is_vip
from pref_users where id=_id
CONTEXT: PL/pgSQL function pref_get_user_info(character varying) line 9 at SQL statement
所以我想知道在这里做什么?
我真的需要吗
select
coalesce(grand, current_timestamp - interval '1 day') > current_timestamp,
coalesce(vip, current_timestamp - interval '1 day') > current_timestamp,
into is_grand is_vip
from pref_users where id=_id;
或者有没有更好的方法(比如“epoch start”或“yesterday”)?
更新:
按照 Clodoaldo Neto 的建议(谢谢!)我试过了:
select
coalesce(grand > current_timestamp, false),
coalesce(vip > current_timestamp, false),
into is_grand is_vip
from pref_users where id=_id;
但是当vip 为NULL 时is_vip 为NULL:
# select * from pref_get_user_info('OK674418426646');
is_banned | is_grand | is_vip | rep
-----------+----------+--------+-----
f | t | |
(1 row)
当我尝试以下任一方法时,会出现语法错误:
select
coalesce(grand > current_timestamp, false),
coalesce(vip > current_timestamp, false),
into is_grand, is_vip
from pref_users where id=_id;
select
coalesce(grand > current_timestamp, false),
coalesce(vip > current_timestamp, false),
into (is_grand, is_vip)
from pref_users where id=_id;
我如何在此处将SELECT 一次转换为 2 个变量?
【问题讨论】:
-
在编辑的第一个版本中,删除第三行末尾“into”之前的逗号。
-
哦,对了,愚蠢的我(在 vi-editor 中复制了上面的行)。但是两个变量之间的逗号呢?两种方式都在“psql”提示符下被接受,但提供不同的结果......
标签: postgresql timestamp postgresql-9.3