是否有动态生成sql的标准方法?

nia*_*ith 12 .net sql

我想问一下其他程序员如何生成动态SQL字符串以作为SQLCommand对象的CommandText执行.

我正在生成包含用户生成的"WHERE"子句和SELECT字段的参数化查询.有时查询很复杂,我需要对如何构建不同部分进行大量控制.

目前,我使用许多循环和switch语句来生成必要的SQL代码片段并创建所需的SQL参数对象.这种方法很难遵循,它使维护成为一项真正的苦差事.

这样做有更清洁,更稳定的方法吗?

有什么建议??

编辑:要添加我以前的帖子的详细信息:

由于要求,我无法真正模拟我的查询.它只是变化太大了.

  1. 我必须允许聚合函数,如Count().这对Group By/Having条款有影响.它还会导致嵌套的SELECT语句.这反过来会影响使用的列名
  2. 某些联系人数据存储在XML列中.用户可以将这些数据AS WELL AS和其他关系列一起查询.后果是xmlcolumns不能出现在Group By子句[sql syntax]中.
  3. 我正在使用一种使用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
Run Code Online (Sandbox Code Playgroud)



在这个例子中.我会查询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);
Run Code Online (Sandbox Code Playgroud)

Yaa*_*lis 2

我最近的一个项目需要这样做。这是我用来生成 SQL 的方案:

  • 查询的每个组件都由一个对象表示(在我的例子中,它是映射到数据库中的表的 Linq-to-Sql 实体)。所以我有以下类:Query、SelectColumn、Join、WhereCondition、Sort、GroupBy。每个类都包含与查询的该组件相关的所有详细信息。
  • 最后五个类都与查询对象相关。因此 Query 对象本身具有每个类的集合。
  • 每个类都有一个方法,可以为其表示的查询部分生成 SQL。因此,创建整体查询最终会调用 Query.GenerateQuery() ,而后者又会枚举所有子集合并调用它们各自的GenerateQuery() 方法

它仍然有点复杂,但最终您知道查询的每个单独部分的 SQL 生成源自何处(而且我不认为有任何大的 switch 语句)。并且不要忘记使用 StringBuilder。