現象:SQL 查詢顯示正常,但導出 Excel 後 rownum 列變空或亂碼。根因:JDBC 返回 BIGINT,Java 端以 String 強轉導致 null。
-- SQL 使用變量生成行號
SELECT CONCAT((@rowNum := @rowNum + 1), '') AS rownum, t.* FROM (...) t;
導出代碼(錯誤版):
Map map = (Map) data.get(i);
HSSFCell cell0 = datarow.createCell(0);
// 錯誤:rownum 實際是 Long,強轉 String 導致 null
HSSFRichTextString t0 = new HSSFRichTextString((String) map.get("rownum") + "");
cell0.setCellValue(t0);
@rowNum 推導類型為 BIGINT。ResultSet.getObject() 返回 Long。(String) map.get("rownum") 嘗試將 Long 強轉為 String,拋出 ClassCastException 被吞噬,最終存入 null。
Map map = (Map) data.get(i);
HSSFCell cell0 = datarow.createCell(0);
// 正確:直接 toString(),支援任意類型(Long、Integer、BigDecimal、String)
Object val = map.get("rownum");
HSSFRichTextString t0 = new HSSFRichTextString(val == null ? "" : val.toString());
cell0.setCellValue(t0);
Object 接收,再 val != null ? val.toString() : \"\"。(String)、(Integer) 易在類型不匹配時拋異常。workbook.write() 並 sheet.flushRows() 防 OOM。CAST((@rowNum := @rowNum + 1) AS CHAR) AS rownum,讓 JDBC 直接返回 String,消除類型歧義。
SELECT * FROM (
SELECT @rownum := @rownum + 1 AS rownum, t.*
FROM (SELECT * FROM orders ORDER BY create_time DESC) t,
(SELECT @rownum := 0) r
) tmp
WHERE rownum BETWEEN 21 AND 30;
MySQL 8.0+ 建議直接用標準 ROW_NUMBER() OVER (ORDER BY create_time DESC) 窗口函數,更簡潔高效。