Upsert
EF Core 新增或更新資料 (UPSERT) 的簡便寫法
Upsert傳統寫法的痛點EntrySetValues 在做什麼summary這是一個非常典型的需求:
傳入一筆資料,用 Primary Key(或唯一欄位)去比對資料庫。
若不存在 → 新增
若存在 → 更新欄位
也就是所謂的 Upsert(Update + Insert)
會員/客戶資料整併會員/客戶資料整併(CRM / User Profile)時,第三方登入回傳一組 ExternalId(Google/Facebook/LINE),系統收到最新暱稱、頭像、Email
沒有這個 ExternalId → 新增會員
已存在 → 更新最新資料(頭像、名稱、聯絡資訊)
1234existing.PropA = record.PropA;existing.PropB = record.PropB;existing.PropC = record.PropC;// ...
問題是當 Entity 有三十個欄位時,這樣的程式碼不僅冗長、容易漏改,也很難維護 ...
執行順序
Help Desk 說:「使用者回報登入錯誤,你幫我修一下。」RD 回:「我先看 log,嗯…沒看到錯誤」Help Desk:「我不是叫你看 log,我是要你先試著登錄看看啊!」RD:「那我得先知道帳號」Help Desk:「我剛不是說了嗎?就是那個登入錯誤的使用者啊!」
SQL 的執行順序,理性、結構化,你說「先 SELECT 再篩資料」,它說「不行,我得先把資料來源 JOIN 起來再說」
了解 SQL 的邏輯執行順序, 當你懂它的思考邏輯,你就不會再覺得它「不聽話」, 反而能跟它合作無間,讓查詢更快、更準、更漂亮
💼 邏輯執行順序SQL 查詢的邏輯執行順序,並不是你「寫」的順序,而是資料庫「想」的順序
步驟
關鍵字
意義
1
FROM / JOIN
先決定資料來源(要用哪些表)
2
ON
決定 JOIN 的配對條件
3
WHERE
過濾出你想要的資料
4
GROUP BY
把資料分組(分類)
5
HAVING
過濾掉不符合條件的群組
6
SELECT
挑出你想顯示的欄位
7
UNION 等集合運算
合併多個查詢結果
8 ...
Field
在 SQL 資料表設計時,「欄位型別的選擇」會直接影響到:
儲存空間(Database Size)
查詢效能(Index / Join / Sort)
可擴充性(是否足夠表示未來的資料量)
💼 char / varchar / nchar / nvarchar「var」表示變長,「n」表示支援 Unicode
🔹 定長:char想像你開一間餐廳,每張桌子都是固定 10 個座位 (char(10)),不管今天坐 2 個人還是 10 個人,桌子都占同樣的空間也就是說,你設定 char(10),即使只放 ‘Hi’,它還是佔 10 Bytes,系統會幫你在後面補空白(space),讓長度固定
char 因為長度固定,SQL Server 可以「快速計算位置」,所以在大量查詢時效能較好。所以 char 比較「浪費空間但速度快」;varchar 比較「省空間但速度略慢一點」
🔹 Unicode vs. 非Unicode(n 開頭的型別)Unicode 是一種「萬國通用的文字編碼」,用來同時支援 中、英、日、韓、泰文 等不同語 ...
Index - 發揮作用...了嗎
5個概念拯救龜速的SQL查詢(Query)
索引沒有覆蓋(Covering Index)索引沒有覆蓋查詢(Covering Index)複合索引的順序不對(Leftmost Prefix 原則)索引欄位的「資料分佈」不好(Cardinality)Equality 與 Range 的順序Optimizersummary索引是「查詢條件、資料分佈、索引結構三件事剛好對齊時,Optimizer 才會願意用它」,假設我們今天建立了一個 Index,我們以為它可以幫忙「快速定位資料」,Optimizer 看查詢條件會嘗試判斷能不能用這個 Index 做 Seek、用了之後要不要回主表(Key Lookup)、成本是不是比 Scan 還低,Optimizer 依據 Statistics 估算回傳列數,不是實際跑,而是「猜」,如果猜錯,整個執行計畫就歪掉,只要任何一環不理想、Index 欄位不夠、欄位順序不對、資料分佈太平均、統計過期,則 Optimizer 就會放棄你以為「應該要用」的索引
因此會發生已經建好索引,而且查詢條件也寫得很明確,但實際發生的是出現 Key Lookup、Index ...
IsolationLevel
交易隔離層級是用來控制「當多個交易同時讀寫資料時,要不要讓他們互相看到對方的變更。要資料「越準確」,就得「越鎖」,要系統「越快」,就得「越鬆」,是在討論競爭條件(Race condition)的議題
💼 READ UNCOMMITTED允許交易去「偷看別人還沒寫完的資料」,這樣雖然速度快,但有風險,因為你讀到的資料可能會「被改回去」或「消失」
不會加共用鎖 (Shared Lock),所以別人正在改資料時,你一樣能讀它。
不會被排他鎖 (Exclusive Lock) 阻擋,所以就算別人正在修改資料、還沒提交,你也能去讀它。
🟢 Shared Lock(共用鎖)是 SQL Server 在「讀資料」時加上的一種鎖,它的作用是我正在看資料,別人在我看完之前不能改它觸發時機:SELECT 查詢(讀資料),可以多個共存 Shared Lock 但會阻擋 Exclusive Lock(別人不能改)
用途:確保你讀的資料在讀取過程中不會被修改
12345BEGIN TRAN;SELECT * FROM Products WHERE Id = 1; -- Shared Lock ...
EFCORE - 關聯載入的海流
潮汐為什麼 Lazy Loading 會造成效能問題?Eager Loading:一次載入所有需要的資料Select 投影(Projection)分段查詢(Split Query)LINQ 查詢中使用 IEnumerable.Contains()非對應類型(Non-Mapped Type)查詢方式的差異Summary這是一份「資料載入的潮汐圖」。我們將從 Lazy 與 Eager 的對比開始,一路探索 N+1 問題的成因、查詢快取的脈動、再航向非對應類型與原生 SQL 的深處…Lazy Loading(延遲載入)是一種「等你真的用到資料時再去撈」的策略
你查出所有英國的客戶(Customers),但還沒看他們的訂單(Orders)。Lazy Loading 的邏輯是:「先不用撈訂單,等你真的要看時再查就好
12var customers = context.Customers.Where(c => c.Country == "UK").ToList();Console.WriteLine(customers.First().Orders.Count);
但實際 ...
Datetime Flow
Flow時間參數化當你對時間欄位動手算,流程就已經反了迴圈實現同一件事反覆發生發現重複運算,其實是在提醒你「邏輯混在一起了」summa所有與時間相關的資料問題,第一步一定是先切出正確的時間工作區,再談任何分析、轉換與計算
在資料查詢與分析中,「流程感」會具體化成這件事 : 先用時間,把資料切成一塊安全、可工作的區間
所以在任何進階操作之前,第一步永遠是時間參數化(所有後續的地基),因此在做下面任何事情之前
格式轉換(YEAR / MONTH / CONVERT / 字串化)
計算邏輯(DATEDIFF、CASE、狀態判斷)
資料聚合(GROUP BY、AVG、SUM)
我們都應該先完成一件事,用「可走索引的時間區間參數」把資料切出來。而這三類操作有一個共通點,它們都會降低索引的價值,甚至直接讓索引失效,因此正確順序不是我要算月報 → GROUP BY MONTH → 再來想效能,而是先用時間縮小資料範圍 → 再隨便你怎麼算任何進階分析、轉換、統計之前,第一件事永遠是:先用「可走索引的時間區間參數」把資料切出一塊安全的工作區
格式轉換(YEAR ...
SQL - 文字列の森
💼 最長欄位SQL Server 在執行 ORDER BY LEN(Video_Introduction) 時,必須對每一筆資料都算一次長度,然後再排序
12345USE InfoDB;SELECT TOP 1 LEN(Video_Introduction),Video_IntroductionFROM Video(NOLOCK)ORDER BY LEN(Video_Introduction) DESC
若僅僅想知道最長,不需要排序!
1SELECT MAX(LEN(Video_Introduction)) FROM Video (NOLOCK);
💼 LIKE ‘%xxx%’ 效能差?索引是一種「字典排序的結構(B-tree)」,想像成一本電話簿(索引)
🔹 有開頭字串的 LIKE你可以很快找到「開頭是 09」的電話,但如果你說「我要找結尾是 1234」的電話,電話簿就得一筆筆翻完才知道
📘 索引是有方向的(從左到右),開頭沒固定的查詢無法用索引來加速
執行策略
說明
效能
Index Seek
透過索引直接找到目標資料列
🚀 快
I ...
Implicit Conversion & Explicit Conversion
關於婚姻與育兒...Implicit ConversionExplicit Conversion先轉型好再 JOIN(避免在 JOIN 內 CAST)誤用 cfn拆出 GroupBy 案例summary生小孩後的夫妻,就像兩個本來型別不同的欄位,一個是「我覺得應該這樣做」的 string,一個是「我以為你希望我這樣做」的 bigint,兩人的期待、習慣、壓力都不一致,但因為忙、因為累、因為怕吵架,沒人敢明確地把自己的需求「顯式轉型」說出來,於是關係裡就開始出現「隱式轉換」
「算了,我先做吧,不然會更麻煩。」
…
「我應該能撐一下,他今天也很累。」
…
「這沒什麼啦,我忍一下就過了。」
看似體貼,能運作,但表面好看,內裡不對等
累 → 生氣生氣 → 委屈委屈 → 無聲無聲 → 彼此以為「沒事」
需要轉型本身並沒有錯誤,資料的來源、格式、責任歸屬、生命周期都跨越多個系統與團隊,此時資料庫遇到 JOIN 或比較時,就會產生轉換需求,重要的是要能有溝通的認知,預防性做好準備
當兩個不同型別的值需要比較時,資料庫必須強制把它們變成「同一種型別」,而這個自動決定的型別若不夠精確,就會導致邏輯錯誤
...
Nested Loop Join & Merge Join & Hash Join
戀愛類型Nested Loop JoinMerge JoinHash Join引擎怎麼做選擇你是什麼樣的戀愛類型呢?
毛吉是那種聞到喜歡的味道就會湊上去確認的類型,因為她他有一開始就設定好標準,只能靠一次次互動中慢慢觀察、逐一比對。透過 Nested Loop 聞到喜歡的屁股就 Join 下去,通常吃幾個巴掌
阿冠比較理性,屬於先驗條件獵人型。他會先用一套邏輯,把自己「Hash」好,然後就靠這組標準去掃描目標對象。這就是 Hash Join,直接把效率拉到極致
最理想的狀況,當然是兩個人都已經「排序」好自己,生活節奏對齊,價值觀同步,見面時幾乎不需要猜測,搭上就能對得很漂亮,就是 Merge Join「外層每一筆資料,都去內層找一筆相對應的資料」,效率完全取決於內層查找是否能快速定位
有兩份名單
Outer Table:10 個學生名字
Inner Table:100 萬筆成績紀錄
要做的事是
「拿出第一個學生 → 去成績表查他的資料」「再拿第二個學生 → 去查他的資料」………
➡️ 所以整個流程非常直覺,有點像是「外層迴圈包內層查詢」
內表能不能快速查到資料?Nested L ...





