带有可选参数的C#中的SQL String Builder查询

时间:2016-03-02 21:03:29

标签: c# sql string

我正在构建一个SQL更新语句,根据哪个复选框为每个要更新的字段选择。因为某些参数是可选的,我在语法上会遇到麻烦。例如,如果用户只是选择“位置”复选框,则该语句将完美执行,因为只更新了其中一列:

UPDATE [Group] SET Location = @p_Location WHERE GroupID = @p_GroupID

但是,如果用户选择多个列进行更新,那么我的语法有问题,因为我无法控制参数之后的逗号,因为它们可以按任意顺序

var sql = new StringBuilder();
sql.Append(@"UPDATE [Group] SET ");
if (updateModel.IsUseGroupNumberSelected)
{
    sql.Append("GroupNumber = @p_GroupNumber");
    cmd.Parameters.AddWithValue("@p_GroupNumber", updateModel.Group.GroupNumber);
}
if (updateModel.IsUseTerminationDateSelected)
{
    sql.Append("GroupNumber = @p_GroupNumber");
cmd.Parameters.AddWithValue("@p_TerminationDate", updateModel.Group.TerminationDate);
}
if (updateModel.IsUseLocationSelected)
{
    sql.Append("Location = @p_Location");
    cmd.Parameters.AddWithValue("@p_Location", updateModel.Group.Location);
}
sql.Append(" WHERE GroupID = @p_GroupID");
cmd.Parameters.AddWithValue("@p_GroupID", updateModel.Group.GroupID);

有没有人对如何打击这个有任何想法?我正在考虑循环遍历SQL字符串并在需要的地方添加额外的逗号,但它似乎不那么安全和混乱。我想我应该首先选择brillent stackoverflow的思想。谢谢你的帮助!

4 个答案:

答案 0 :(得分:1)

使用所有参数创建更新语句,然后使用COALESCE忽略未设置的参数。

UPDATE [Group] 
   SET Location = COALESCE(@p_Location, [Location]),
       GroupNumber = COALESCE("@_GroupNumber", [GroupNumber]),
   ... etc

如果需要动态过滤,也可以在WHERE子句中执行此操作。

答案 1 :(得分:1)

您可以等到最后添加查询的开头:

<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
  <title>jQueryForm</title>
</head>

<body ng-app="myApp" ng-controller="myCtrl">
  <div id="form">
    <div ng-repeat="data in dataSet">
      <input ng-click="calculate()" type="checkbox" ng-model="data.checked" />
      <label>Data:</label>
      <input ng-change="calculate()" type="number" ng-model="data.number" />
      <br/>
    </div>

    <span>{{result}}</span>

    <script>
      var app = angular.module('myApp', []);
      app.controller('myCtrl', function($scope) {
        $scope.dataSet = [{}, {}, {}, {}, {}];

        $scope.calculate = function() {
          $scope.result = 0;

          for (var i = 0; i < $scope.dataSet.length; i++) {
            if (angular.isNumber($scope.dataSet[i].number) && $scope.dataSet[i].checked)
              $scope.result += $scope.dataSet[i].number;
          }
        }
      });
    </script>
  </div>
  </div>
  </span>

</body>


</html>

答案 2 :(得分:1)

您需要添加一些布尔逻辑,以使其按您想要的方式工作。关键是当您不是第一个添加要更新的列时,只添加逗号。

       Bool first = true;
        var sql = new StringBuilder();
        sql.Append(@"UPDATE [Group] SET ");
           if (updateModel.IsUseGroupNumberSelected)
           {
               if (!first) sql.Append(", ");
               sql.Append("GroupNumber = @p_GroupNumber");
               cmd.Parameters.AddWithValue("@p_GroupNumber", updateModel.Group.GroupNumber);
               first = false;
            }
           if (updateModel.IsUseTerminationDateSelected)
           {
               if (!first) sql.Append(", ");
               sql.Append("TerminationDate = @p_TerminationDate");
               cmd.Parameters.AddWithValue("@p_TerminationDate", updateModel.Group.TerminationDate);
               first = false;
            }

           if (updateModel.IsUseLocationSelected)
           {
                if (!first) sql.Append(", ");
                sql.Append("Location = @p_Location");
                cmd.Parameters.AddWithValue("@p_Location", updateModel.Group.Location);
                first = false;
            }

          sql.Append(" WHERE GroupID = @p_GroupID");
          cmd.Parameters.AddWithValue("@p_GroupID", updateModel.Group.GroupID);

答案 3 :(得分:0)

跟踪List<string>中的其他查询。将它们全部放入列表后,您可以用逗号连接它们:

https://dotnetfiddle.net/LtIhW8

   List<string> whereClauses = new List<string>();

    for(int i = 0; i < 10; i++){
        whereClauses.Add("where Clause " + i.ToString())        ;
    }


    sql.Append(string.Join(",", whereClauses));