SQL Server

Truy vấn T-SQL nâng cao

JOIN, subquery, set operation, CTE recursive, window function, transaction, isolation level — gốc cho SQL Server.

1. JOIN — đào sâu

5 loại JOIN + minh hoạ

-- INNER — chỉ row match cả 2 bảng
SELECT c.Name, o.OrderDate
FROM Customers c
INNER JOIN Orders o ON o.CustomerId = c.Id;

-- LEFT — tất cả customer + đơn nếu có
SELECT c.Name, o.OrderDate
FROM Customers c
LEFT JOIN Orders o ON o.CustomerId = c.Id;

-- RIGHT — đảo lại (ít dùng vì khó đọc, swap LEFT thuận hơn)
SELECT c.Name, o.OrderDate
FROM Orders o
RIGHT JOIN Customers c ON o.CustomerId = c.Id;

-- FULL OUTER — tất cả row 2 bên
SELECT c.Name, o.OrderDate
FROM Customers c
FULL OUTER JOIN Orders o ON o.CustomerId = c.Id;

-- CROSS — tích Descartes (m × n)
SELECT c.Name, p.Name
FROM Customers c CROSS JOIN Products p;
Bẫy phỏng vấn — LEFT JOIN + WHERE: điều kiện trên bảng phải đặt vào ON, không phải WHERE, để giữ NULL.
-- ❌ Vô tình biến LEFT JOIN thành INNER
SELECT c.* FROM Customers c
LEFT JOIN Orders o ON o.CustomerId = c.Id
WHERE o.Status = 'Paid';   -- lọc luôn row có o.Status NULL

-- ✅ Đặt vào ON
SELECT c.* FROM Customers c
LEFT JOIN Orders o ON o.CustomerId = c.Id AND o.Status = 'Paid';

SELF JOIN

-- Bảng Employees có ManagerId trỏ về Employees.Id
SELECT e.Name AS Employee, m.Name AS Manager
FROM Employees e
LEFT JOIN Employees m ON m.Id = e.ManagerId;

Anti-join — tìm record KHÔNG có liên kết

-- Khách hàng chưa từng đặt đơn — 3 cách
-- 1. LEFT JOIN ... IS NULL
SELECT c.* FROM Customers c
LEFT JOIN Orders o ON o.CustomerId = c.Id
WHERE o.Id IS NULL;

-- 2. NOT EXISTS (thường tốt nhất với SQL Server)
SELECT c.* FROM Customers c
WHERE NOT EXISTS (
    SELECT 1 FROM Orders o WHERE o.CustomerId = c.Id
);

-- 3. NOT IN (cẩn thận NULL!)
SELECT c.* FROM Customers c
WHERE c.Id NOT IN (
    SELECT CustomerId FROM Orders WHERE CustomerId IS NOT NULL
);
Câu PV:"NOT IN vs NOT EXISTS — khác gì?"
  • NOT IN cho kết quả sai nếu subquery có NULL (vì x <> NULL là UNKNOWN).
  • NOT EXISTS xử lý NULL đúng + thường có plan tốt hơn.
  • Khuyến nghị: mặc định dùng NOT EXISTS.

2. Subquery

Scalar subquery — trả 1 giá trị

SELECT Name,
    (SELECT COUNT(*) FROM Orders WHERE CustomerId = c.Id) AS OrderCount
FROM Customers c;

Correlated subquery — tham chiếu outer query

-- Top 3 sản phẩm đắt nhất MỖI category
SELECT * FROM Products p1
WHERE (
    SELECT COUNT(*) FROM Products p2
    WHERE p2.CategoryId = p1.CategoryId AND p2.Price > p1.Price
) < 3;

→ Cách hiện đại: dùng Window function (mục 5).

EXISTS

-- Khách có ít nhất 1 đơn > 10 triệu
SELECT * FROM Customers c
WHERE EXISTS (
    SELECT 1 FROM Orders o
    WHERE o.CustomerId = c.Id AND o.Total > 10000000
);

Derived table (inline view)

SELECT t.City, t.TotalRevenue
FROM (
    SELECT c.City, SUM(o.Total) AS TotalRevenue
    FROM Customers c JOIN Orders o ON o.CustomerId = c.Id
    GROUP BY c.City
) t
WHERE t.TotalRevenue > 100000000;

3. Set operations

-- UNION — gộp + loại trùng (chậm hơn)
SELECT Email FROM Customers
UNION
SELECT Email FROM Suppliers;

-- UNION ALL — gộp, không loại trùng (NHANH HƠN)
SELECT Email FROM Customers
UNION ALL
SELECT Email FROM Suppliers;

-- INTERSECT — giao
SELECT Email FROM Customers
INTERSECT
SELECT Email FROM Suppliers;

-- EXCEPT — hiệu (A trừ B)
SELECT Email FROM Customers
EXCEPT
SELECT Email FROM Suppliers;
UNION vs UNION ALL:UNION thêm bước SORT DISTINCT (tốn). Nếu biết chắc không trùng, dùng UNION ALL nhanh hơn nhiều.

4. CTE — Common Table Expression

CTE đơn giản

WITH HighValueOrders AS (
    SELECT * FROM Orders WHERE Total > 10000000
)
SELECT c.Name, COUNT(*) AS BigOrderCount
FROM HighValueOrders o
JOIN Customers c ON c.Id = o.CustomerId
GROUP BY c.Name;

CTE giúp code đọc dễ hơn nhiều subquery lồng nhau.

CTE đa stage

WITH 
TopCustomers AS (
    SELECT TOP 10 CustomerId, SUM(Total) AS Spent
    FROM Orders GROUP BY CustomerId
    ORDER BY Spent DESC
),
TheirOrders AS (
    SELECT o.* FROM Orders o
    WHERE o.CustomerId IN (SELECT CustomerId FROM TopCustomers)
)
SELECT * FROM TheirOrders WHERE OrderDate >= '2026-01-01';

Recursive CTE — tree

-- Build cây tổ chức từ root xuống
WITH OrgTree AS (
    -- Anchor: root (không có manager)
    SELECT Id, Name, ManagerId, 0 AS Lvl, CAST(Name AS NVARCHAR(MAX)) AS Path
    FROM Employees WHERE ManagerId IS NULL
    
    UNION ALL
    
    -- Recursive: tìm nhân viên có manager đã ở trong tree
    SELECT e.Id, e.Name, e.ManagerId, t.Lvl + 1,
           CAST(t.Path + N' > ' + e.Name AS NVARCHAR(MAX))
    FROM Employees e
    JOIN OrgTree t ON t.Id = e.ManagerId
)
SELECT * FROM OrgTree ORDER BY Path;
Câu PV:"Khi nào dùng Recursive CTE?" → tree/hierarchy (org chart, comment thread, bill-of-material), graph path, generate sequence (số 1→N).

5. Window function

Cấu trúc tổng quát

function_name() OVER (
    [PARTITION BY col1, col2 ...]
    [ORDER BY col1 [ASC|DESC] ...]
    [ROWS|RANGE BETWEEN ... AND ...]
)

Ranking — ROW_NUMBER / RANK / DENSE_RANK

-- Cùng dữ liệu: 100, 100, 90, 80
SELECT
    Value,
    ROW_NUMBER() OVER (ORDER BY Value DESC) AS Rn,    -- 1, 2, 3, 4
    RANK()       OVER (ORDER BY Value DESC) AS Rk,    -- 1, 1, 3, 4 (skip)
    DENSE_RANK() OVER (ORDER BY Value DESC) AS Dk     -- 1, 1, 2, 3 (no skip)
FROM Scores;

Use case kinh điển — Top N per group

-- Đơn hàng MỚI NHẤT của MỖI khách
WITH Ranked AS (
    SELECT *, ROW_NUMBER() OVER (
        PARTITION BY CustomerId
        ORDER BY OrderDate DESC
    ) AS Rn
    FROM Orders
)
SELECT * FROM Ranked WHERE Rn = 1;
Câu hỏi siêu hot:"Lấy đơn hàng mới nhất của mỗi khách hàng — viết query."Đây là test point xem fresher biết window function không. Câu trên là đáp án chuẩn. Cách cổ điển (correlated subquery) chậm hơn nhiều.

Aggregate window function

SELECT
    OrderDate,
    Total,
    SUM(Total) OVER (ORDER BY OrderDate) AS RunningTotal,
    AVG(Total) OVER (
        ORDER BY OrderDate
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) AS MovingAvg7Days
FROM Orders;

LAG / LEAD — so sánh row liền kề

SELECT
    OrderDate, Total,
    LAG(Total) OVER (ORDER BY OrderDate) AS PrevTotal,
    Total - LAG(Total) OVER (ORDER BY OrderDate) AS DeltaFromPrev
FROM Orders;

NTILE — chia bucket

-- Chia khách thành 4 quartile theo total spend
SELECT CustomerId, Spent,
    NTILE(4) OVER (ORDER BY Spent DESC) AS Quartile
FROM (
    SELECT CustomerId, SUM(Total) AS Spent
    FROM Orders GROUP BY CustomerId
) t;

6. Aggregate & GROUP BY nâng cao

GROUPING SETS / ROLLUP / CUBE

-- Tổng theo nhiều combination cùng lúc — báo cáo
SELECT City, Status, COUNT(*) AS Cnt
FROM Orders o JOIN Customers c ON c.Id = o.CustomerId
GROUP BY GROUPING SETS (
    (City, Status),       -- detail
    (City),               -- subtotal theo City
    (Status),             -- subtotal theo Status
    ()                    -- grand total
);

-- ROLLUP = subtotal lũy tiến
GROUP BY ROLLUP (Year, Month, Day);

-- CUBE = mọi combination
GROUP BY CUBE (City, Status);

HAVING vs WHERE

-- WHERE lọc TRƯỚC group, HAVING lọc SAU group
SELECT City, COUNT(*) cnt
FROM Customers
WHERE IsActive = 1                 -- trước group
GROUP BY City
HAVING COUNT(*) > 5;               -- sau group

STRING_AGG (2017+)

-- Gộp tên người trong cùng city thành 1 string
SELECT City, STRING_AGG(Name, ', ')
    WITHIN GROUP (ORDER BY Name) AS People
FROM Customers
GROUP BY City;

7. PIVOT / UNPIVOT

-- Doanh thu theo tháng, hàng = sản phẩm
SELECT *
FROM (
    SELECT ProductName, MONTH(OrderDate) AS m, Total
    FROM Orders
) src
PIVOT (
    SUM(Total) FOR m IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) AS p;

PIVOT hay được dùng cho báo cáo. Với data dynamic cột → kết hợp dynamic SQL.

8. Transaction & ACID

Cú pháp transaction

BEGIN TRANSACTION;
BEGIN TRY
    UPDATE Accounts SET Balance = Balance - 1000 WHERE Id = 1;
    UPDATE Accounts SET Balance = Balance + 1000 WHERE Id = 2;
    
    IF (SELECT Balance FROM Accounts WHERE Id = 1) < 0
        THROW 50001, N'Insufficient funds', 1;
    
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    THROW;            -- rethrow để app biết
END CATCH

Savepoint

BEGIN TRANSACTION;
INSERT INTO Logs VALUES ('Step 1');
SAVE TRANSACTION sp1;

INSERT INTO Logs VALUES ('Step 2');
IF (@@ERROR <> 0) ROLLBACK TRANSACTION sp1;   -- rollback về step 1 thôi

COMMIT TRANSACTION;

ACID — định nghĩa

Ý nghĩa
AtomicityTất cả hoặc không gì — commit hết hoặc rollback hết.
ConsistencyDB trước-sau transaction vẫn hợp lệ (PK, FK, CHECK).
IsolationTransaction không thấy nháp của transaction khác.
DurabilitySau COMMIT, dữ liệu bền vững dù crash.
PV gần như chắc chắn hỏi ACID. Học thuộc 4 chữ + giải thích bằng ví dụ chuyển khoản ngân hàng.

9. Isolation level

5 level của SQL Server

LevelDirty readNon-repeatable readPhantom read
Read Uncommitted✅ Có✅ Có✅ Có
Read Committed (default)
Repeatable Read
Serializable
Snapshot❌ (dùng MVCC versioning)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- ...transaction body...

-- Hoặc per query (hint)
SELECT * FROM Orders WITH (NOLOCK);    -- = READ UNCOMMITTED — dirty read OK

3 anomaly cần thuộc

  • Dirty read: đọc dữ liệu của transaction CHƯA commit.
  • Non-repeatable read: đọc cùng row 2 lần, lần 2 thấy khác (vì transaction khác UPDATE+commit giữa chừng).
  • Phantom read: query 1 range 2 lần, lần 2 thấy thêm/bớt row (vì transaction khác INSERT/DELETE).
Câu PV hot:"SQL Server default isolation là gì? Postgres default là gì? Khác gì?"
  • SQL Server: READ COMMITTED (block, không MVCC mặc định).
  • Postgres: READ COMMITTED nhưng dùng MVCC — đọc không block ghi.
  • MySQL InnoDB: REPEATABLE READ (default cao hơn 2 cái trên).

NOLOCK — đừng lạm dụng

WITH (NOLOCK) = READ UNCOMMITTED cho 1 query. Dùng cho báo cáo chấp nhận sai số nhẹ. Tránh trong code nghiệp vụ (ngân hàng, đơn hàng) — gây dirty read.

10. Deadlock — nhận biết & tránh

Deadlock = 2+ transaction giữ lock và chờ nhau, bế tắc. SQL Server tự pick "deadlock victim" và rollback nó.Cách tránh:
  • Lock theo cùng thứ tự trong mọi transaction (vd: luôn UPDATE Account A trước B).
  • Giữ transaction ngắn.
  • Update đúng cột cần, không lock thừa.
  • Isolation thấp hơn nếu được (Snapshot).
-- Bật theo dõi deadlock trong session
DBCC TRACEON (1222, -1);   -- log deadlock graph ra ERRORLOG

11. AI-Augmented Query Optimization (SQL Server 2025)

SQL Server 2025 dua AI/ML vao query optimizer -- engine tu hoc tu workload thuc te de chon plan tot hon.

Cardinality Estimation (CE) Feedback

CE Feedback la tinh nang hoc tu query lap lai. Engine ghi nhan khi uoc luong cardinality sai, tu dieu chinh cho lan chay sau. Du lieu feedback duoc persist qua restart -- khong mat khi reboot.
-- Bat CE Feedback (mac dinh ON trong 2025)
ALTER DATABASE SCOPED CONFIGURATION
SET CE_FEEDBACK = ON;

-- Kiem tra feedback da duoc ap dung
SELECT * FROM sys.query_store_plan_feedback
WHERE feature_id = 1;  -- CE feedback
Cau PV 2026:"CE Feedback giai quyet van de gi?"
  • Bad parameter sniffing -- khi plan duoc compile cho tham so A nhung chay voi tham so B gay scan ca bang.
  • CE Feedback phat hien sai, tu tao plan moi -- khong can RECOMPILE hint hay plan guide thu cong.
  • Khac voi Query Store plan forcing: CE Feedback tu dong va hoc lien tuc.

PSPO -- Parameter Sensitive Plan Optimization

-- Bat PSPO (mac dinh ON trong 2025)
ALTER DATABASE SCOPED CONFIGURATION
SET PARAMETER_SENSITIVE_PLAN_OPTIMIZATION = ON;

PSPO cache nhieu execution plan cho cung 1 query, moi plan toi uu cho 1 khoang gia tri tham so khac nhau. Khi chay, engine tu chon plan phu hop nhat voi gia tri hien tai.

Khi nao dung: stored procedure co tham so @Status -- khi @Status = 'Active' tra 90% bang, khi @Status = 'Suspended' tra 0.1% bang. PSPO giu 2 plan rieng, khong con "1 plan fit all" gay loi.

OPPO -- Optional Parameter Plan Optimization

Giai quyet van de optional parameter -- khi tham so co the NULL hoac co gia tri:

-- Pattern pho bien gay van de:
SELECT * FROM Orders
WHERE (@CustomerId IS NULL OR CustomerId = @CustomerId)
  AND (@Status IS NULL OR Status = @Status);
-- ⚠️ OPTION (RECOMPILE) truoc day la cach chua duy nhat

OPPO tu dong nhan dien pattern nay, tao plan toi uu cho tung to hop tham so, khong can OPTION (RECOMPILE).

Optimized Locking -- dot pha ve concurrency

Dot pha ve concurrency trong SQL Server 2025: Optimized Locking loai bo lock escalation -- row-level locks giu nguyen row-level trong suot transaction. Giam blocking dang ke, dac biet voi workload OLTP nang.
-- Bat Optimized Locking (mac dinh ON trong 2025)
ALTER DATABASE SCOPED CONFIGURATION
SET OPTIMIZED_LOCKING = ON;
Truoc 2025Tu 2025
UPDATE 10,000 rows → escalate len page/table lockUPDATE 10,000 rows → giu 10,000 row-level locks
Chan toan bo session khacSession khac van truy cap rows khac binh thuong

LAQ -- Lock After Qualification

-- Pattern duoc LAQ toi uu:
UPDATE Orders SET Status = 'Processed'
WHERE Status = 'Pending' AND OrderDate < '2026-01-01';
Truoc 2025Voi LAQ
Lock TAT CA rows trong bang → loc WHERE → update rows matchLoc WHERE truoc → chi lock rows match dieu kien
Cau PV:"LAQ khac gi voi cach lock truyen thong?" → Lock After Qualification loc truoc, lock sau -- giam so luong lock, giam blocking, tang throughput. Dac biet hieu qua khi WHERE filter ra it rows (< 10% bang).

12. Batch Mode cho Built-in Functions (SQL Server 2025)

Cac ham built-in nay gio chay o batch mode (vectorized) thay vi row-by-row:

ABS(), SIN(), COS(), DATE_TRUNC(), LOG(), EXP(), SQRT(), POWER(), CEILING(), FLOOR(), ROUND(), GREATEST(), LEAST()

-- Query nay gio chay ~70% nhanh hon nho batch mode
SELECT
    ABS(PriceChange) AS AbsoluteChange,
    SIN(RADIANS(Latitude)) AS SinLat,
    DATE_TRUNC('month', OrderDate) AS OrderMonth
FROM Orders
WHERE OrderDate >= '2026-01-01';
Cau PV:"Batch mode la gi? Tai sao 2025 lai mo rong?"
  • Batch mode xu ly 900 rows/lan (vectorized), thay vi tung row mot (row mode).
  • Truoc 2025: chi columnstore indexes, aggregate functions (SUM, AVG) va mot vai operator dung batch mode.
  • 2025: mo rong sang built-in scalar functions -- CPU-bound queries cai thien ~70%.
  • Khong can thay doi code -- optimizer tu chon batch mode khi co loi.

13. OPTIMIZED_SP_EXECUTESQL (SQL Server 2025)

Tinh nang danh cho high-concurrency: ngăn "compile storm" khi hang tram/hang ngan connection goi cung 1 stored procedure dong thoi.
-- Thay vi sp_executesql thong thuong
EXEC sp_executesql @sql, @params, @p1, @p2;

-- Dung OPTIMIZED variant
EXEC sys.OPTIMIZED_SP_EXECUTESQL @sql, @params, @p1, @p2;

Van de: Khi nhieu connection cung goi 1 stored procedure lan dau tien, moi connection deu co gang compile rieng → "compile storm" ton CPU, tranh Plan Cache.

Giai phap: OPTIMIZED_SP_EXECUTESQL chia se cung 1 compiled plan cho tat ca cac concurrent executions, chi compile 1 lan duy nhat.

Khi nao dung: API endpoint duoc goi > 1000 req/s, moi req goi cung 1 stored procedure. Dung OPTIMIZED variant giam CPU compile, tang throughput.

14. Vector Search trong Truy van

SQL Server 2025 ho tro native vector operations cho semantic/embedding search.

Semantic search ket hop SQL truyen thong

-- Tim 10 san pham tuong tu nhat, kem loc theo category + gia
DECLARE @query_vector VECTOR(1536);
-- @query_vector duoc tao tu embedding model (OpenAI, v.v.)

SELECT TOP 10
    p.name,
    p.price,
    VECTOR_DISTANCE('cosine', p.embedding, @query_vector) AS score
FROM products p
WHERE p.category_id = 5
    AND p.price BETWEEN 100 AND 1000
ORDER BY score ASC;

Hybrid search: filter + vector

-- Dung VECTOR_SEARCH de lay tap ung vien, sau do JOIN loc them
WITH semantic AS (
    SELECT
        id,
        VECTOR_DISTANCE('cosine', embedding, @query_vector) AS score
    FROM products
    WHERE VECTOR_SEARCH(embedding, @query_vector, 100)
)
SELECT p.*, s.score
FROM products p
JOIN semantic s ON p.id = s.id
WHERE p.in_stock = 1
ORDER BY s.score ASC;
Cau PV 2026:"Hybrid search la gi? Tai sao khong chi dung vector?"
  • Hybrid search = vector similarity + traditional SQL filter (WHERE, JOIN, GROUP BY).
  • Chi dung vector: tim "giay chay bo" tra ve ca san pham het hang hoac sai category.
  • Hybrid: semantic similarity trong pham vi category="shoes" AND in_stock=1.
  • Pattern: CTE/WITH de tinh vector score → JOIN ra bang goc → loc them.

Tao & quan ly vector index

-- Tao vector index cho tim kiem ANN (Approximate Nearest Neighbor)
CREATE VECTOR INDEX idx_product_embedding
ON products (embedding)
WITH (DISTANCE_METRIC = 'cosine', INDEX_TYPE = 'IVFFLAT');

-- Query su dung index
SELECT TOP 20 name, VECTOR_DISTANCE('cosine', embedding, @query_vector) AS score
FROM products
ORDER BY score ASC;
Distance metrics:cosine (pho bien nhat cho semantic similarity), euclidean, dot_product. Chon tuy theo embedding model cua ban.

15. JSON Queries Nang Cao

SQL Server 2025 bo sung cac ham xu ly JSON manh me hon.

JSON_TABLE -- bien JSON thanh bang quan he

-- JSON_TABLE: tuong tu MySQL, chuyen JSON array thanh cac row
SELECT j.*
FROM orders
CROSS APPLY OPENJSON(order_data, '$.items')
    WITH (
        product_id INT       '$.product_id',
        qty        INT       '$.qty',
        price      DECIMAL(10,2) '$.price'
    ) AS j;

JSON_CONTAINS -- kiem tra gia tri trong JSON

-- Kiem tra JSON co chua gia tri 'error' trong field $.level khong
SELECT *
FROM logs
WHERE JSON_CONTAINS(payload, 'error', '$.level');

-- Tim san pham co tag 'sale'
SELECT *
FROM products
WHERE JSON_CONTAINS(tags, '"sale"');

JSON_PATH_EXISTS -- kiem tra path ton tai

SELECT *
FROM documents
WHERE JSON_PATH_EXISTS(metadata, '$.author.email');
So sanh nhanh JSON functions:
FunctionCong dung
OPENJSON + WITHParse JSON array → bang (da co tu 2016)
JSON_VALUELay scalar value tu path
JSON_QUERYLay object/array tu path
JSON_MODIFYCap nhat gia tri trong JSON
JSON_CONTAINSKiem tra gia tri co ton tai (2025)
JSON_PATH_EXISTSKiem tra path co ton tai (2025)

16. RegEx trong Truy van

SQL Server 2025 ho tro Regular Expressions native.

REGEXP_LIKE -- tim kiem pattern

-- Tim tai lieu chua tu khoa nhay cam (case-insensitive)
SELECT *
FROM documents
WHERE REGEXP_LIKE(content, '\b(confidential|secret|internal)\b', 'i');

-- Validate email format
SELECT *
FROM users
WHERE NOT REGEXP_LIKE(email, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');

REGEXP_SUBSTR -- trich xuat du lieu tu text

-- Trich xuat dia chi IP tu log
SELECT
    id,
    REGEXP_SUBSTR(description, '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}') AS ip_address
FROM logs;

-- Trich xuat so dien thoai
SELECT REGEXP_SUBSTR(notes, '\d{2,4}[-\s]?\d{3,4}[-\s]?\d{4}') AS phone
FROM contacts;

REGEXP_REPLACE -- thay the pattern

-- Mask so dien thoai trong log
SELECT REGEXP_REPLACE(
    log_message,
    '\d{2,4}[-\s]?\d{3,4}[-\s]?\d{4}',
    '***MASKED***'
) AS sanitized_message
FROM audit_logs;

REGEXP_COUNT -- dem so lan xuat hien

-- Dem so URL trong bai viet
SELECT
    id,
    REGEXP_COUNT(content, 'https?://[^\s]+') AS url_count
FROM articles;
Cau PV:"Truoc 2025 SQL Server xu ly RegEx nhu the nao?" → Chi co LIKE voi wildcard (%, _, [abc]) don gian, hoac dung CLR integration / external script de goi .NET Regex. 2025 co native RegEx -- nhanh hon nhieu, khong can CLR.
Canh bao performance: RegEx khong dung index. Tranh REGEXP_LIKE tren bang lon khong co WHERE loc truoc. Pattern nen cang cu the cang tot, tranh backtracking qua sau.

17. Intelligent Query Processing (IQP) -- Tong quan & Cap nhat 2025

IQP la bo tinh nang tu dong cai thien query performance, khong can thay doi code.

Bang tong hop IQP qua cac phien ban

Tinh nang IQP2017201920222025
Adaptive Joins
Interleaved Execution
Memory Grant Feedback✅ (cai thien)✅ (cai thien)
Table Variable Deferred Compilation--
Scalar UDF Inlining--
Degree of Parallelism Feedback (DOP Feedback)----✅ (cai thien)
CE Feedback------NEW
Optimized Locking------NEW
Parameter Sensitive Plan (PSPO)------NEW
Optional Parameter Plan (OPPO)------NEW
Cau PV 2026:"So sanh IQP qua cac phien ban -- diem moi cua 2025 la gi?"
  • 2017: Adaptive Joins + Interleaved Execution + Memory Grant Feedback (3 tinh nang goc).
  • 2019: Scalar UDF Inlining + Table Variable Deferred Compilation.
  • 2022: DOP Feedback + Memory Grant Feedback cai thien (persisted).
  • 2025: AI-driven -- CE Feedback hoc tu workload, Optimized Locking loai bo lock escalation, PSPO/OPPO tu dong chon plan theo tham so.
  • Khac biet cot loi: 2017-2022 la "heuristic cai thien", 2025 la "ML tu hoc lien tuc".

Bat/tat IQP features

-- Kiem tra IQP features dang bat
SELECT name, value_in_use
FROM sys.configurations
WHERE name LIKE '%intelligent%'
   OR name LIKE '%feedback%'
   OR name LIKE '%adaptive%';

-- Bat tat ca IQP features (2025, mac dinh ON)
ALTER DATABASE SCOPED CONFIGURATION
SET CE_FEEDBACK = ON,
    DOP_FEEDBACK = ON,
    MEMORY_GRANT_FEEDBACK = ON,
    OPTIMIZED_LOCKING = ON,
    PARAMETER_SENSITIVE_PLAN_OPTIMIZATION = ON;

18. Azure SQL Hyperscale — khác biệt về isolation, failover, scale-out

Azure SQL Database Hyperscale là kiến trúc storage-compute tách rời, khác biệt đáng kể so với SQL Server boxed product về cách hoạt động transaction, failover, và read scale.

Isolation & transaction

SQL Server on-premAzure SQL Hyperscale
Default isolationRead Committed (lock-based)Read Committed Snapshot (RCSI) ON mặc định
Snapshot / MVCCPhải bật READ_COMMITTED_SNAPSHOT thủ côngBật sẵn — version store dùng page server (storage layer riêng)
TempDBLocal SSD, contention bottleneckKhông dùng TempDB cho version store — tránh PAGELATCH bottleneck
Long transactionBloat version store trong TempDBVersion store nằm trên page server (hầu như không giới hạn)
Lock memoryShared global lock managerPer-node lock manager (scale-out tự nhiên hơn)
Câu PV quan trọng:"RCSI trong Hyperscale khác gì SQL Server thường?"

"Hyperscale bật RCSI mặc định và không dùng TempDB cho version store. Page server lưu tất cả version → loại bỏ hoàn toàn TempDB contention, PAGELATCH bottleneck. Long transaction không gây bloat TempDB. Đây là lý do Hyperscale phù hợp cho workload mixed OLTP + reporting."

Failover & High Availability

┌──────────────┐      ┌──────────────┐
│  Compute     │◄────►│  Compute     │
│  (Primary)   │      │  (Secondary) │
└──────┬───────┘      └──────┬───────┘
       │                     │
       └──────────┬──────────┘
                  │
         ┌────────▼────────┐
         │   Page Server   │  ← Storage layer shared giữa các replica
         │   (Data + Log)  │
         └─────────────────┘
SQL Server on-premAzure SQL Hyperscale
Failover time30s-2 phút (AG failover)< 10 giây (compute node restart + reattach page server)
Data syncSync/async commit qua AGKhông cần sync data — page server dùng chung
RPO0 với sync commit, >0 với async0 RPO (log ghi vào page server trước khi ACK)
Read replicasTối đa 8 secondary (AG), cần license0-30 named replicas (không giới hạn bởi AG), provision nhanh
Replica lagVài ms đến vài giây (tuỳ sync mode)Sub-second (page server push log trực tiếp)

Scale-out reads — tính năng đặc thù Hyperscale

-- Connect string cho read-only replica trong Hyperscale
-- Server=tcp:myserver.database.windows.net;Database=mydb;ApplicationIntent=ReadOnly;

-- Không cần cấu hình AG listener thủ công — Azure tự route
-- Mỗi named replica có connection string riêng
Hyperscale read scale-out:
  • Named replicas: tạo replica với tên riêng, có thể có compute size khác primary (VD: primary 8 vCore, replica 40 vCore cho reporting nặng).
  • High-availability replicas: free, tự động tạo cho HA (không dùng cho read workload).
  • Mỗi replica dùng chung page server → không cần sync data → tạo replica trong < 1 phút, không cần seed database hàng giờ như AG on-prem.
  • Licensing: named replicas tính riêng vCore cost; HA replicas miễn phí (đã bao gồm trong tier).

Khi nào dùng Hyperscale vs SQL Server on-prem vs Azure SQL thường?

Use caseKhuyến nghị
OLTP < 100GB, RTO thấpAzure SQL (DTU/vCore)
OLTP + real-time reporting, > 1TBHyperscale
Cần 10+ read replicas, sub-second lagHyperscale
Regulatory: data phải on-premSQL Server + AG
Full Enterprise feature (SSIS, SSAS)SQL Server on-prem / Azure VM
Dev/test localDocker container

SQL Database on Microsoft Fabric

SQL Database trong Fabric là 1 database engine SaaS-native, dùng chung codebase với SQL Server 2025:
-- Tạo database trong Fabric (không cần provision server!)
CREATE DATABASE MyFabricDB;
-- Auto-provisioned, auto-scale, auto-backup

-- Dùng T-SQL y hệt SQL Server
CREATE TABLE products (id INT, name NVARCHAR(200), embedding VECTOR(1536));
INSERT INTO products VALUES (1, 'Widget', @embedding);
  • Zero server management — không cần setup instance, không patch, không backup config.
  • Tích hợp Fabric ecosystem: OneLake, Power BI, notebook, data pipeline.
  • Copilot tích hợp sẵn — natural language → T-SQL trong Fabric portal.
  • Phù hợp cho analytics project, data warehouse nhỏ, team muốn SQL mà không muốn quản trị server.

© 2026 .NET Fresher Guide. All rights reserved.

Về Trang Web

Hướng dẫn toàn diện để chuẩn bị phỏng vấn vị trí .NET Fresher với nội dung từ lý thuyết đến thực hành.