Hướng Dẫn Thời Gian Hiện Tại trong MySQL: NOW(), CURRENT_TIMESTAMP, DATE_FORMAT, Cài Đặt Múi Giờ & Các Thực Tiễn Tốt Nhất

目次

1. Giới thiệu

Khi nào bạn cần xử lý thời gian hiện tại trong MySQL?

Trong MySQL, việc lấy thời gian hiện tại là cần thiết trong nhiều tình huống khác nhau. Ví dụ, các trường hợp sử dụng sau đây là phổ biến:

  • Tự động chèn dấu thời gian khi ghi dữ liệu
  • Ví dụ, ghi lại ngày và giờ tạo khi lưu dữ liệu đơn hàng hoặc dữ liệu log.
  • Lọc dữ liệu dựa trên thời gian hiện tại
  • Ví dụ, chỉ lấy dữ liệu trong 7 ngày qua hoặc tìm các bản ghi có ngày trong tương lai.
  • Định dạng ngày và giờ để hiển thị
  • Định dạng giá trị ngày và giờ để dễ đọc hơn khi tạo báo cáo.
  • Quản lý thời gian hết hạn của dữ liệu bằng thời gian hiện tại
  • Ví dụ, xác định một coupon còn hiệu lực hay không bằng cách so sánh với thời gian hiện tại.

Như bạn thấy, việc lấy và thao tác thời gian hiện tại trong MySQL là một kỹ năng quan trọng trong quản trị cơ sở dữ liệu.

Những gì bạn sẽ học trong bài viết này

Bài viết này giải thích chi tiết các chủ đề sau:

  • Cách lấy thời gian hiện tại trong MySQL (NOW(), CURRENT_TIMESTAMP, …)
  • Cách thay đổi định dạng ngày và giờ (sử dụng DATE_FORMAT())
  • Các phép tính ngày và giờ dựa trên thời gian hiện tại (sử dụng INTERVAL)
  • Cách thay đổi múi giờ (SET SESSION time_zone)
  • Sử dụng thời gian hiện tại làm giá trị mặc định (CURRENT_TIMESTAMP)
  • Các lỗi thường gặp và cách khắc phục chúng (FAQ)

Từ cơ bản đến nâng cao về việc xử lý “thời gian hiện tại” trong MySQL, hướng dẫn này cung cấp các ví dụ SQL thực tế. Hãy đọc đến cuối để nắm bắt hết nội dung.

2. Cách lấy thời gian hiện tại trong MySQL

Danh sách các hàm để lấy thời gian hiện tại trong MySQL

MySQL cung cấp một số hàm để lấy thời gian hiện tại. Hiểu sự khác nhau và sử dụng chúng một cách phù hợp.

FunctionReturnsExample
NOW()Current date and time (date + time)SELECT NOW();2025-02-11 16:00:00
CURRENT_TIMESTAMPSame as NOW() (SQL standard)SELECT CURRENT_TIMESTAMP;
CURDATE()Current date onlySELECT CURDATE();2025-02-11
CURTIME()Current time onlySELECT CURTIME();16:00:00

Hàm NOW()

NOW() là hàm được sử dụng phổ biến nhất trong MySQL để lấy thời gian hiện tại.
Nó trả về cả ngày và giờ.

SELECT NOW();

Ví dụ đầu ra:

2025-02-11 16:00:00
  • NOW() trả về thời gian hệ thống hiện tại.
  • Vì nó chịu ảnh hưởng của múi giờ, thời gian hiển thị có thể khác nhau tùy vào môi trường của bạn (được giải thích chi tiết trong phần “Cài đặt múi giờ”).

Cách sử dụng CURRENT_TIMESTAMP

CURRENT_TIMESTAMP hoạt động gần như tương tự NOW(). Nó tuân thủ chuẩn SQL và cũng có thể được dùng trong các hệ quản trị cơ sở dữ liệu khác.

SELECT CURRENT_TIMESTAMP;

Ví dụ đầu ra:

2025-02-11 16:00:00

Lấy chỉ ngày với CURDATE()

CURDATE() được dùng khi bạn muốn lấy chỉ ngày hiện tại (năm, tháng, ngày).

SELECT CURDATE();

Ví dụ đầu ra:

2025-02-11

Lấy chỉ giờ với CURTIME()

Nếu bạn muốn lấy chỉ thời gian hiện tại (giờ, phút, giây), hãy dùng CURTIME().

SELECT CURTIME();

Ví dụ đầu ra:

16:00:00

Bạn nên dùng hàm nào?

PurposeRecommended Function
Retrieve both date and timeNOW() or CURRENT_TIMESTAMP
Retrieve date onlyCURDATE()
Retrieve time onlyCURTIME()

3. Cách định dạng thời gian hiện tại trong MySQL

Định dạng tùy chỉnh với DATE_FORMAT()

Cú pháp cơ bản của DATE_FORMAT()

Trong MySQL, bạn có thể sử dụng hàm DATE_FORMAT() để tự do thay đổi định dạng của ngày và giờ.

SELECT DATE_FORMAT(datetime_value, 'format_specifiers');

Ví dụ: Chuyển NOW() sang định dạng YYYY/MM/DD HH:MM

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

Kết quả:

2025/02/11 16:45

Danh sách các ký hiệu định dạng phổ biến

SpecifierMeaningExample (2025-02-11 16:45:30)
%Y4-digit year2025
%m2-digit month (01-12)02
%d2-digit day (01-31)11
%HHour (00-23, 24-hour format)16
%iMinutes (00-59)45
%sSeconds (00-59)30

Trích xuất chỉ phần thời gian với TIME()

Nếu bạn muốn trích xuất chỉ phần thời gian từ giá trị datetime trả về bởi NOW(), hãy dùng hàm TIME().

SELECT TIME(NOW());

Kết quả:

16:45:30

Trích xuất các phần với YEAR(), MONTH(), và DAY()

Để lấy ra các phần cụ thể, hãy sử dụng các hàm sau.

FunctionReturnsSQLOutput Example (2025-02-11 16:45:30)
YEAR()YearSELECT YEAR(NOW());2025
MONTH()MonthSELECT MONTH(NOW());2
DAY()DaySELECT DAY(NOW());11

Các ví dụ thực tế về định dạng

The following SQL is useful for trying various formats in practice.

SELECT 
    NOW() AS 'Original datetime',
    DATE_FORMAT(NOW(), '%Y/%m/%d') AS 'YYYY/MM/DD format',
    DATE_FORMAT(NOW(), '%H:%i:%s') AS 'HH:MM:SS',
    TIME(NOW()) AS 'Time only',
    YEAR(NOW()) AS 'Year',
    MONTH(NOW()) AS 'Month',
    DAY(NOW()) AS 'Day';

4. Date/Time Calculations Using the Current Time in MySQL

Add/Subtract with INTERVAL

Basic Syntax

SELECT current_datetime + INTERVAL number unit;
SELECT current_datetime - INTERVAL number unit;

Add Time Based on NOW()

For example, to retrieve the datetime “one week later”:

SELECT NOW() + INTERVAL 7 DAY;

Output example:

2025-02-18 16:30:00
UnitMeaningExample
SECONDSecondsNOW() + INTERVAL 10 SECOND
MINUTEMinutesNOW() + INTERVAL 5 MINUTE
HOURHoursNOW() + INTERVAL 2 HOUR
DAYDaysNOW() + INTERVAL 10 DAY
MONTHMonthsNOW() + INTERVAL 3 MONTH

Calculate the Difference Between Two Dates with DATEDIFF()

SELECT DATEDIFF(NOW(), '2025-01-01');

Output example:

30

Filter by a Date Range with BETWEEN

SELECT * FROM orders
WHERE created_at BETWEEN '2025-02-01 00:00:00' AND '2025-02-28 23:59:59';

5. MySQL Time Zone Settings

Check the Current Time Zone

SHOW VARIABLES LIKE '%time_zone%';

Output example:

+------------------+----------------+
| Variable_name    | Value          |
+------------------+----------------+
| system_time_zone | UTC            |
| time_zone        | SYSTEM         |
+------------------+----------------+

Change the Time Zone per Session

SET SESSION time_zone = 'Asia/Tokyo';

Change the Server’s Default Time Zone

Add the following to the configuration file (my.cnf):

[mysqld]
default_time_zone = 'Asia/Tokyo'

Get UTC Time with UTC_TIMESTAMP

SELECT UTC_TIMESTAMP();

Convert to Local Time with CONVERT_TZ()

SELECT CONVERT_TZ(UTC_TIMESTAMP(), 'UTC', 'Asia/Tokyo');

6. How to Set the Current Time as a Default Value in MySQL

Set CURRENT_TIMESTAMP as the Default Value

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Automatic Updates with ON UPDATE CURRENT_TIMESTAMP

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

Difference Between DATETIME and TIMESTAMP

TypeAffected by Time ZoneCan Set CURRENT_TIMESTAMP as Default
TIMESTAMPYesYes
DATETIMENoNo

Why You Cannot Use NOW() as a Default Value and the Solution

ERROR 1067 (42000): Invalid default value for 'created_at'

Solution:

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

7. Common MySQL Errors and Solutions (FAQ)

Cannot Use NOW() as a Default Value

Error Example

CREATE TABLE logs (
    created_at DATETIME DEFAULT NOW()
);
ERROR 1067 (42000): Invalid default value for 'created_at'

Solution

CREATE TABLE logs (
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CURRENT_TIMESTAMP Time Is Incorrect

SHOW VARIABLES LIKE 'time_zone';

Solution

SET SESSION time_zone = 'Asia/Tokyo';

NOW() Result Is Off by One Hour

SHOW VARIABLES LIKE 'system_time_zone';

Solution

SET GLOBAL time_zone = 'Asia/Tokyo';

BETWEEN Range Filtering Does Not Work as Expected

SELECT * FROM orders
WHERE created_at BETWEEN '2025-02-01' AND '2025-02-28';

Solution

SELECT * FROM orders
WHERE created_at BETWEEN '2025-02-01 00:00:00' AND '2025-02-28 23:59:59';

8. Best Practices for Handling the Current Time in MySQL

When to Use NOW() vs CURRENT_TIMESTAMP

Use CaseRecommended
Retrieve the current time in a SELECT statementNOW()
Automatically set the current time during INSERTCURRENT_TIMESTAMP
Set as the default value of a TIMESTAMP columnCURRENT_TIMESTAMP

When to Use TIMESTAMP vs DATETIME

Data TypeAffected by Time ZoneStorage Size
TIMESTAMPYes4 bytes
DATETIMENo8 bytes

Store in UTC and Convert to Local Time

SELECT CONVERT_TZ(event_time, 'UTC', 'Asia/Tokyo');

Sử dụng >=< Thay vì BETWEEN

SELECT * FROM orders
WHERE created_at >= '2025-02-01 00:00:00' 
AND created_at < '2025-03-01 00:00:00';

Chuẩn hóa Việc Sử dụng INTERVAL

SELECT NOW() + INTERVAL 1 DAY;

Làm sạch dữ liệu cũ một cách thích hợp

DELETE FROM logs WHERE created_at < NOW() - INTERVAL 1 YEAR LIMIT 1000;