查詢分析器 (Query Analyzer) 即時除錯實戰
透過查詢分析器的即時回饋功能,快速定位語法錯誤、資料截斷、型別不符等常見問題,無需部署至應用程式即可驗證。
錯誤訊息結構分析
-- 範例錯誤
INSERT INTO MO_CONTRACT_INFO(CONTRACT_CODE,CD_ID,MO_SALES_ID,C_ID,MONEY_SUM,CREATE_TIME,OPERATOR_NAME,TEXT_ID,TEXT_TYPE,CONTRACT_CHARACTER)
VALUES('GD0407110719','192','2846',16991,252.0,'2007-11-30','高杏華','7045536/7045487/6640113/6640093','0','0');
-- 錯誤輸出:
-- 伺服器: 訊息 8152,層級 16,狀態 9,行 1
-- String or binary data would be truncated.
-- The statement has been terminated.
錯誤代碼 8152 深度解析
| 屬性 | 值 | 說明 |
| 錯誤號 | 8152 | 字串或二進位資料會被截斷 |
| 嚴重層級 | 16 | 使用者可修正的錯誤 (11-16 為使用者錯誤) |
| 狀態 | 9 | 內部狀態碼,輔助診斷具體位置 |
| 行號 | 1 | 批次中的行號 (動態 SQL 可能不準) |
快速定位截斷欄位的方法
方法 1:逐一比對欄位長度 (手動)
-- 取得目標表欄位定義
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MO_CONTRACT_INFO'
ORDER BY ORDINAL_POSITION;
-- 對照 VALUES 列表長度
-- CONTRACT_CODE: 'GD0407110719' (12 字元) → 檢查定義長度
-- TEXT_ID: '7045536/7045487/6640113/6640093' (39 字元) → 高度可疑
方法 2:動態 SQL 自動比對 (進階)
DECLARE @TableName SYSNAME = 'MO_CONTRACT_INFO';
DECLARE @Values NVARCHAR(MAX) = N'''GD0407110719'',''192'',''2846'',16991,252.0,''2007-11-30'',''高杏華'',''7045536/7045487/6640113/6640093'',''0'',''0''';
-- 產生比對腳本
DECLARE @SQL NVARCHAR(MAX) = N'
DECLARE @Vals TABLE (Val NVARCHAR(MAX), Ord INT IDENTITY);
INSERT INTO @Vals (Val) SELECT value FROM STRING_SPLIT(@Values, '','');
SELECT
c.COLUMN_NAME,
c.DATA_TYPE,
c.CHARACTER_MAXIMUM_LENGTH AS MaxLen,
v.Val,
LEN(v.Val) AS ValLen,
CASE WHEN LEN(v.Val) > ISNULL(c.CHARACTER_MAXIMUM_LENGTH, 0) THEN ''TRUNCATE!'' ELSE ''OK'' END AS Status
FROM INFORMATION_SCHEMA.COLUMNS c
JOIN @Vals v ON c.ORDINAL_POSITION = v.Ord
WHERE c.TABLE_NAME = @TableName;';
EXEC sp_executesql @SQL, N'@Values NVARCHAR(MAX)', @Values = @Values;
方法 3:嘗試轉換插入暫存表 (最直觀)
-- 建立相同結構暫存表 (自動推導型別)
SELECT TOP 0 * INTO #TempCheck FROM MO_CONTRACT_INFO;
-- 嘗試插入
INSERT INTO #TempCheck
VALUES('GD0407110719','192','2846',16991,252.0,'2007-11-30','高杏華','7045536/7045487/6640113/6640093','0','0');
-- 若成功 → 原表有觸發器/限制/計算欄位導致
-- 若失敗 → 相同錯誤,但可排除權限/觸發器因素
查詢分析器除錯功能總覽
| 功能 | 快捷鍵/選單 | 用途 |
| 解析 (僅語法檢查) | Ctrl+F5 / 查詢 → 僅解析 | 快速檢測語法錯誤,不執行 |
| 顯示預估執行計畫 | Ctrl+L / 查詢 → 顯示預估執行計畫 | 檢視索引建議、型別轉換、統計資訊 |
| 顯示實際執行計畫 | Ctrl+M / 查詢 → 顯示實際執行計畫 | 執行後查看實際運算子、行數、成本 |
| 統計資訊 IO | SET STATISTICS IO ON | 邏輯/實體讀取、預讀頁面 |
| 統計資訊 TIME | SET STATISTICS TIME ON | CPU 時間、經過時間 |
| 客戶端統計資料 | 查詢 → 包含客戶端統計資料 | 網路封包、往返次數、處理時間 |
| 中斷點偵錯 (預存程序) | F9 切換 / 偵錯 → 切換中斷點 | 逐步執行、監看變數、呼叫堆疊 |
常見錯誤代碼速查表
| 錯誤碼 | 描述 | 常見原因 | 快速排查 |
| 8152 | 字串/二進位資料截斷 | 欄位長度不足、隱含轉換 | 比對欄位定義與輸入值長度 |
| 207 | 無效的欄位名稱 | 拼寫錯誤、Schema 變更、別名誤用 | 檢查 sys.columns、使用 CTE 重用別名 |
| 208 | 無效的物件名稱 | 表/視圖不存在、Schema 前綴缺失 | 確認 USE 資料庫、dbo. 前綴 |
| 245 | 轉換失敗 (varchar→int 等) | 非數值字串轉數值、日期格式錯誤 | TRY_CAST/TRY_CONVERT、CONVERT 風格 |
| 2627 | 唯一/主鍵違規 | 重複鍵值、Identity 衝突 | 檢查索引、DBCC CHECKIDENT |
| 547 | 外鍵/檢查條件違規 | 參考資料不存在、條件不符 | 檢查父表資料、條件定義 |
| 1205 | 死鎖犧牲者 | 並發更新同一資源、索引順序不一 | 統一存取順序、縮短交易、ROWLOCK |
最佳實踐:開發階段錯誤預防清單
- ✅ 使用
TRY_CAST/TRY_CONVERT (2012+) 安全轉換,失敗回傳 NULL 不報錯
- ✅ 參數化查詢 (sp_executesql) 避免動態 SQL 注入與格式問題
- ✅ 明確指定 INSERT 欄位清單:
INSERT INTO Table (Col1, Col2) VALUES (...)
- ✅ 字串欄位長度驗證:應用層 + 資料庫層 (CHECK CONSTRAINT) 雙重防護
- ✅ 使用
MERGE 替代複雜 UPSERT 邏輯 (2008+)
- ✅ 定期
DBCC CHECKDB、UPDATE STATISTICS 維護資料庫健康
- 上一篇文章: SQL Server Timestamp (Rowversion) 資料類型深度解析:版本控管、並發檢查與 BigInt 轉換實戰
- 下一篇文章: SQL Server sa 登入失敗完整排查與解決方案
Copyright ©
程式碼之家 All Rights Reserved