異構數據庫環境下,應用遷移、數據同步、ETL 腳本編寫時,「插入當前時間」看似簡單,實則語法差異巨大。本文提供主流五大數據庫的標準函數、數據類型匹配、時區處理、批量插入性能差異對照表,並附帶 Java/JDBC 參數綁定最佳實踐。
| 數據庫 | 當前日期時間函數 | 返回類型 | 目標列推薦類型 | 備註 |
|---|---|---|---|---|
| Oracle | SYSDATE / SYSTIMESTAMP | DATE / TIMESTAMP WITH TIME ZONE | DATE / TIMESTAMP(6) | `SYSDATE` 精度至秒,`SYSTIMESTAMP` 精度至微秒含時區。`CURRENT_DATE` 返回會話時區時間。 |
| DB2 (LUW) | CURRENT TIMESTAMP / CURRENT TIMESTAMP(6) | TIMESTAMP | TIMESTAMP | 標準 SQL 函數。`CURRENT DATE` 僅日期。z/OS 版本語法一致。 |
| SQL Server | GETDATE() / SYSDATETIME() / SYSUTCDATETIME() | DATETIME / DATETIME2(7) / DATETIME2(7) UTC | DATETIME2(7) (推薦) | `GETDATE()` 精度 ~3.33ms (DATETIME);`SYSDATETIME()` 精度 100ns (DATETIME2);`GETUTCDATE()`/`SYSUTCDATETIME()` 返回 UTC。 |
| MySQL | NOW() / CURRENT_TIMESTAMP / SYSDATE() | DATETIME | DATETIME(6) / TIMESTAMP(6) | `NOW()` = 語句執行開始時間;`SYSDATE()` = 函數執行瞬間時間 (複製表時不同);`CURRENT_TIMESTAMP` 標準 SQL。`DATE()`/`CURDATE()` 僅日期。 |
| PostgreSQL | NOW() / CURRENT_TIMESTAMP / CLOCK_TIMESTAMP() | TIMESTAMP WITH TIME ZONE (timestamptz) | TIMESTAMPTZ / TIMESTAMP(6) | `NOW()` = 事務開始時間 (事務內固定);`CLOCK_TIMESTAMP()` = 實時時間;`LOCALTIMESTAMP` 無時區。支援 `TIMEZONE('UTC', NOW())` 時區轉換。 |
-- 表結構通用: CREATE TABLE test_time (id INT PRIMARY KEY, name VARCHAR(50), created_at <目標類型>);
-- Oracle
INSERT INTO test_time (id, name, created_at) VALUES (1, 'Oracle', SYSDATE);
-- 或帶微秒時區
INSERT INTO test_time (id, name, created_at) VALUES (1, 'Oracle', SYSTIMESTAMP);
-- DB2
INSERT INTO test_time (id, name, created_at) VALUES (1, 'DB2', CURRENT TIMESTAMP);
-- SQL Server
INSERT INTO test_time (id, name, created_at) VALUES (1, 'SQLServer', SYSDATETIME()); -- 高精度推薦
-- MySQL
INSERT INTO test_time (id, name, created_at) VALUES (1, 'MySQL', NOW());
-- 或指定微秒精度 (5.6.4+)
INSERT INTO test_time (id, name, created_at) VALUES (1, 'MySQL', CURRENT_TIMESTAMP(6));
-- PostgreSQL
INSERT INTO test_time (id, name, created_at) VALUES (1, 'PostgreSQL', NOW());
-- 存 UTC 時間
INSERT INTO test_time (id, name, created_at) VALUES (1, 'PostgreSQL', TIMEZONE('UTC', NOW()));
| 場景 | Oracle | SQL Server | MySQL | PostgreSQL |
|---|---|---|---|---|
| 獲取 UTC 時間 | `SYS_EXTRACT_UTC(SYSTIMESTAMP)` | `SYSUTCDATETIME()` / `GETUTCDATE()` | `UTC_TIMESTAMP()` / `CONVERT_TZ(NOW(), @@session.time_zone, '+00:00')` | `TIMEZONE('UTC', NOW())` / `NOW() AT TIME ZONE 'UTC'` |
| 會話/連接時區設置 | `ALTER SESSION SET TIME_ZONE = '+08:00'` | `SET DATEFORMAT` / 連接字符串 `TimeZone=UTC` | `SET time_zone = '+08:00'` / `my.cnf default-time-zone` | `SET TIME ZONE 'UTC'` / `postgresql.conf timezone` |
| 數據庫級默認時區 | 安裝時指定 / `DBTIMEZONE` | OS 時區 | `system_time_zone` / `default-time-zone` | `postgresql.conf timezone` |
**嚴禁**在 SQL 字符串中拼接時間函數 (如 `INSERT ... VALUES (?, SYSDATE)`),應由**應用層生成時間並綁定參數**,確保跨數據庫一致性、可測試性、避免 SQL 注入。
// Java 8+ java.time API (推薦)
LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); // 業務邏輯統一用 UTC
// 或 Instant now = Instant.now();
// PreparedStatement 綁定
String sql = "INSERT INTO test_time (id, name, created_at) VALUES (?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, 1);
ps.setString(2, "AppInsert");
// Oracle / PostgreSQL / MySQL / DB2 / SQL Server (JDBC 4.2+ 支援 java.time)
ps.setObject(3, now);
// 老版本驅動可能需轉換
// ps.setTimestamp(3, Timestamp.valueOf(now)); // 無時區
// ps.setTimestamp(3, Timestamp.from(Instant.now())); // UTC
ps.executeUpdate();
}
// 批量插入優化
ps.addBatch(); // 循環添加
ps.executeBatch();
| 數據庫 | 批量插入當前時間推薦方式 | 性能特徵 |
|---|---|---|
| Oracle | `FORALL` + `SYSDATE` / `SYSTIMESTAMP` / `DBMS_UTIL.GET_TIME` | PL/SQL 批量綁定最快;SQL*Loader 外部表 `SYSDATE` 常數列 |
| SQL Server | `BULK INSERT` / `BCP` / `INSERT ... SELECT` + `SYSDATETIME()` | 最小化日志模式下極快;表值參數 (TVP) 應用層批量傳遞 |
| MySQL | `LOAD DATA INFILE` + 當前時間列默認值 `DEFAULT CURRENT_TIMESTAMP` | 文件載入最快;避免觸發器/函數開銷 |
| PostgreSQL | `COPY` + `DEFAULT NOW()` / `INSERT ... SELECT` + `NOW()` | `COPY` 文本流極快;預備語句批量綁定 |
| DB2 | `LOAD` / `INGEST` / `IMPORT` + `CURRENT TIMESTAMP` | `LOAD` 繞過日志最快 |
掌握異構數據庫時間函數差異、時區統一策略、JDBC 參數化綁定、批量載入優化,是構建可移植、高性能、全球化數據應用的必備技能。建議團隊建立「時間處理規範文檔」,強制 UTC 存儲、參數化綁定、顯式格式化,納入代碼審查清單。