Dot-Net

是否有動態生成 sql 的標準方法?

  • May 30, 2019

我想問一下其他程序員如何生成動態 SQL 字元串以作為 SQLCommand 對象的 CommandText 執行。

我正在生成包含使用者生成的 WHERE 子句和 SELECT 欄位的參數化查詢。有時查詢很複雜,我需要對不同部分的建構方式進行大量控制。

目前,我正在使用許多循環和 switch 語句來生成必要的 SQL 程式碼片段並創建所需的 SQL 參數對象。這種方法很難遵循,它使維護成為一件真正的苦差事。

有沒有更清潔、更穩定的方法來做到這一點?

有什麼建議麼?

編輯:為我以前的文章添加細節:

  1. 由於要求,我無法真正模板化我的查詢。只是變化太大了。
  2. 我必須允許聚合函式,比如 Count()。這對 Group By/Having 條款有影響。它還會導致嵌套的 SELECT 語句。反過來,這會影響所使用的列名
  3. 一些聯繫人數據儲存在 XML 列中。使用者可以將這些數據連同其他關係列一起查詢。後果是 xmlcolumns 不能出現在 Group By 子句中$$ sql syntax $$.
  4. 我正在使用一種使用 Row_Number() SQL 函式的高效分頁技術。結果是我必須使用 Temp 表,然後在選擇我的子集之前獲取@@rowcount,以避免第二次查詢。

我將展示一些程式碼(恐怖!),以便你們了解我正在處理的內容。

sqlCmd.CommandText = "DECLARE @t Table(ContactId int, ROWRANK int" + declare
     + ")INSERT INTO @t(ContactId, ROWRANK" + insertFields + ")"//Insert as few cols a possible
     + "Select ContactID, ROW_NUMBER() OVER (ORDER BY " + sortExpression + " "
     + sortDirection + ") as ROWRANK" // generates a rowrank for each row
     + outerFields
     + " FROM ( SELECT c.id AS ContactID"
     + coreFields
     + from         // sometimes different tables are required 
     + where + ") T " // user input goes here.
     + groupBy+ " "
     + havingClause //can be empty
     + ";"
     + "select @@rowcount as rCount;" // return 2 recordsets, avoids second query
     + " SELECT " + fields + ",field1,field2" // join onto the other cols n the table
     +" FROM @t t INNER JOIN contacts c on t.ContactID = c.id" 
     +" WHERE ROWRANK BETWEEN " + ((pageIndex * pageSize) + 1) + " AND " 
     + ( (pageIndex + 1) * pageSize); // here I select the pages I want

在此範例中,我正在查詢 XML 數據。對於純關係數據,查詢要簡單得多。每個部分變數都是 StringBuilders。Where 子句的建構方式如下:

// Add Parameter to SQL Command
AddParamToSQLCmd(sqlCmd, "@p" + z.ToString(), SqlDbType.VarChar, 50, ParameterDirection.Input, qc.FieldValue);
// Create SQL code Fragment
where.AppendFormat(" {0} {1} {2} @p{3}", qc.BooleanOperator, qc.FieldName, qc.ComparisonOperator, z);

我需要在我最近的一個項目中這樣做。這是我用於生成 SQL 的方案:

  • 查詢的每個組件都由一個對象表示(在我的例子中,它是一個映射到數據庫中表的 Linq-to-Sql 實體)。所以我有以下類:Query、SelectColumn、Join、WhereCondition、Sort、GroupBy。這些類中的每一個都包含與查詢的該組件相關的所有詳細資訊。
  • 最後五個類都與一個 Query 對象相關。因此 Query 對象本身俱有每個類的集合。
  • 每個類都有一個方法,可以為它所代表的查詢部分生成 SQL。因此,創建整體查詢最終會呼叫 Query.GenerateQuery() 依次列舉所有子集合併呼叫它們各自的 GenerateQuery() 方法

它仍然有點複雜,但最終您知道查詢的每個單獨部分的 SQL 生成源自何處(而且我不認為有任何大的 switch 語句)。並且不要忘記使用 StringBuilder。

引用自:https://stackoverflow.com/questions/51827