專案需將 SQL Server 資料庫轉換為 Access (.mdb)。使用「匯入/匯出精靈」轉換後,部分查詢在 Access 中執行直接當機 (Access 停止回應),SQL Server 卻完全正常。
SELECT
Product.產品ID,
(SELECT SUM(數量) FROM NowLib WHERE NowLib.產品ID = Product.產品ID) AS 現存數量,
預警上限,
(SELECT 預警上限 - SUM(數量) FROM NowLib WHERE NowLib.產品ID = Product.產品ID) AS 缺貨數量,
...
FROM Product
GROUP BY Product.產品ID, 通用名, ..., 預警上限, 預警下限
ORDER BY 品名, 產地;
第二個子查詢引用了外層查詢的 預警上限 (主表欄位)。Access 對「子查詢中引用外層非關聯欄位」的處理機制有缺陷,導致查詢最佳化器陷入無限循環或記憶體耗盡而當機。
SELECT
產品ID, 預警上限, 預警下限, 通用名, 輸入碼, 品名, 產地, 規格, 單位, 包裝, 劑型,
零售價, 批發價, 近期進價, 批准文號,
(SELECT SUM(n3.數量) FROM NowLib n3 WHERE n3.產品ID = Pro.產品ID) AS 總數量,
預警上限 - 總數量 AS 缺貨數量
FROM Product Pro
GROUP BY 產品ID, 通用名, 輸入碼, 品名, 產地, 規格, 單位, 包裝, 劑型,
零售價, 批發價, 近期進價, 批准文號, 預警上限, 預警下限
ORDER BY 品名, 產地;
原則:子查詢僅引用關聯鍵值 (如產品ID),所有外層業務欄位移至外層 SELECT 列表運算。
| 項目 | SQL Server | Access | 處理建議 |
|---|---|---|---|
| 視圖轉換 | View | 自動轉為資料表 (非查詢) | 手動重建為 Access 查詢 |
| 空字串預設值 | '' | "" | 腳本批次替換 |
| 目前日期時間 | GETDATE() | NOW() / DATE() | 全域搜尋替換 |
| 用戶端機器名 | HOST_NAME() | 無對應函數 | 應用層傳入 |
| CASE WHEN | 支援 | 不支援 | 改用 IIF() 或 SWITCH() |
| TOP n | TOP n | TOP n (需 ORDER BY) | 補齊 ORDER BY |
| IDENTITY | IDENTITY(1,1) | AUTOINCREMENT | 重建資料表 |
| 日期字面值 | '2024-01-15' | #2024-01-15# | 腳本替換 |
| 字串聯集 | + | & | 腳本替換 |
| ISNULL | ISNULL(a,b) | NZ(a,b) | 腳本替換 |
GETDATE()、HOST_NAME()、CASE WHEN、ISNULL、+ (字串聯集)。'YYYY-MM-DD' → #YYYY-MM-DD#。IDENTITY → AUTOINCREMENT,注意種子值重設。SQL Server 遷移 Access 非單純資料搬移,查詢引擎差異 (特別是子查詢關聯、CASE WHEN、日期函數) 是當機與錯誤的主要來源。建議採「連結資料表 + 前端遷移」架構,或完整重寫查詢邏輯並充分測試。