Sua coluna
created_at
é timestamp without time zone
. Mas
now()
retorna timestamp with time zone
. A expressão now() - '1 hour'::interval
está sendo forçado a timestamp [without time zone]
, que traz dois problemas :1.) Você não pediu este, mas a expressão não é confiável. Seu resultado depende da configuração de fuso horário atual da sessão em que a consulta está sendo executada. Detalhes aqui:
Para tornar a expressão clara, você pode usar:
now() AT TIME ZONE 'Europe/London' -- your time zone here
Ou apenas (leia o manual aqui) :
LOCALTIMESTAMP -- explicitly take the local time
Eu consideraria trabalhar com
timestamptz
em vez disso.Nenhum dos dois resolve seu segundo problema:
2.) Responda à sua pergunta. A exclusão de restrição não funciona. Por documentação:
Minha ênfase em negrito.
now()
é a implementação Postgres de CURRENT_TIMESTAMP
. Como você pode ver no catálogo do sistema, é apenas STABLE
, não IMMUTABLE
:SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
Soluções
1.) Você pode superar a limitação fornecendo uma constante no
WHERE
condição (que é sempre "imutável"):select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2.) Ou "fingindo" uma função imutável:
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
E depois:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
Tenha cuidado como você usa isso:while
now()
é STABLE
(não muda durante a transação), muda altere entre as transações, portanto, tome cuidado para não usar isso em instruções preparadas (exceto como valor de parâmetro) ou índices ou qualquer coisa que possa mordê-lo. 3.) Ou você pode adicionar uma constante aparentemente redundante
WHERE
cláusulas para sua consulta atual que correspondem à restrição em sua partição:SELECT count(*)
FROM events
WHERE created_at > now() - '1 hour'::interval
AND created_at >= '2015-04-01 00:00:00'::timestamp
AND created_at <= '2015-04-30 23:59:59.999999'::timestamp;
Apenas certifique-se de que
now() - '1 hour'::interval
cai na partição certa ou você não obtém resultados, obviamente. A parte:eu prefiro usar essa expressão em
CHECK
restrições e consultas. Mais fácil de manusear e faz o mesmo: created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp