如何在参数化查询中创建可选参数

时间:2013-11-03 13:33:38

标签: c# sql c#-4.0 sqlcommand parameterized-query

在我的代码中,我使用简单的参数化查询 它有很多参数,有些可以是 NULL ,有些是null 抱怨FK
如何解决此问题以获得可选参数,但不使用存储过程 要清楚,我想在参数为null时避免尝试更新该字段。

conn.Open();

                string sql = @"UPDATE UserProfile
                               SET FirstName = @p_FirstName
                                  ,LastName = @p_LastName
                                  ,Gender = @p_Gender
                                  ,DateOfBirth = @p_DateOfBirth
                                  ,CityId = @p_CityId
                                  ,MartialStatusId = @p_MartialStatusId
                                  ,ProfileImageId = @p_ProfileImageId
                             WHERE UserId = @p_UserId";

                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {                    
                    cmd.Parameters.AddWithValue("@p_FirstName", userProfile.FirstName);
                    cmd.Parameters.AddWithValue("@p_LastName", userProfile.LastName);
                    cmd.Parameters.AddWithValue("@p_Gender", userProfile.Gender);
                    cmd.Parameters.AddWithValue("@p_DateOfBirth", userProfile.DateOfBirth);
                    cmd.Parameters.AddWithValue("@p_CityId", userProfile.CityId);
                    cmd.Parameters.AddWithValue("@p_MartialStatusId", userProfile.MartialStatusId);
                    cmd.Parameters.AddWithValue("@p_ProfileImageId", userProfile.ProfileImageId);
                    cmd.Parameters.AddWithValue("@p_UserId", userProfile.UserId);

                    cmd.ExecuteNonQuery();

                }

2 个答案:

答案 0 :(得分:2)

您可以构造SQL,以便在不需要时,这些可选参数永远不会出现在:

var sql = new StringBuilder();
sql.Append(@"UPDATE UserProfile
               SET "); 

if(addFirstName) // <-- some boolean condition here
  sql.Append("FirstName = @p_FirstName, ");

// ... etc...

sql.Append(" WHERE UserId = @p_UserId");

与实际参数相同 - 请勿添加您不想添加的内容。

答案 1 :(得分:1)

您可以按照以下方式更改UPDATE语句,以避免NULL - 将参数设置为NULL的字段:

UPDATE UserProfile
SET
    FirstName = CASE WHEN @p_FirstName_set THEN @p_FirstName ELSE FirstName END
,   LastName  = CASE WHEN @p_LastName_set  THEN @p_LastName  ELSE LastName END
--  ...and so on
WHERE UserId = @p_UserId

这会使参数数量增加一倍 - 对于每个可选参数@XYZ,如果使用@XYZ_set,则需要添加1参数设置为@XYZ,或者<{1}}时未使用0

@XYZ

您可以添加一个函数来封装此if (changeFirstName) { cmd.Parameters.AddWithValue("@p_FirstName", userProfile.FirstName); cmd.Parameters.AddWithValue("@p_FirstName_set", 1); } else { cmd.Parameters.AddWithValue("@p_FirstName", ""); cmd.Parameters.AddWithValue("@p_FirstName_set", 0); } // ... and so on 语句。

如果需要,此方法允许您将值设置为if,因为参数本身的值中不再包含有关是否设置相应参数的信息。

请注意,无论设置了多少字段,查询都将保持静态,因此每次设置不同的参数组时,RDBMS都可能避免构建新的查询计划。