🧾SQL Server 日期轉換錯誤 (241) + Loader 檔名解析失敗?一次搞懂半導體資料載入常見陷阱與解法
🔍 問題背景:Loader 為什麼突然壞掉?
在實務中,我們常會遇到這種情況:
- Loader 原本正常運作
-
某一天突然:
- ❌ 資料全部進不去
- ❌ log 出現錯誤
- ❌ 檔案被丟到 fail 資料夾
這篇文章用一個真實案例帶你理解:
👉 其實問題不是一個,而是兩個「時間相關」問題同時發生
🚨 問題一:SQL Server Error 241(日期轉換失敗)
📌 錯誤訊息長這樣
DataError: ('22007', 'SQL Server 無法將字串轉換成 datetime (241)')
🧠 問題原因(白話版)
你的程式做了這件事:
👉 把「不存在的時間」當成字串寫進資料庫
例如:
END_TIME = 'NaT'
但 SQL Server 看到會說:
👉「這不是日期,我不認識」
所以直接報錯。
🧩 為什麼會出現 NaT?
在 Python(特別是 pandas)裡:
| 值 | 意義 |
|---|---|
NaT
|
Not a Time(時間版的空值) |
當 Loader 解析不到時間,就會產生這個值。
❌ 常見錯誤寫法(示意)
# ❌ 錯誤:直接轉字串
sql = f"UPDATE table SET end_time = '{time_value}'"
當 time_value = NaT 時:
'end_time = 'NaT''
👉 SQL Server 爆炸 💥
✅ 正確作法
✔ 方法一:改成 NULL
if time_value is None:
db_value = None
else:
db_value = time_value
✔ 方法二:用參數化(強烈建議)
query = "UPDATE table SET end_time = :t"
execute(query, {"t": time_value})
👉 資料庫會自動處理 NULL
🚨 問題二:檔名被判定「格式錯誤」
📌 Log 會看到
The file name ... format is incorrect
然後檔案直接被丟到:
/fail/
🧠 真正原因(重點!)
Loader 做了這件事:
👉 把「檔名最後一段」當成時間解析
例如:
XXX_FT1_250371000300.csv
Loader 以為:
250371000300 = YYMMDDHHMMSS
但實際上:
25 / 03 / 71 ❌
👉 71 號不存在 → 解析失敗
⚠️ 但真相是
👉 那段根本不是時間!
在半導體資料中(尤其測試廠):
最後一段常常是:
- 測試批次 ID
- 機台執行序號
- Session code
👉 不是時間
🔥 關鍵錯誤設計(Loader 的盲點)
Loader 假設:
檔名最後 = 時間
但實際:
| 廠商 | 檔名最後 |
|---|---|
| A廠 | 時間 |
| B廠 | 時間 |
| C廠(你這次) | ❌ Tracking Code |
👉 Loader 設計不夠彈性 → 直接爆
🛠️ 正確設計方式(超重要)
🥇 時間來源優先順序
應該是:
1️⃣ CSV 內部時間(最準)
2️⃣ Header 資訊
3️⃣ 檔名(最後才用)
❌ 錯誤設計
檔名 → CSV → Header
✅ 正確設計
CSV → Header → 檔名
🧩 解法總整理
✔ 解法一:檔名時間改為「非必填」
parsed_time = try_parse(filename_part)
if parsed_time is None:
log("檔名沒有時間,改用內容")
✔ 解法二:改從 CSV 抓時間
if parsed_time is None:
parsed_time = csv_header_time
✔ 解法三:不要讓解析錯誤直接丟 fail
# ❌ 不要這樣
if time is None:
raise Exception()
# ✅ 改成
if time is None:
log("skip filename time parsing")
📊 這次案例總結
在 2026/02/13 的 log 中:
🧨 發生兩種錯誤
1️⃣ SQL datetime 錯誤(241)
- 原因:NaT 被寫進 DB
- 影響:資料更新失敗
2️⃣ 檔名解析錯誤
- 原因:誤把 tracking code 當時間
- 影響:檔案全部被丟 fail
🎯 一句話總結
👉 不要相信檔名的時間,請相信資料本身
💡 工程師實戰建議
如果你在做:
- 半導體資料分析
- Loader / ETL pipeline
- Python + SQL Server
請一定要做到:
留言
張貼留言