📊 為什麼同一段 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

這些都是資料工程與資料分析系統的重要基礎。

留言

這個網誌中的熱門文章

🔍Vue.js 專案錯誤排查:解決 numericFields is not defined 與合併儲存格邏輯最佳化

🖥️遠端桌面連線完整新手指南:Windows RDP、Chrome Remote Desktop、AnyDesk、TeamViewer 一次搞懂

🔎EF Core 連 Oracle 出現 ORA-00600 [kpp_concatq:2] 的完整排錯指南(含 EF Core ToString/CultureInfo 錯誤)