MySQL里用LEFT截取字符串前几位
LEFT()函数的常见用法、边界情况,以及和其他截取函数的简单对比,顺便聊聊线上可能踩的坑。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道
2026-05-24 08:04:45 MySQL datetime 时间处理 Java
最近帮同事查一个订单创建时间丢时分秒的 bug,代码里明明设了 14:30:45,落库后变成 2024-05-20 00:00:00。
最后发现 ORM 映射里把字段写成了 java.sql.Date——这个坑我自己也踩过不止一次,刚好趁这次把 datetime 相关的常用操作和容易出问题的地方整理一下。
先看建表。需要记录完整时间点的时候,字段类型就设成 DATETIME,格式是 YYYY-MM-DD HH:MM:SS,范围从 1000-01-01 00:00:00 到 9999-12-31 23:59:59。
跟 date(只有日期)和 time(只有时间)的区别就在这里。
CREATE TABLE t_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(50) NOT NULL,
create_time DATETIME NOT NULL COMMENT '创建时间(含时分秒)'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
往这个字段里插数据,最省事的办法就是 NOW(),自动拿当前日期时间,带全时分秒:
INSERT INTO t_order (order_no, create_time)
VALUES ('ORD2024052001', NOW());
如果要插一个指定的时间,直接写标准格式的字符串就行,MySQL 会自动把它转成 datetime,不需要在外面多套一层 DATE_FORMAT:
INSERT INTO t_order (order_no, create_time)
VALUES ('ORD2024052003', '2024-05-20 14:30:45');
除非你的时间字符串格式比较怪,比如先拿到的是一串数字或非标准分隔符,那可以用 DATE_FORMAT 转一下:
INSERT INTO t_order (order_no, create_time)
VALUES ('ORD2024052002', DATE_FORMAT('2024-05-20 14:30:45', '%Y-%m-%d %H:%i:%s'));
不过多数情况下第一种就够了。另外,如果希望插入时自动填当前时间,定义字段的时候加上 DEFAULT CURRENT_TIMESTAMP,之后 INSERT 语句可以省掉这个字段:
CREATE TABLE t_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(50) NOT NULL,
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO t_order (order_no) VALUES ('ORD2024052004');
查询出来就是完整的 2024-05-20 14:30:45 格式,没啥特别的。想定制显示的话,用 DATE_FORMAT:
SELECT
order_no,
DATE_FORMAT(create_time, '%Y年%m月%d日 %H时%i分%s秒') AS formatted_time
FROM t_order;
单拿小时、分钟、秒可以用 HOUR()、MINUTE()、SECOND():
SELECT
order_no,
HOUR(create_time) AS hour,
MINUTE(create_time) AS minute,
SECOND(create_time) AS second
FROM t_order;
不过这些都是 SQL 层面的事。
真正容易出问题的,其实是应用代码跟数据库之间的类型映射。开头说的那种问题,在 Java 里的标准修法是这样——如果你用的是 Java 8 以上,直接用 java.time.LocalDateTime,通过 JDBC 驱动的 setObject 传进去就行:
LocalDateTime createTime = LocalDateTime.of(2024, 5, 20, 14, 30, 45);
ps.setObject(2, createTime);
还在用旧版本 Java 的话,就改用 java.sql.Timestamp:
Timestamp timestamp = Timestamp.valueOf("2024-05-20 14:30:45");
ps.setTimestamp(2, timestamp);
千万别用 java.sql.Date,那个只有日期部分,时分秒会全丢。
另一个高频问题是时区。Java 里明明时间是对的,进到库就少了 8 小时,或者多了。
这种情况大概率是 JVM 跟 MySQL 的时区没对齐。可以在 MySQL 那边设东八区:
SET GLOBAL time_zone = '+8:00';
SET SESSION time_zone = '+8:00';
或者在 JDBC 连接串里显式指定,这个更常用:
jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=Asia/Shanghai
实际项目里,我习惯把这几个点统一处理:数据库字段就用 DATETIME,Java 侧固定用 LocalDateTime,连接串带上 serverTimezone=Asia/Shanghai,SQL 一律参数绑定不拼字符串。这样类型映射和时区一般不会再折腾你。需要范围查询的 datetime 字段,比如按时间段拉订单,该加索引就加一个:
CREATE INDEX idx_create_time ON t_order(create_time);
基本就这些。时间类型出的问题排查起来往往很绕,但最后发现都落在类型映射和时区配置上,提前统一掉能省很多半夜报警。
上一篇: Ubuntu 下动态链接库路径的折腾记录
LEFT()函数的常见用法、边界情况,以及和其他截取函数的简单对比,顺便聊聊线上可能踩的坑。
MySQL SSL配置失败让人抓狂?别担心,这篇文章手把手教你排查常见问题,让你轻松搞定数据库加密连接,更有自动化工具推荐哦!
在处理海量MySQL数据时,如何高效利用REPLACE函数进行字符串替换,避免性能瓶颈?本文不仅详述REPLACE的强大功能,更聚焦于其在大型数据库操作中的性能表现与优化技巧。我们将深入探讨分批执行、索引影响、事务管理等高级策略,旨在帮助DBA和开发者在实现数据清洗、格式统一的同时,最大限度保障系统性能,确保数据操作的顺畅与高效。
想象一下从精确到极致的BigDecimal世界踏入“四舍五入”的Double领域。本文揭示Java数值转换的奥秘,解析精度损失的陷阱与范围限制的边界,助你明智选择,避免程序中的“财务黑洞”。
拥抱Java 8及更高版本带来的日期处理革新!本文聚焦于yyyy-MM-dd格式化,详细对比传统SimpleDateFormat与现代DateTimeFormatter。深入探讨DateTimeFormatter为何成为未来主流,其不可变性、线程安全等核心优势如何助你构建更健壮、高效的应用。是时候升级你的日期格式化方式了!