多條件查詢常見寫法:C# 端用 StringBuilder 依條件組裝 WHERE 子句,再拼接 SELECT。缺點顯而易見:程式碼冗長、易生 SQL 注入、參數化困難、計畫快取利用率低、除錯困難。
// 範例一:傳統拼湊 (略)
利用 ('@param = '' OR Col = @param') 模式,參數為空時條件恆真自動略過,非空時套用篩選。SQL Server 查詢優化器能識別此模式並產生參數化計畫:
DECLARE @Order VARCHAR(20) = '', @Produce VARCHAR(20) = '711',
@StartDate DATETIME = NULL, @EndDate DATETIME = NULL;
SELECT * FROM Sales.SalesOrderDetail
WHERE (@Order = '' OR SalesOrderID = @Order)
AND (@Produce = '' OR ProductID = @Produce)
AND (@StartDate IS NULL OR ModifiedDate > @StartDate)
AND (@EndDate IS NULL OR ModifiedDate < @EndDate);
C# 呼叫端只需傳入參數,無需組裝 SQL 字串:
string sql = @"
SELECT * FROM Sales.SalesOrderDetail
WHERE (@Order = '' OR SalesOrderID = @Order)
AND (@Produce = '' OR ProductID = @Produce)
AND (@StartDate IS NULL OR ModifiedDate > @StartDate)
AND (@EndDate IS NULL OR ModifiedDate < @EndDate)";
using (var cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.AddWithValue("@Order", txtOrder.Text);
cmd.Parameters.AddWithValue("@Produce", txtProduce.Text);
cmd.Parameters.AddWithValue("@StartDate", string.IsNullOrEmpty(txtStart.Text) ? (object)DBNull.Value : txtStart.Text);
cmd.Parameters.AddWithValue("@EndDate", string.IsNullOrEmpty(txtEnd.Text) ? (object)DBNull.Value : txtEnd.Text);
// ExecuteReader...
}
ASP.NET WebForms 可直接在標記中定義參數化查詢,配合 ConvertEmptyStringToNull="true" 將空字串轉為 NULL:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
CancelSelectOnNullParameter="false"
SelectCommand="
SELECT * FROM Sales.SalesOrderDetail
WHERE (@Order IS NULL OR SalesOrderID = @Order)
AND (@Produce IS NULL OR ProductID = @Produce)
AND (@StartDate IS NULL OR ModifiedDate > @StartDate)
AND (@EndDate IS NULL OR ModifiedDate < @EndDate)">
<SelectParameters>
<asp:ControlParameter ControlID="txtOrder" Name="Order"
ConvertEmptyStringToNull="true" />
<asp:ControlParameter ControlID="txtProduce" Name="Produce"
ConvertEmptyStringToNull="true" />
<asp:ControlParameter ControlID="txtStartDate" Name="StartDate" Type="DateTime"
ConvertEmptyStringToNull="true" />
<asp:ControlParameter ControlID="txtEndDate" Name="EndDate" Type="DateTime"
ConvertEmptyStringToNull="true" />
</SelectParameters>
</asp:SqlDataSource>
CREATE PROCEDURE dbo.SearchSalesOrderDetail
@Order VARCHAR(20) = NULL,
@Produce VARCHAR(20) = NULL,
@StartDate DATETIME = NULL,
@EndDate DATETIME = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM Sales.SalesOrderDetail
WHERE (@Order IS NULL OR SalesOrderID = @Order)
AND (@Produce IS NULL OR ProductID = @Produce)
AND (@StartDate IS NULL OR ModifiedDate > @StartDate)
AND (@EndDate IS NULL OR ModifiedDate < @EndDate);
END
優點:邏輯集中資料庫端、參數強型別、計畫快取穩定、權限可控、易於效能調校 (OPTION RECOMPILE 等)。
作者實測指出此模式在大資料量下效能較差,主要原因:
改善方向:
OPTION (RECOMPILE),每次編譯針對當前參數值優化 (適用中低頻查詢)。FORCESEEK 或覆蓋索引。OFFSET/FETCH (SQL 2012+) 避免全量傳回。「參數化短路邏輯」是解決動態條件查詢的標準模式,兼顧安全性、可維護性與計畫重用。針對效能敏感場景,可進階採用動態 SQL、重編譯提示或索引優化。核心原則:拒絕字串拼湊,擁抱參數化,邏輯下推資料庫層。