No Snowflake, como faço para CAST CURRENT_TIMESTAMP até o minuto apenas. Não quero segundos, milissegundos ou fuso horário incluídos no meu resultado.
Por que to_timestamp
usa fusos horários diferentes para exibir épocas, na mesma consulta? Nota +02
vs. +01
_
=> select to_timestamp(1651157248),to_timestamp(1647224832);
to_timestamp | to_timestamp
------------------------+------------------------
2022-04-28 16:47:28+02 | 2022-03-14 03:27:12+01
(1 row)
=> select version();
version
----------------------------------------------------------------------------------------------------------------------------------------
PostgreSQL 12.12 (Ubuntu 12.12-0ubuntu0.20.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
(1 row)
=> show timezone;
TimeZone
---------------
Europe/Vienna
(1 row)
Pode estar relacionado com a mudança do horário de inverno para o horário de verão no final de março, com +01
correspondente a CET
e +02
a CEST
.
Como faço para usar to_timestamp
de forma consistente o mesmo deslocamento de tempo (não importa qual)?
Estou usando o PgAdmin 4 v6 e, para alguns dados de timestamp com tipo de dados timestamp with time zone
, estou vendo no PgAdmin assim:
2022-03-06 16:11:33+04
Por que o +04
ser exibido?
Eu olhei para o seguinte guia postgres:
Afirma o seguinte:
Todas as datas e horas com reconhecimento de fuso horário são armazenadas internamente em UTC. Eles são convertidos para a hora local na zona especificada pelo parâmetro de configuração TimeZone antes de serem exibidos ao cliente.
A referência aqui afirma o seguinte sobre a configuração do TimeZone no Postgres:
TimeZone (string)
Define o fuso horário para exibir e interpretar carimbos de hora. O padrão integrado é GMT, mas normalmente é substituído em postgresql.conf; O initdb instalará uma configuração correspondente ao ambiente do sistema.
Isso sugere que um fuso horário derivado de alguma forma do sistema host do banco de dados está sendo adicionado ao postgresql.conf.
Presumo que a razão pela qual vejo o deslocamento no PgAdmin é que o PgAdmin está exibindo uma versão convertida do valor armazenado, com base nas informações de fuso horário para o sistema host do banco de dados, que foi armazenado em postgresql.conf. Alguém pode confirmar se é isso que o PgAdmin faz quando exibe dados com tipo de dados timestamp with timezone
?
A updated
coluna foi criada como
| updated | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
um simples SELECT
dá
+---------------------+
| updated |
+---------------------+
| 2021-12-25 00:15:47 |
+---------------------+
Infelizmente, updated
não foi criado como timestamp(3)
.
Existe alguma maneira de extrair mais precisão de updated
? (o MySQL armazena mais precisão do que o segundo, mesmo que mostre apenas segundos?)
Eu tenho uma coluna Postgresql que é um varchar que está salvando uma string que se parece com '2 years, 5 months'
ou '3 months'
ou '9 years, 0 months
'. Não consigo converter a coluna em um intervalo porque ela quebrará várias funcionalidades existentes, então o que estou tentando fazer é converter esse varchar em um intervalo na instrução select. Não consigo descobrir como fazer isso, estava pensando que primeiro preciso formatá-lo em um timestamp e depois transformá-lo em um intervalo? Mas não consegui encontrar nenhuma informação sobre este caso específico. Obrigado pela ajuda!
Edit 1: a solução de a_horse_with_no_name funcionou, mas eu estava recebendo um erro anteriormente por causa das linhas vazias, então escrevi um caso assim para corrigi-lo
case
when
duration = ''
then
interval '0'
else
duration::interval
end
Estou ciente de que, no PostgreSQL, o valor de retorno de NOW()
é o registro de data e hora do início da transação . Portanto, se você usar NOW()
várias vezes na mesma transação, sempre retornará o mesmo valor.
E isso é bom no meu livro.
Mas eu tenho um pequeno problema com testes de unidade em um aplicativo cliente com isso e adoraria poder dizer ao PostgreSQL para desabilitar (temporariamente) isso, se possível.
A razão pela qual eu não quero (não posso) usar outra função timestamp como clock_timestamp()
é porque a chamada de função NOW()
fica dentro de um gatilho e, no código de produção, quero o comportamento "início da transação".
Mas em meus testes de unidade estou corrigindo a função "commit" no nível da API para não comprometer dados reais acidentalmente no banco de dados durante o teste (não se preocupe, não uso o banco de dados de produção durante o teste). Portanto, durante os testes de unidade, commit
nunca atinge o banco de dados, então não recebo novos registros de data e hora de transação.
O banco de dados usa tabelas temporais e novas entradas são anexadas apenas às tabelas de histórico se o carimbo de data/hora for alterado para garantir que consolidamos apenas uma entrada na tabela de histórico por transação.
Mas ao testar o comportamento da tabela temporal, isso agora faz com que nenhuma entrada apareça nas tabelas de histórico. O fragmento de chave do gatilho da tabela temporal é este:
new_validity_period = tstzrange(
lower(OLD.validity_period),
NOW(),
'[)'
);
IF isempty(new_validity_period) THEN
RAISE DEBUG 'New entry % will not introduce a new history item', OLD;
RETURN OLD;
END IF;
Portanto, quando eu fizer uma operação de "inserção" no meu teste de unidade e o tempo de transação for '2020-01-01 01:02:03', o período de validade dessa entrada será [2020-01-01 01:02:02,)
. Se, ainda no mesmo teste unitário, eu excluir a entrada (e para testar se ela aparece na tabela de histórico), a operação acontece no mesmo TX, e o código acima ficará assim:
new_validity_perion = tstzrange(
'2020-01-01 01:02:03', -- the lower-bound of the 'OLD' row
'2020-01-01 01:02:03', -- the result of 'NOW()'
'[)'
)
-- resulting in an empty range because the two timestamps are identical
IF isempty(new_validity_periond) THEN -- <- Resulting to TRUE
...
RETURN OLD; -- returning here, not continuing to store the history entry
END IF;
-- code below here is skipped
Existe uma maneira de configurar o PG para sempre retornar o tempo de parede ao ligar NOW()
? Os testes são executados em um contêiner docker para que eu tenha controle total sobre o server-config. Mas seria ainda melhor se eu pudesse alterar o comportamento definindo a configuração por meio de um comando SQL, para que eu pudesse alterar apenas o comportamento dos testes da tabela temporal.
Se isso não for possível, eu precisaria usar uma configuração de sessão/transação de banco de dados diferente para esses testes. Isso também é bom, mas eu queria saber se eu poderia controlar esse comportamento do PG.
Apêndice: Isolamento de transação de teste de unidade
Este é o código que uso para isolar as chamadas de confirmação no código do usuário:
@fixture
def rb_session():
"""
Returns a session which will always be rolled back.
"""
engine = create_engine(Configurations.getenv("IPBASE_DATABASE_DSN"))
# Get a *specific* connection from the pool
connection = engine.connect()
# Explicitly start a new connection on the connection we got
# This makes the normal "session.begin()" and "session.commit()"
# calls in SQLAlchemy no-ops as there is already a transaction
# in progress.
transaction = connection.begin()
# Ensure we use the "primed" connection for all our SQLAlchemy
# session needs in our unit-tests.
session = Session(bind=connection)
try:
yield session
finally:
transaction.rollback()
session.close()
connection.close()
No caso do MySQL ,
Os valores TIMESTAMP são armazenados como o número de segundos desde a época ('1970-01-01 00:00:00' UTC)`
No caso de PostgreSQL com versão menor ou igual a 9.6
os valores de timestamp são armazenados como segundos antes ou depois da meia-noite 2000-01-01
No caso de PostgreSQL com versão maior ou igual a 10 , não há explicação sobre isso
Tenho duas perguntas sobre a lógica interna do PostgreSQL.
- Ele ainda usa o mesmo padrão da versão 9.6?
- Por que "meia-noite 2000-01-01"? A época do Unix começa em
1970-01-01 00:00:00 UTC
. A época J2000 começa em12 noon (midday) on January 1, 2000
.
Parece que apenas alguns sistemas usam 2000-01-01 00:00:00
.
Como o PostgreSQL fornece funções para converter UNIX epoch em timestamp to_timestamp
ou vice-versa EXTRACT(EPOCH FROM ...)
, usar o padrão diferente do UNIX epoch parece exigir cálculos de deslocamento adicionais.
Eu criei um created_time
campo BIGINT
em uma tabela MySQL 5.7, agora quero gerar automaticamente um timestamp Unix de milissegundos quando insiro um registro. É possível fazer isso? Eu tentei o código abaixo, mas falhou:
ALTER TABLE db.video_info MODIFY COLUMN created_time bigint(20)
DEFAULT (ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000)) NULL;
Atualmente tenho
SELECT x, plans.name
FROM plans
CROSS JOIN generate_series(timestamp '2021-01-01 06:00'
, timestamp '2021-01-07 22:00'
, interval '1 hour') t(x)
Definição da tabela
create table plans
(
id serial not null
constraint plans_pk
primary key,
name varchar default 50,
duration interval default '01:00:00'::interval
);
o que me dá um produto cartesiano da tabela de planos e da série gerada por timestamp.
Eu gostaria de introduzir uma duração específica para cada linha de planos, para que uma linha pudesse ter "1 hora", enquanto a outra teria "30 minutos" e geraria cada combinação para cada linha. Um CROSS JOIN aqui não funciona, eu tentei:
SELECT x, plans.name
FROM plans
CROSS JOIN generate_series(timestamp '2021-01-01 06:00'
, timestamp '2021-01-07 22:00'
, interval plans.duration) t(x)
SQL Fiddle: http://sqlfiddle.com/#!17/97a12/10
Supondo que eu tenha uma tabela chamada MyTable, com um campo TimeStamp "Created". Eu quero apenas extrair a parte Date desta coluna, e na minha pesquisa encontrei essas alternativas:
SELECT created AS "Original",
date(created) AS "DateFunction",
created::date AS "DoubleColonCast",
cast(created as date) AS "CastFunction",
date_trunc('day', created) AS "DateTrunc"
FROM MyTable
- Em questão de SARGability , qual é o método preferido?
- Qual é a maneira "SQL ANSI" (ou seja, mais portátil)?
- Qual é o mais comum/usado no Postgres?