📊 為什麼同一段 SQL 在程式與資料庫跑出不同結果?工程師解析 Spotfire + SQL Server 常見陷阱
一、問題背景:為什麼同一段 SQL 結果會不同?
在資料分析或 BI 系統(例如 TIBCO Spotfire)中,常見一種情況:
同一段 SQL 查詢
-
在程式裡執行 → 結果正常
-
在 SQL Server Management Studio (SSMS) 執行 → 結果不同
很多工程師第一時間會懷疑:
-
資料不同
-
SQL 寫錯
-
系統快取
但實際上,最常見原因其實是 SQL Server 的 Session 設定不同。
其中一個非常容易忽略的設定就是:
QUOTED_IDENTIFIER
二、QUOTED_IDENTIFIER 是什麼?
SQL Server 有一個設定:
QUOTED_IDENTIFIER
它會影響 雙引號 " 的解讀方式
| 設定 | 行為 |
|---|---|
| ON | 雙引號代表欄位名稱 |
| OFF | 雙引號代表字串 |
範例說明
假設資料表:
WAFER_RESULT
有欄位:
device
lot_id
die_total
wafer_no
bin_count
工程師寫了一段 SQL:
SELECT
device,
lot_id,
CASE
WHEN "1" IS NOT NULL
THEN (1.0 * "1" / die_total)
END AS "1"
FROM WAFER_RESULT
如果:
情況 A:QUOTED_IDENTIFIER = ON
"1"
代表欄位名稱
等於:
[1]
結果正常。
情況 B:QUOTED_IDENTIFIER = OFF
"1"
會被當成:
'1'
也就是字串。
SQL 會變成:
1.0 * '1'
系統會做隱含轉換,結果就可能完全不同。
三、BI 系統與 SSMS 為什麼會不同?
不同工具通常有不同預設設定:
| 工具 | QUOTED_IDENTIFIER |
|---|---|
| Spotfire | ON |
| SQL Server Agent | ON |
| ODBC Driver | ON |
| SSMS 查詢視窗 | 有時 OFF |
因此:
同一段 SQL
在 Spotfire 正常
在 SSMS 可能出現錯誤結果。
四、Pivot 查詢常見問題
在製造業或半導體分析系統中,常見需要把資料 橫向展開 (Pivot)。
例如 wafer 測試資料:
| device | lot | wafer | bin |
|---|---|---|---|
| DEV_A | LOT01 | 1 | 150 |
| DEV_A | LOT01 | 2 | 152 |
| DEV_A | LOT01 | 3 | 149 |
工程師會使用 Pivot:
SELECT *
FROM (
SELECT device, lot, wafer, bin
FROM WAFER_RESULT
) src
PIVOT (
AVG(bin)
FOR wafer IN ([1],[2],[3],[4],[5])
) p
這樣結果會變成:
| device | lot | 1 | 2 | 3 | 4 | 5 |
|---|
五、最佳做法:避免使用雙引號
工程師建議:
永遠使用 [] 當欄位名稱
例如:
錯誤寫法:
"1"
正確寫法:
[1]
原因:
-
不受 QUOTED_IDENTIFIER 影響
-
所有 SQL Server 工具一致
-
BI 工具也相容
六、修正後的安全 SQL 範例
以下是一個較安全的 Pivot 查詢寫法:
SELECT
product,
batch_id,
total_die,
CASE WHEN [1] IS NOT NULL THEN (1.0 * [1] / total_die) END AS wafer_1,
CASE WHEN [2] IS NOT NULL THEN (1.0 * [2] / total_die) END AS wafer_2,
CASE WHEN [3] IS NOT NULL THEN (1.0 * [3] / total_die) END AS wafer_3
FROM
(
SELECT
product,
batch_id,
wafer_no,
total_die,
pass_die
FROM TEST_RESULT
WHERE test_time >= '2026-01-01'
AND test_time < '2026-01-08'
) source
PIVOT
(
AVG(pass_die)
FOR wafer_no IN ([1],[2],[3])
) pivot_table;
這種寫法:
✔ 所有工具一致
✔ 不受 SQL Session 設定影響
✔ BI 系統也能正常運作
七、如何檢查 SQL Server 設定?
可以用以下 SQL 查看:
SELECT SESSIONPROPERTY('QUOTED_IDENTIFIER');
回傳值:
| 結果 | 說明 |
|---|---|
| 1 | ON |
| 0 | OFF |
八、實務建議(資深工程師經驗)
在大型資料分析系統(例如:
-
Spotfire
-
Power BI
-
Tableau
-
Python ETL
-
Java Loader
)中,建議遵守以下原則:
1️⃣ 永遠使用 [欄位名]
避免 "欄位名"
2️⃣ 不依賴 Session 設定
不同工具會改變:
-
ANSI_NULLS
-
QUOTED_IDENTIFIER
-
ARITHABORT
3️⃣ SQL 在 SSMS 測試時加上設定
SET QUOTED_IDENTIFIER ON;
SET ANSI_NULLS ON;
九、工程師總結
當 SQL 查詢在不同環境結果不一致時:
最常見原因不是資料錯誤,而是:
-
Session 設定不同
-
BI 工具 SQL Parser 不同
-
欄位引用方式錯誤
其中最容易踩雷的就是:
雙引號引用欄位
工程上最穩定的方法就是:
永遠使用 []
這樣可以確保:
-
Spotfire
-
SQL Server
-
ETL
-
Reporting System
全部結果一致。
十、延伸閱讀
推薦工程師可以研究:
-
SQL Server Pivot
-
BI Tool SQL Execution
-
Database Session Settings
-
ETL Data Pipeline
這些都是資料工程與資料分析系統的重要基礎。
留言
張貼留言