Curso SQL Server — Edição Definitiva

Módulo 5 — Datas e Horas no SQL Server (Tipos + YEAR, MONTH, DAY, GETDATE, DATEPART, DATEDIFF)

Entenda os tipos de data/hora do SQL Server e aprenda a trabalhar com datas no dia a dia: extração de partes, diferenças, filtros de período e melhores práticas.

Objetivo

Dominar os tipos de data/hora (DATE, TIME, DATETIME, DATETIME2, SMALLDATETIME) e as funções mais usadas na prática: YEAR, MONTH, DAY, GETDATE, DATEPART, DATEDIFF.

Escolher o tipo certo e filtrar períodos corretamente evita perda de registros e erros de precisão.

Comparativo dos tipos de data/hora

TipoTamanhoPrecisãoIntervaloQuando usar
DATE3 bytesDia0001–9999Datas sem hora (aniversário, vencimento)
TIME3–5 bytesAté 100ns00:00:00–23:59:59.9999999Horários (abre/fecha)
DATETIME8 bytes~3ms1753–9999Legado; prefira DATETIME2
DATETIME26–8 bytesAté 100ns0001–9999Timestamp moderno recomendado
SMALLDATETIME4 bytes1 min1900–2079Quando minuto é suficiente

DATE

O que é / Para que serve: Armazena apenas a data (sem hora).

Sintaxe: col DATE

Como funciona: Guarda ano, mês e dia. Ideal para datas puras.

Implicações & boas práticas: • Usa menos espaço. • Combine com TIME se precisar guardar também o horário.

CREATE TABLE Ferias (ColaboradorID INT, Inicio DATE, Fim DATE);
INSERT INTO Ferias VALUES (1,'2025-09-01','2025-09-10');
SELECT * FROM Ferias;

TIME

O que é / Para que serve: Armazena apenas o horário do dia.

Sintaxe: col TIME[(s)] -- s = 0 a 7 casas fracionárias

Como funciona: Quanto maior a precisão, mais bytes são usados (3–5 bytes).

Implicações & boas práticas: • Bom para agendas. • Não guarda fuso/offset.

CREATE TABLE Expediente (DiaSemana TINYINT, Abre TIME(0), Fecha TIME(0));
INSERT INTO Expediente VALUES (1,'08:00','17:00');
SELECT * FROM Expediente;

DATETIME (legado)

O que é / Para que serve: Data e hora com precisão ~3ms.

Sintaxe: col DATETIME

Como funciona: Amplamente usado historicamente, mas com limitações de precisão.

Implicações & boas práticas: • Prefira DATETIME2 em projetos novos. • GETDATE() retorna DATETIME.

CREATE TABLE LogAntigo (CriadoEm DATETIME DEFAULT(GETDATE()));
INSERT INTO LogAntigo DEFAULT VALUES;
SELECT CriadoEm FROM LogAntigo;

DATETIME2

O que é / Para que serve: Data e hora moderna com precisão configurável.

Sintaxe: col DATETIME2[(s)] -- s = 0..7

Como funciona: Mais amplo e preciso que DATETIME; SYSDATETIME() retorna DATETIME2(7).

Implicações & boas práticas: • Recomendado para timestamps. • Pode usar GETUTCDATE/SYSUTCDATETIME para UTC.

CREATE TABLE LogNovo (CriadoEm DATETIME2(3) DEFAULT(SYSDATETIME()));
INSERT INTO LogNovo DEFAULT VALUES;
SELECT CriadoEm FROM LogNovo;

SMALLDATETIME

O que é / Para que serve: Data e hora com precisão de minuto.

Sintaxe: col SMALLDATETIME

Como funciona: Arredonda para o minuto mais próximo (sem segundos fracionários).

Implicações & boas práticas: • Menor armazenamento, mas intervalo até 2079. • Útil quando segundo não é necessário.

CREATE TABLE Eventos (Inicio SMALLDATETIME);
INSERT INTO Eventos VALUES ('2025-09-01 08:15');
SELECT * FROM Eventos;

GETDATE()

O que é / Para que serve: Retorna a data/hora atual do servidor (DATETIME).

Sintaxe: GETDATE()

Como funciona: Avaliado no servidor quando a consulta é executada.

Implicações & boas práticas: • Usa fuso do servidor. • Para maior precisão use SYSDATETIME().

SELECT GETDATE() AS Agora;

YEAR / MONTH / DAY

O que é / Para que serve: Extrair partes de uma data.

Sintaxe: YEAR(data) | MONTH(data) | DAY(data)

Como funciona: Retornam inteiros correspondentes ao ano, mês e dia.

Implicações & boas práticas: • Em filtros, prefira faixas (>= e <) para usar índices, em vez de aplicar função na coluna.

SELECT YEAR(GETDATE()) AS Ano, MONTH(GETDATE()) AS Mes, DAY(GETDATE()) AS Dia;

DATEPART

O que é / Para que serve: Extrair uma parte específica da data, como day, month, year, weekday etc.

Sintaxe: DATEPART(parte, data) -- parte: year, month, day, hour, minute, second, weekday...

Como funciona: Retorna um inteiro de acordo com a parte pedida.

Implicações & boas práticas: • Útil em relatórios. • Evite em colunas em WHERE (pode quebrar índices).

SELECT DATEPART(weekday, GETDATE()) AS DiaSemana, DATEPART(hour, GETDATE()) AS HoraAtual;

DATEDIFF

O que é / Para que serve: Calcular a diferença inteira entre duas datas em uma unidade escolhida.

Sintaxe: DATEDIFF(parte, inicio, fim)

Como funciona: Conta quantas “fronteiras” da unidade foram cruzadas entre início e fim.

Implicações & boas práticas: • Resultado é inteiro (pode “virar” no limite). • Para intervalo completo de um dia, use técnica de faixa aberta (>= e <).

SELECT DATEDIFF(day, '2025-08-01', '2025-08-27') AS Dias;
SELECT DATEDIFF(minute, '2025-08-27 08:00', '2025-08-27 08:59:59.999') AS Minutos;

Filtro de período (técnica sem perder registros)

Evite usar BETWEEN com datas de fim ajustadas manualmente. Prefira a técnica de faixa aberta no fim:

DECLARE @ini DATE = '2025-09-01';
DECLARE @fim DATE = '2025-10-01'; -- dia imediatamente seguinte ao período desejado
SELECT *
FROM Vendas
WHERE CriadoEm >= @ini
  AND CriadoEm < @fim; -- inclui todo 30/09, qualquer fração de segundo
Essa técnica funciona com DATETIME, DATETIME2 e SMALLDATETIME e costuma preservar o uso de índices.

Exercícios práticos

  1. Crie a tabela Pedidos com CriadoEm DATETIME2(3) DEFAULT(SYSDATETIME()) e insira 3 linhas em horários diferentes.
  2. Liste o ano, mês e dia de cada pedido com YEAR, MONTH, DAY.
  3. Crie um relatório de pedidos do mês corrente usando a técnica (>= primeiro dia e < primeiro dia do próximo mês).
  4. Mostre quantos minutos se passaram entre o primeiro e o último pedido usando DATEDIFF.

Referências oficiais & leituras recomendadas