📌如何解決前後端資料重複、筆數異常與 Oracle ORA-00904 "FALSE" 錯誤:APS 排程資料查詢最佳化

技術教學  | 發佈日期:2025年8月4日

如何解決前後端資料重複、筆數異常與 Oracle ORA-00904 "FALSE" 錯誤:APS 排程資料查詢最佳化

摘要: 本文拆解企業級 APS 排程結果頁面常見的前後端資料異常(重複、筆數錯誤)與 Oracle boolean 轉譯錯誤(ORA-00904 "FALSE"),提供從後端 EF Core 查詢優化(JOIN+去重)、資料投影、前端 Vue 3 動態欄位對齊與篩選修正,以及 Oracle boolean 處理的完整解法,提升正確性與效能。

一、前言

在企業級資料排程系統中(例如 APS 排程),常見問題包括:後端撈出大量重複資料、前端顯示筆數異常、Oracle 報錯 boolean 相關錯誤。本文以實際案例拆解核心原因並提供端到端解法,讓不熟悉該領域的人也能理解與實作。

目標讀者包括後端開發、前端工程師、系統整合人員,以及希望寫 SEO 友善技術部落格的軟體工程師。

二、問題描述(實例場景)

  • 畫面上只有幾組像 SEQ_NO + APS_PLAN_NO 的資料,卻各自重複出現好幾筆。
  • 後端明明有多筆資料,但前端呈現比預期少(篩掉或漏掉)。
  • Oracle 報錯 ORA-00904: "FALSE": 無效的 ID,因為 bool 直接投影到 SQL。

原始後端做法:先把整張表用 ToListAsync() 抓出來、在記憶體配對再產生 DTO。前端做法:固定 mapping header、錯誤篩選 key(如不存在的 LCM_ID)導致資料被過濾。

三、核心原因拆解

1. 後端資料重複沒在查詢層去重

若資料庫裡同一組 key(例如 SEQ_NO + APS_PLAN_SEQ)存在多筆歷史/重複資料,而不在 SQL 端去重,就會在前端看到重複。

2. Oracle 不支援 SQL 裡的 FALSE / TRUE literal

若在 LINQ 直接投影 C# 的 bool,EF Core 可能生成 SQL 中出現 FALSE 文字,而 Oracle 會回 ORA-00904 錯誤。

3. 前端寫死 header 與錯誤篩選邏輯

固定把 tableHeaders 寫死成 mapping keys,但 API 回傳的欄位可能不一致,另外 filterableColumns 包含不存在欄位會把正常資料錯誤排除。

四、解法與實作

1. 後端:在資料庫端做去重、JOIN 與投影(性能最佳化)

重寫查詢,把原本兩次 ToListAsync() + 記憶體配對,改成單一 SQL 在 DB 做:

public async Task GetDataByVersionA(string apsVersion)
{
    var planQuery = _context.APSZPLANs
        .AsNoTracking()
        .Where(p => p.APS_VERSION == apsVersion)
        .GroupBy(p => new { p.SEQ_NO, p.APS_PLAN_SEQ })
        .Select(g => g.First());

    var lcmQuery = _context.APSZLCMs
        .AsNoTracking()
        .Where(l => l.APS_VERSION == apsVersion && l.PROCESS_NAME == "後段");

    var list = await (
        from p in planQuery
        join l in lcmQuery
          on new { p.CUSTOMER_NAME, p.DEMAND_QTY, p.PRODUCT_ID }
          equals new { l.CUSTOMER_NAME, l.DEMAND_QTY, l.PRODUCT_ID }
          into lg
        from lcm in lg.DefaultIfEmpty()
        select new APSZRESULTA
        {
            SEQ_NO         = p.SEQ_NO ?? "",
            APS_PLAN_NO    = p.APS_PLAN_NO,
            PROCESS_NAME   = p.PROCESS_NAME,
            CUSTOMER_NAME  = p.CUSTOMER_NAME ?? "",
            SITE           = p.SITE ?? "",
            APPL           = p.APPL ?? "",
            DEMAND_QTY     = (p.DEMAND_QTY ?? 0).ToString("N0"),
            DEMAND_DATE    = p.DEMAND_DATE.HasValue
                             ? p.DEMAND_DATE.Value.ToString("yyyy-MM-dd")
                             : null,
            PRODUCT_ID     = p.PRODUCT_ID ?? "",
            INPUT_QTY      = (p.INPUT_QTY ?? 0).ToString("N0")           
        }
    ).ToListAsync();

    return list;
}
          

優化要點:

  • 使用 AsNoTracking() 避免不必要的 EF Core 追蹤。
  • GroupBy(...).First() 在 DB 去重,避免重複組合在前端呈現。
  • LEFT JOIN 並在 SQL 端投影,減少傳回資料量。
  • Boolean 用三元轉成字串避開 Oracle 的 ORA-00904 "FALSE" 問題。

2. 記憶體層面去重(如果原始 DTO 裡仍有完全一樣的重複)

var distinct = resultData
    .GroupBy(r => (
        r.DEMAND_DATE,
        r.DEMAND_QTY,
        r.SITE,
        r.CUSTOMER_NAME,
        r.APPL,
        r.PLANT,
        r.PRODUCT_ID,
        r.RECIPE,
        r.EQ,
        r.INPUT_DATE,
        r.INPUT_QTY        
    ))
    .Select(g => g.First())
    .ToList();
          

3. 前端修正:動態 header 與篩選鍵

避免固定用 mapping key 當欄位,應動態建立 header,確保與 API 回傳一致:

tableHeaders.value = rows.length ? Object.keys(rows[0]) : []
          

同時移除前端篩選列表中 API 不回傳的欄位(例如原本包含但不存在的 LCM_ID),避免篩選邏輯把資料過濾掉。

4. Oracle Boolean 處理

Oracle 沒有 TRUE/FALSE literal,直接投影 C# bool 會導致:

ORA-00904: "FALSE": 無效的 ID
        

解法:在投影時手動轉型:

// 轉成字串表示
APS_DEAL = p.APS_DEAL == true ? "Y" : "N",
          

五、實作後的效益

  • **查詢效能提升**:從多次拉整表+記憶體配對,變成單一 SQL JOIN + 投影。
  • **資料正確性改善**:DB 端去重 + 前端動態欄位對齊避免「少筆但重複」錯覺。
  • **錯誤消除**:用手動轉換避免 Oracle boolean 相關錯誤。
  • **前端不再誤篩資料**:只用實際回傳的欄位進行篩選與排序。

六、SEO 關鍵字建議

可以用於 meta / 標題 / 開頭段落的關鍵字:

  • APS 排程資料重複
  • EF Core 查詢最佳化 Oracle
  • ORA-00904 FALSE 錯誤解決
  • Vue 3 table headers 動態
  • 前端篩選資料筆數少
  • 資料去重 C#
  • Oracle boolean 轉換 EF Core
  • 資料投影與 JOIN 性能提升

七、結語

企業系統常見的「前後端資料不同步」、「重複顯示」、「資料被錯誤篩掉」以及「資料庫與 ORM 型別不一致」問題,若只靠單點修補容易再出新 bug。本文從查詢層、資料投影、前端渲染、型別轉換四個層面一次性整理並修復,是一套端到端可復用的實作模式。

本篇內容適用在使用 .NET Core + EF Core 與 Oracle 後端,搭配 Vue 3 前端資料表顯示的排程系統錯誤排查與效能優化。

留言

這個網誌中的熱門文章

🛠【ASP.NET Core + Oracle】解決 ORA-00904 "FALSE": 無效的 ID 錯誤與資料欄位動態插入顯示問題

🛠【實戰排除教學】從 VS Code 的 _logger 錯誤,到 PowerShell 找不到 npm/serve,再到 Oracle ORA-03135 連線中斷——一次搞懂!

🔎如何在 Oracle PL/SQL 儲存過程中為文字欄位加入換行符號(CHR(10))——以 Updlcmremark 為例