Access (Jet/ACE) 到 SQL Server (T-SQL) 遷移看似簡單,實則暗藏大量語法、型別、行為差異。本文彙整 22 項實戰踩坑點,附對照表與修正建議,助你一次遷移成功。
| # | 項目 | Access | SQL Server | 修正建議 |
|---|---|---|---|---|
| 1 | 自動編號 | AutoNumber | Identity(1,1) | 匯入後手動設定「識別規格」= 是,種子/遞增 = 1 |
| 2 | 預設值遺失 | Default Value | Default Constraint | 逐表補齊 ALTER TABLE ... ADD CONSTRAINT ... DEFAULT ... |
| 3 | 現在時間 | Now() / Date() / Time() | GETDATE() / SYSDATETIME() | 全域搜尋替換 |
| 4 | 日期差 (天) | DateDiff('d', d1, d2) | DATEDIFF(DAY, d1, d2) | 單位改大寫英文,移除引號 |
| 5 | 日期差 (週) | DateDiff('ww', d1, d2) | DATEDIFF(WEEK, d1, d2) | 同上 |
| 6 | 保留字衝突 | 無限制 | 眾多保留字 | 欄位/表名加 [括號] 或改名 |
| 7 | 時間參數化 | WHERE dt = #" & Now() & "# | WHERE dt = @dt 參數化 | 改用參數化查詢,防注入 |
| 8 | 日期函數 | DateAdd/DateDiff/Format | DATEADD/DATEDIFF/FORMAT | 語法大寫,參數順序可能不同 |
| 9 | 時間型別 | Date/Time (Double) | SMALLDATETIME / DATETIME / DATETIME2 | 建議統一 DATETIME2(3),範圍更大 |
| 10 | IsNull 判斷 | IsNull(field) | field IS NULL | T-SQL ISNULL() 是替換函數,非判斷 |
| 11 | 游標類型 | 預設即可 | ADO 需 CursorType=1 (adOpenKeyset) | 開啟 Recordset 時指定 |
| 12 | Memo/長文字 | Memo | VARCHAR(MAX) / NVARCHAR(MAX) | 讀取時 CAST(col AS VARCHAR(MAX)) |
| 13 | 布林值 | True/False (-1/0) | BIT (1/0) | 應用層統一轉換 |
| 14 | DELETE 語法 | DELETE * FROM t WHERE ... | DELETE FROM t WHERE ... | 移除星號 |
| 15 | VB 函數在 SQL | CStr(), Format() 等可直接用 | 不可用,需改 T-SQL 對應函數 | 重寫邏輯或移至應用層 |
| 16 | 時間字串格式 | #yyyy-mm-dd# | 'yyyy-mm-dd' (單引號) | 統一 ISO 8601 格式 |
| 17 | 樂觀鎖衝突 | 罕見 | 常見 80040e38 | 改用 UPDATE t SET col=val WHERE pk=@pk 明確更新 |
| 18 | 整數除法 | \ 或 / | 僅 / (回傳浮點),整數除法用 / 後 FLOOR | 注意型別轉換 |
| 19 | 主鍵缺失 | 不強制 | 更新需主鍵/唯一索引 | 遷移後務必補建 PK |
| 20 | Recordset 開啟模式 | 預設 | rs.Open sql, conn, 3, 2 (adOpenStatic, adLockOptimistic) | 明確指定游標/鎖定類型 |
TRY_CAST/TRY_CONVERT 防轉換失敗按表逐項核對修正,配合 SSMA 工具輔助,Access 遷移 SQL Server 可控、可測、可交付。