Timestamp corrente in MySQL: NOW(), CURRENT_TIMESTAMP, SYSDATE(), UTC e migliori pratiche

目次

1. L’SQL più breve per ottenere la data/ora corrente in MySQL

Se vuoi ottenere la data/ora corrente in MySQL, le prime funzioni da ricordare sono NOW() e CURRENT_TIMESTAMP. Di seguito trovi gli esempi SQL più brevi per caso d’uso.

1.1 Ottieni la data/ora corrente (base)

SELECT NOW();

or

SELECT CURRENT_TIMESTAMP;
  • Entrambi restituiscono la data/ora corrente (YYYY-MM-DD HH:MM:SS).
  • All’interno della stessa query, l’ora è fissata al “tempo di inizio della query”.

Casi d’uso

  • Log
  • Ottenere il timestamp di creazione di un record
  • Ottenere un’ora di riferimento

Errore comune

  • Il fuso orario dell’app e quello del DB differiscono e si verificano “spostamenti di tempo”. → Verifica con SELECT @@session.time_zone;

1.2 Ottieni solo la data di oggi

SELECT CURDATE();
  • Formato di ritorno: YYYY-MM-DD
  • Il tipo è DATE (solo data, non datetime)

Casi d’uso

  • Ricerca dei dati “di oggi”
  • Aggregazione giornaliera

Note

  • A differenza di NOW(), non include l’ora.
  • Se ti serve l’ora per query di intervallo, usa NOW().

1.3 Ottieni solo l’ora corrente

SELECT CURTIME();
  • Formato di ritorno: HH:MM:SS
  • Il tipo è TIME (solo ora)

Casi d’uso

  • Visualizzare il tempo di esecuzione di un batch
  • Stampare solo la parte dell’ora nei log

Insidia comune

  • Poiché non include una data, non può essere usato per confronti datetime.

1.4 Ottieni l’ora corrente in UTC (importante)

SELECT UTC_TIMESTAMP();
  • Restituisce UTC indipendentemente dal fuso orario del server.
  • Consigliato per servizi globali.

Politica di base nei progetti reali

  • Memorizzare in UTC
  • Convertire in ora locale al momento della visualizzazione

Note

  • Se l’app converte già in UTC, attenzione alla doppia conversione.

1.5 Ottieni millisecondi / microsecondi

SELECT NOW(3);  -- milliseconds (3 digits after the decimal point)
SELECT NOW(6);  -- microseconds (6 digits after the decimal point)
  • Disponibile in MySQL 5.6.4 e successive.
  • Usato per log ad alta precisione e audit delle transazioni.

Idea sbagliata comune

  • NOW() da solo non può restituire secondi frazionari.
  • Anche la tua colonna deve specificare la precisione, ad es. DATETIME(6).

1.6 La migliore funzione per caso d’uso (inizia qui se non sei sicuro)

Use caseRecommended function
General current datetimeNOW()
Table default valueCURRENT_TIMESTAMP
Date onlyCURDATE()
Time onlyCURTIME()
Unified UTC managementUTC_TIMESTAMP()
High-precision logsNOW(6)

Punti chiave che la gente spesso dimentica

  • NOW() e CURRENT_TIMESTAMP sono effettivamente equivalenti (stesso valore)
  • All’interno della stessa query, l’ora è fissata
  • Il valore visualizzato cambia a seconda delle impostazioni del fuso orario
  • Per i microsecondi, la definizione della tua colonna deve specificare la precisione

2. Differenze tra NOW() / CURRENT_TIMESTAMP / SYSDATE()

Esistono diverse funzioni per ottenere l’ora corrente, ma la parte più confusa è la differenza tra NOW(), CURRENT_TIMESTAMP e SYSDATE().
Se non la comprendi correttamente, potresti ottenere comportamenti inattesi nei log e nell’elaborazione delle transazioni.

2.1 NOW() e CURRENT_TIMESTAMP sono effettivamente equivalenti

SELECT NOW(), CURRENT_TIMESTAMP;
  • Entrambi restituiscono il datetime corrente (un valore DATETIME).
  • All’interno della stessa query, l’ora è fissata al “tempo di inizio della query”.
  • CURRENT_TIMESTAMP può anche essere usato con la sintassi di chiamata funzione:
    SELECT CURRENT_TIMESTAMP();
    

Come scegliere nei progetti reali

Use caseRecommended
Simple retrievalNOW()
Table DEFAULT / ON UPDATECURRENT_TIMESTAMP

Punti importanti

  • Il significato del valore recuperato è lo stesso.
  • La differenza principale è nella sintassi/uso (ad es., consentito in DEFAULT).
  • Non è una differenza di tipo (facile da fraintendere).

2.2 SYSDATE() restituisce l’ora al “tempo di valutazione”

SYSDATE() sembra simile a NOW(), ma il momento in cui il valore viene fissato è diverso.

SELECT NOW(), SLEEP(2), NOW();

Risultato (esempio):

2025-02-23 14:00:00
2025-02-23 14:00:00
SELECT SYSDATE(), SLEEP(2), SYSDATE();

Risultato (esempio):

2025-02-23 14:00:00
2025-02-23 14:00:02

La differenza fondamentale

FunctionWhen the time is fixed
NOW()Query start time
SYSDATE()Evaluation time

In altre parole, SYSDATE() può cambiare all’interno della stessa query man mano che il tempo avanza.

2.3 Note per le transazioni e la replica

Poiché NOW() è fissato all’inizio della query, è
più sicuro quando hai bisogno di un tempo di riferimento coerente all’interno di una transazione.

D’altra parte, poiché SYSDATE() dipende dal timing di esecuzione, può influire sulla riproducibilità in:

  • Replica
  • Lavori batch
  • Elaborazione di log in blocco

Regola pratica

  • Vuoi un tempo di riferimento fisso → NOW()
  • Hai bisogno dell’istante esatto ogni volta → SYSDATE() (uso limitato)

2.4 Nota: CURRENT_DATE / CURRENT_TIME / LOCALTIME

MySQL supporta anche:

SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT LOCALTIME;
  • CURRENT_DATE → uguale a CURDATE()
  • CURRENT_TIME → uguale a CURTIME()
  • LOCALTIME → uguale a NOW()

Confusione comune

  • Queste sono per lo più “differenze cosmetiche”; c’è poca differenza funzionale.
  • Per sicurezza, dai priorità alla leggibilità e standardizza all’interno del progetto.

Punti chiave di questa sezione

  • NOW() e CURRENT_TIMESTAMP significano essenzialmente la stessa cosa.
  • SYSDATE() si comporta diversamente perché si basa sul tempo di valutazione.
  • Per tempi di riferimento fissi, usa NOW() come predefinito.
  • Usa CURRENT_TIMESTAMP per DEFAULT e ON UPDATE.

3. Modifica il formato di visualizzazione della data/ora corrente

Il tempo corrente ottenuto con NOW() viene visualizzato per impostazione predefinita come YYYY-MM-DD HH:MM:SS. Nel lavoro reale, avrai spesso bisogno di cose come:

  • Mostrare solo la data
  • Usare YYYY/MM/DD
  • Usare un formato localizzato (es., 23 feb 2025)
  • Mostrare i millisecondi

Per questo, usa DATE_FORMAT() (converti un datetime in un formato stringa arbitrario).

3.1 Sintassi di base di DATE_FORMAT()

DATE_FORMAT(datetime, 'format_string')

Esempio: Converti il tempo corrente in YYYY/MM/DD HH:MM

SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i');

Esempio di output:

2025/02/23 14:35

Specificatori di formato comuni

SpecifierMeaningExample
%Y4-digit year2025
%m2-digit month02
%d2-digit day23
%HHour (24-hour)14
%iMinutes35
%sSeconds50
%fMicroseconds123456

Note

  • Alcuni specificatori differiscono tra maiuscole e minuscole.
  • %h è il formato a 12 ore, %H è il formato a 24 ore.

3.2 Esempi di formato comuni (frequenti nel lavoro reale)

1. Separato da slash

SELECT DATE_FORMAT(NOW(), '%Y/%m/%d');

2. Localizzato (Inglese)

SELECT DATE_FORMAT(NOW(), '%b %d, %Y');

3. Senza secondi

SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');

Trappola comune

  • Poiché restituisce una stringa, non puoi usarla per calcoli numerici.
  • Per confronti e ricerche, dovresti usare il tipo DATETIME originale.

3.3 Estrai solo la parte data o ora

Puoi anche recuperare le parti mantenendo il tipo (invece di formattare in una stringa).

SELECT DATE(NOW());   -- date only (DATE type)
SELECT TIME(NOW());   -- time only (TIME type)
SELECT YEAR(NOW());   -- year only
SELECT MONTH(NOW());  -- month only
SELECT DAY(NOW());    -- day only

Uso consigliato

GoalRecommended
Formatting for displayDATE_FORMAT
Calculation / comparisonDATE() / TIME()

3.4 Visualizza con microsecondi

Quando hai bisogno di log ad alta precisione:

SELECT NOW(6);

Con formattazione:

SELECT DATE_FORMAT(NOW(6), '%Y-%m-%d %H:%i:%s.%f');

Note importanti

  • La tua colonna deve essere DATETIME(6) o TIMESTAMP(6), altrimenti la precisione non verrà memorizzata.
  • Non disponibile nelle versioni di MySQL precedenti alla 5.6.4 (dipendente dall’ambiente).

Errori comuni

  • Usare DATE_FORMAT() in una clausola WHERE impedisce l’uso degli indici. wp:list /wp:list

    • Esempio errato: WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-23'
    • Consigliato: WHERE created_at >= '2025-02-23 00:00:00' AND created_at < '2025-02-24 00:00:00'
    • Memorizzare direttamente la stringa formattata per la visualizzazione (danneggia le prestazioni di ricerca)

Punti chiave di questa sezione

  • Usa DATE_FORMAT() per cambiare i formati di visualizzazione.
  • Per calcoli/confronti, mantieni il tipo originale.
  • Se hai bisogno di microsecondi, specifica la precisione nella definizione della colonna.
  • Usare funzioni nelle clausole WHERE può causare problemi di prestazioni.

4. Calcoli datetime usando il tempo corrente

In MySQL, è comune calcolare cose come “N ore dopo”, “N giorni fa” o “gli ultimi N giorni” basati sull’ora corrente.
Il caso più comune nel mondo reale è “ottenere dati dalle ultime 24 ore.”

La base dell’aritmetica delle date e ore è INTERVAL (sintassi per aggiungere/sottrarre unità di tempo).

4.1 Aggiungi/sottrai con INTERVAL

Ottieni 1 ora dopo

SELECT NOW() + INTERVAL 1 HOUR;

Ottieni 3 giorni fa

SELECT NOW() - INTERVAL 3 DAY;

Ottieni 1 mese dopo

SELECT NOW() + INTERVAL 1 MONTH;

Unità comuni

UnitMeaning
SECONDSeconds
MINUTEMinutes
HOURHours
DAYDays
WEEKWeeks
MONTHMonths
YEARYears

Errori comuni

  • DAY in INTERVAL 1 DAY funziona anche in minuscolo, ma dovresti standardizzare all’interno del team.
  • I calcoli di fine mese possono differire dalle aspettative perché il numero di giorni varia (ad es., 31 gen + 1 mese).

4.2 Ottieni dati dalle ultime 24 ore (pattern più comune)

SELECT *
FROM users
WHERE created_at >= NOW() - INTERVAL 1 DAY;

Significato

  • Punta a “dal momento attuale indietro di 24 ore.”

Note

  • Se usi CURDATE() , la baseline diventa “oggi alle 00:00”, che cambia il significato.

Esempio (dati di oggi):

SELECT *
FROM users
WHERE created_at >= CURDATE();

Comprendere la differenza è critico

ExpressionMeaning
NOW() - INTERVAL 1 DAYPast 24 hours
CURDATE()Since today 00:00

4.3 Ottieni differenze di giorni con DATEDIFF()

SELECT DATEDIFF('2025-03-01', '2025-02-23');

Risultato:

6
  • L’unità è “giorni”
  • La parte oraria viene ignorata

Note

  • Il segno cambia a seconda dell’ordine degli argomenti.
  • Non puoi calcolare differenze in ore/minuti/secondi.

4.4 Usa TIMESTAMPDIFF() per ore/minuti/secondi

SELECT TIMESTAMPDIFF(HOUR,
                     '2025-02-23 12:00:00',
                     '2025-02-23 18:30:00');

Risultato:

6

Minuti

SELECT TIMESTAMPDIFF(MINUTE,
                     '2025-02-23 12:00:00',
                     '2025-02-23 12:30:00');

Secondi

SELECT TIMESTAMPDIFF(SECOND,
                     '2025-02-23 12:00:00',
                     '2025-02-23 12:00:45');

Casi d’uso

  • Calcoli di durata sessione
  • Controlli di scadenza
  • Decisioni di timeout

4.5 Ottieni inizio mese / fine mese (trappola comune nel mondo reale)

Ottieni il primo giorno di questo mese:

SELECT DATE_FORMAT(NOW(), '%Y-%m-01');

Primo giorno del mese successivo:

SELECT DATE_FORMAT(NOW() + INTERVAL 1 MONTH, '%Y-%m-01');

Note

  • La fine mese non è una data fissa.
  • Per query di intervalli, “>= inizio AND < primo giorno del mese successivo” è sicuro.

Riepilogo errori comuni

  • Usare BETWEEN con valori di data-only e dimenticare l’ora
  • Disabilitare gli indici usando DATE(created_at) nelle clausole WHERE
  • Cadere nella trappola del “giorno 31” nei calcoli mensili
  • Fraintendere la differenza tra NOW() e CURDATE()

Punti chiave di questa sezione

  • INTERVAL è la base dell’aritmetica delle date e ore.
  • Ultime 24 ore = NOW() - INTERVAL 1 DAY .
  • Giorni = DATEDIFF() ; unità più piccole = TIMESTAMPDIFF() .
  • Sii attento con le condizioni di fine per i calcoli basati su mesi.

5. Per query di intervalli, questo è più sicuro di BETWEEN

Quando si eseguono ricerche di intervalli di date in MySQL, molti principianti usano BETWEEN. Tuttavia, spesso produce risultati non intenzionali se non gestisci correttamente i confini temporali, quindi un pattern più sicuro è raccomandato nel lavoro reale.

5.1 Basi di BETWEEN e la trappola

Una query comune

SELECT *
FROM orders
WHERE order_date BETWEEN '2025-02-01' AND '2025-02-10';

Sembra a posto, ma internamente è equivalente a:

WHERE order_date &gt;= '2025-02-01 00:00:00'
  AND order_date &lt;= '2025-02-10 00:00:00'

Quindi non include dati dopo le 00:00 del 10 feb.


5.2 Pattern più sicuro (raccomandato)

Pattern raccomandato

SELECT *
FROM orders
WHERE order_date &gt;= '2025-02-01 00:00:00'
  AND order_date &lt;  '2025-02-11 00:00:00';

Punti chiave

  • Specificare il limite finale come “meno del giorno successivo alle 00:00”
  • Più sicuro di <= 23:59:59 (supporta i microsecondi)

5.3 Il modo corretto per ottenere i dati di oggi

Esempio errato:

WHERE DATE(created_at) = CURDATE();

Problemi:

  • Applicare una funzione alla colonna disabilita gli indici
  • Può causare rallentamenti seri su tabelle grandi

Consigliato:

WHERE created_at &gt;= CURDATE()
  AND created_at &lt;  CURDATE() + INTERVAL 1 DAY;

Questo assicura:

  • Gli indici possono essere usati
  • Ricerche veloci
  • Nessun problema di limiti

5.4 Modelli sicuri per gli ultimi 7 / ultimi 30 giorni

Ultimi 7 giorni

WHERE created_at &gt;= NOW() - INTERVAL 7 DAY;

Ultimi 30 giorni

WHERE created_at &gt;= NOW() - INTERVAL 30 DAY;

Note

  • CURDATE() - INTERVAL 7 DAY si basa su “oggi 00:00”
  • NOW() - INTERVAL 7 DAY si basa su “ora corrente”
  • Scegliere in base ai requisiti

5.5 Regola chiave per mantenere gli indici efficaci

Errato:

WHERE DATE(created_at) = '2025-02-23';

Corretto:

WHERE created_at &gt;= '2025-02-23 00:00:00'
  AND created_at &lt;  '2025-02-24 00:00:00';

Perché:

  • Gli indici funzionano sulla “colonna stessa”
  • Applicare una funzione impedisce l’uso dell’indice (scansione completa)

Riepilogo degli errori comuni

  • Dimenticare di includere l’ora nel limite finale in BETWEEN
  • Mancare i microsecondi quando si usa 23:59:59
  • Usare DATE() nelle clausole WHERE rallentando le query
  • Lasciare ambigua la differenza tra “now” e “today 00:00”

Punti chiave di questa sezione

  • Le query di intervallo sono più sicure con >= start AND < end.
  • BETWEEN richiede una gestione attenta dei limiti.
  • Per mantenere gli indici efficaci, non avvolgere le colonne in funzioni.
  • Scegliere chiaramente tra logica basata su NOW() e logica basata su CURDATE().

6. DEFAULT CURRENT_TIMESTAMP e ON UPDATE (concetti base di progettazione tabelle)

Nella progettazione di database, è comune gestire automaticamente created_at e updated_at.
In MySQL, CURRENT_TIMESTAMP consente di impostare automaticamente l’ora corrente durante l’inserimento e l’aggiornamento.

6.1 Impostazione automatica di created_at (DEFAULT CURRENT_TIMESTAMP)

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Comportamento:

INSERT INTO users (name) VALUES ('Alice');

→ L’ora corrente viene inserita automaticamente in created_at.

Punti chiave

  • CURRENT_TIMESTAMP può essere usato in DEFAULT.
  • NOW() non può essere usato direttamente in DEFAULT.

Errore comune

created_at DATETIME DEFAULT NOW();  -- error

Motivo:

  • In MySQL, generalmente non è possibile impostare una funzione come DEFAULT (l’eccezione è CURRENT_TIMESTAMP).

6.2 Aggiornamento automatico di updated_at (ON UPDATE)

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
               ON UPDATE CURRENT_TIMESTAMP
);

Comportamento:

UPDATE users SET name = 'Bob' WHERE id = 1;

updated_at viene aggiornato automaticamente all’ora corrente.

Casi d’uso

  • Tracciamento ultimo accesso
  • Cronologia aggiornamenti
  • Log di audit

6.3 DATETIME vs TIMESTAMP (importante)

TypeRangeTime zone impact
DATETIMEYear 1000 to 9999No
TIMESTAMP1970 to 2038Yes

La differenza essenziale

  • TIMESTAMP è memorizzato internamente in UTC e convertito al fuso orario della sessione al momento della visualizzazione.
  • DATETIME memorizza il valore letterale (senza conversione).

Linee guida

CaseRecommended type
Log managementTIMESTAMP
Future dates (after 2038)DATETIME
Fixed values not requiring TZ conversionDATETIME

6.4 CURRENT_TIMESTAMP può essere usato anche con DATETIME

In MySQL 5.6 e successive, è possibile specificare CURRENT_TIMESTAMP come DEFAULT e ON UPDATE anche per le colonne DATETIME.

created_at DATETIME DEFAULT CURRENT_TIMESTAMP

Note

  • Le versioni MySQL più vecchie hanno restrizioni (dipendenti dall’ambiente).
  • Se serve precisione:
    DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)
    

6.5 Se vuoi usare NOW(): un’alternativa (trigger)

CREATE TRIGGER set_created_at
BEFORE INSERT ON logs
FOR EACH ROW
SET NEW.created_at = NOW();

Casi d’uso

  • Logica complessa di valore iniziale
  • Assegnazione condizionale di timestamp

Note

  • I trigger sono difficili da debug.
  • Evitali a meno che non siano necessari.

Errori comuni di progettazione

  • Aggiungere ON UPDATE sia a created_at che a updated_at
  • Confondere il comportamento di DATETIME e TIMESTAMP
  • Rimandare le decisioni sui fusi orari

Punti chiave di questa sezione

  • Usa CURRENT_TIMESTAMP per DEFAULT.
  • Usa ON UPDATE CURRENT_TIMESTAMP per il tracciamento degli aggiornamenti.
  • Scegli i tipi in base al comportamento dei fusi orari e al problema del 2038.
  • Se ti serve precisione, non dimenticare (6) .

7. Progettazione dei fusi orari (memorizzare in UTC, visualizzare in ora locale)

Quando si gestisce l’ora corrente, una cattiva progettazione del fuso orario causa deriva temporale e doppia conversione.
In pratica, l’impostazione predefinita più sicura è “memorizzare in UTC, convertire in ora locale per la visualizzazione.”

MySQL timezone architecture storing timestamps in UTC and converting to local time (JST)

Figura: Architettura di base per memorizzare UTC in MySQL e visualizzare l’ora locale

7.1 Verifica il fuso orario corrente

Prima, verifica quale fuso orario sta usando MySQL.

SELECT @@global.time_zone, @@session.time_zone;
  • @@global.time_zone → impostazione a livello di server
  • @@session.time_zone → impostazione della connessione/sessione corrente
  • Se mostra SYSTEM , dipende dall’impostazione del sistema operativo

Problemi comuni

  • I server di produzione e sviluppo hanno fusi orari OS diversi
  • L’app converte in UTC e il DB converte di nuovo (doppia conversione)

7.2 Cambia il fuso orario per sessione

SET time_zone = 'Asia/Tokyo';

o uniformare a UTC:

SET time_zone = '+00:00';

Punti importanti

  • Torna allo stato precedente quando la connessione è chiusa
  • Se usi il pooling delle connessioni, controlla le impostazioni dell’applicazione

7.3 Perché memorizzare in UTC (principio pratico)

Politica consigliata

  1. Memorizzare i dati in UTC
  2. Convertire nel fuso orario dell’utente al momento della visualizzazione

Motivi:

  • Supporto internazionale più semplice
  • Evitare problemi di ora legale (DST)
  • Minimizzare l’impatto quando si spostano i server

Ottieni UTC:

SELECT UTC_TIMESTAMP();

7.4 Converti i fusi orari con CONVERT_TZ()

Esempio: UTC → JST

SELECT CONVERT_TZ('2025-02-23 05:35:00', '+00:00', '+09:00');

Usando i nomi dei fusi orari:

SELECT CONVERT_TZ('2025-02-23 05:35:00', 'UTC', 'Asia/Tokyo');

Esempio pratico

SELECT CONVERT_TZ(created_at, 'UTC', 'Asia/Tokyo')
FROM users;

7.5 Perché CONVERT_TZ() restituisce NULL

Se restituisce NULL, le cause comuni includono:

  • Le tabelle dei fusi orari di MySQL non sono caricate
  • Il nome del fuso orario specificato non esiste

Esempio di caricamento su Linux:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

Note

  • In produzione, conferma i permessi e se è necessario un riavvio
  • In Docker, zoneinfo potrebbe non essere incluso a seconda dell’immagine

7.6 Cambia il fuso orario a livello di server

File di configurazione (my.cnf / my.ini):

[mysqld]
default_time_zone = '+00:00'

Verifica dopo il riavvio:

SELECT @@global.time_zone;

Importante

  • Per modifiche in produzione, conferma l’ambito di impatto
  • Fai attenzione ai dati esistenti (a volte cambiano solo le visualizzazioni)

Errori comuni

  • Memorizzare l’ora locale invece di UTC, poi aggiungere il supporto internazionale in seguito
  • Doppia conversione tra l’app e il DB
  • Progettare con DATETIME senza considerare i fusi orari
  • Impostazioni TZ diverse tra test e produzione

Punti chiave di questa sezione

  • Memorizzare in UTC e convertire al momento della visualizzazione.
  • Usa UTC_TIMESTAMP() .
  • Quando usi CONVERT_TZ(), verifica le tabelle TZ.
  • Considera sempre le differenze ambientali nei fusi orari.

8. Esempi pratici pronti all’uso

Ecco esempi SQL concreti che mostrano come usare l’ora corrente di MySQL nello sviluppo/operazioni reali.
Sono scritti in modo da poter copiare e incollare direttamente.

8.1 Inserire automaticamente l’ora corrente nei log

Crea tabella

CREATE TABLE system_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    level VARCHAR(50),
    message TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Inserisci log

INSERT INTO system_logs (level, message)
VALUES ('ERROR', 'Failed to connect to the DB');

Punti chiave

  • created_at viene inserito automaticamente
  • Non è necessario passare un timestamp dall’app
  • Progettazione essenziale per audit e indagine di incidenti

Errori comuni

  • Gestire il tempo sia nell’app che nel DB
  • Incoerenze temporali dovute a fusi orari non unificati

8.2 Aggiorna l’ora dell’ultimo accesso

Progettazione della tabella

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255),
    last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP
               ON UPDATE CURRENT_TIMESTAMP
);

Aggiornamento al login

UPDATE users
SET last_login = NOW()
WHERE id = 1;

Note

  • ON UPDATE si attiva solo quando la colonna cambia
  • Alcune istruzioni UPDATE potrebbero non modificare il valore e quindi non aggiornare

8.3 Fissa un tempo di riferimento nei job batch

Per processi a lunga esecuzione, è più sicuro fissare un tempo di riferimento.

SET @base_time = NOW();

SELECT *
FROM orders
WHERE created_at &gt;= @base_time - INTERVAL 1 DAY;

Perché

  • Il tempo non cambia a metà processo
  • La coerenza è mantenuta

8.4 Aggregazione per oggi / ieri / ultimi 7 giorni

Vendite di oggi

SELECT SUM(amount)
FROM orders
WHERE created_at &gt;= CURDATE()
  AND created_at &lt;  CURDATE() + INTERVAL 1 DAY;

Vendite di ieri

SELECT SUM(amount)
FROM orders
WHERE created_at &gt;= CURDATE() - INTERVAL 1 DAY
  AND created_at &lt;  CURDATE();

Ultimi 7 giorni

SELECT COUNT(*)
FROM users
WHERE created_at &gt;= NOW() - INTERVAL 7 DAY;

Importante

  • Non applicare funzioni alle colonne nelle clausole WHERE
  • Scrivi condizioni che mantengano gli indici utilizzabili

8.5 Controlli di scadenza (sessioni/token)

SELECT *
FROM sessions
WHERE expires_at &gt; NOW();

Elimina righe scadute

DELETE FROM sessions
WHERE expires_at &lt;= NOW();

Errori comuni

  • Usare CURDATE() ignorando l’ora
  • Memorizzare in UTC ma confrontare con NOW() locale

8.6 Ottieni righe che scadono entro N ore

SELECT *
FROM coupons
WHERE expires_at &lt;= NOW() + INTERVAL 1 HOUR;

Casi d’uso:

  • Avvisi di scadenza
  • Notifiche di scadenza

Ciò che devi sempre tenere a mente

  • Sii esplicito se la tua base temporale è “now” o “oggi 00:00”
  • Scrivi predicati che mantengano gli indici efficaci
  • Decidi il design del fuso orario in anticipo
  • Non mescolare NOW() e UTC_TIMESTAMP() senza una politica chiara

Punti chiave di questa sezione

  • Per log/audit/tracciamento degli aggiornamenti, usa CURRENT_TIMESTAMP
  • Per aggregazione, usa il pattern sicuro >= AND <
  • Per la gestione delle sessioni, confronta con NOW()
  • Fissa un tempo di base per mantenere il processo coerente

9. Domande Frequenti (FAQ)

Ecco le domande comuni sul tempo corrente di MySQL, soprattutto le insidie che emergono nel lavoro reale.

9.1 Qual è la differenza tra NOW() e CURRENT_TIMESTAMP?

Conclusione: il significato del valore restituito è lo stesso.

SELECT NOW(), CURRENT_TIMESTAMP;

Entrambi restituiscono la data e ora corrente.

La principale differenza è l’uso sintattico

  • CURRENT_TIMESTAMP può essere usato in DEFAULT e ON UPDATE
  • NOW() non può essere usato direttamente in DEFAULT

Note

  • Non è una differenza di tipo
  • Puoi specificare la precisione con argomenti come (6)

9.2 Dovresti usare SYSDATE()?

SYSDATE() restituisce il tempo al “momento di valutazione”.

SELECT SYSDATE(), SLEEP(2), SYSDATE();

Il valore può cambiare anche all’interno della stessa query.

Quando usarlo

  • Quando hai bisogno di registrare l’esatto istante reale

Quando evitarlo

  • Replicazione
  • Elaborazione di transazioni dove la coerenza è importante

Nella maggior parte dei casi, usare NOW() è sufficiente.

9.3 Perché il tempo è spostato?

Cause principali:

  1. Impostazioni del fuso orario del server
  2. Impostazioni del fuso orario della sessione
  3. Conversione doppia con l’applicazione
  4. Comportamento di conversione automatica del tipo TIMESTAMP

Verifica con:

SELECT @@global.time_zone, @@session.time_zone;

Mitigazione

  • Memorizza in UTC per impostazione predefinita
  • Converti solo durante la visualizzazione
  • Unifica la policy tra app e DB

9.4 CONVERT_TZ() restituisce NULL

Cause:

  • Le tabelle dei fusi orari non sono caricate
  • Nome del fuso orario errato

Correzione:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

Sii particolarmente attento negli ambienti Docker.

9.5 Spostamenti di intervallo con BETWEEN

Cattivo:

WHERE created_at BETWEEN '2025-02-01' AND '2025-02-10';

Sicuro:

WHERE created_at &gt;= '2025-02-01 00:00:00'
  AND created_at &lt;  '2025-02-11 00:00:00';

Motivi:

  • Problema di tempo al confine finale
  • Perdita di microsecondi
  • Efficienza degli indici

9.6 Come scegli tra DATETIME e TIMESTAMP?

  • Supporto internazionale / gestione UTC → TIMESTAMP
  • Dopo il 2038 o datetime fissi → DATETIME

Decidi questo durante la progettazione.

9.7 I microsecondi non vengono memorizzati

Causa:

  • Nessuna precisione specificata nella definizione della colonna

Correzione:

created_at DATETIME(6)

Punti chiave da questa sezione

  • Inizia con NOW() e CURRENT_TIMESTAMP
  • Per le query di intervallo, usa >= AND <
  • L’archiviazione UTC è l’impostazione predefinita più sicura
  • Non dimenticare la selezione del tipo e la precisione

10. Riepilogo

Questo articolo ha organizzato modi pratici per recuperare, formattare, calcolare e gestire l’ora corrente in MySQL.
Infine, ecco i essenziali minimi che dovresti sapere per rimanere al sicuro.

10.1 Ottenere l’ora corrente (basi)

  • Recupero generale → NOW()
  • DEFAULT della tabella / tracciamento aggiornamenti → CURRENT_TIMESTAMP
  • Solo data → CURDATE()
  • Solo ora → CURTIME()
  • UTC → UTC_TIMESTAMP()
  • Alta precisione → NOW(6)

Regole empiriche

  • Se non sei sicuro, usare NOW() va bene nella maggior parte dei casi.
  • Per la progettazione dello schema, usa CURRENT_TIMESTAMP .

10.2 Query di intervallo: “>= AND <” è la regola d’oro

Pattern sicuro:

WHERE created_at &gt;= 'START'
  AND created_at &lt;  'END'

Perché:

  • Previene la perdita di righe al confine finale
  • Funziona con i microsecondi
  • Mantiene gli indici utilizzabili

Esempio cattivo

WHERE DATE(created_at) = CURDATE();

Non avvolgere la colonna in una funzione.

10.3 Basi dell’aritmetica datetime

  • Aggiungi/sottrai → INTERVAL
  • Differenze di giorni → DATEDIFF()
  • Differenze di tempo → TIMESTAMPDIFF()

Tieni sempre a mente se la tua baseline è “ora” o “oggi 00:00.”

10.4 Principi di progettazione dei fusi orari

  • Memorizza in UTC
  • Converti durante la visualizzazione
  • Unifica la policy tra app e DB

Verifica con:

SELECT @@global.time_zone, @@session.time_zone;

10.5 Migliori pratiche per la progettazione delle tabelle

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
           ON UPDATE CURRENT_TIMESTAMP
  • Attrezzatura standard per auditing/logging/tracciamento aggiornamenti
  • Se hai bisogno di precisione, specifica (6)

I 4 punti più importanti nel mondo reale

  1. Non fraintendere la differenza tra NOW() e CURRENT_TIMESTAMP
  2. Per le query di intervallo, usa >= AND <
  3. Memorizza in UTC per impostazione predefinita
  4. Decidi i tipi (DATETIME vs TIMESTAMP) durante la progettazione

La gestione dell’ora corrente in MySQL è fondamentale per logging, aggregazione vendite, gestione auth/sessione, job batch e altro.
Se segui i principi in questo articolo, puoi evitare molti problemi comuni come deriva temporale, bug ai confini e degradazione delle prestazioni.