简体   繁体   English

C# 中的 SQL Server 更新语句

[英]SQL Server Update statement in C#

I have table SelectedType with columns type_1 ... type_2_3 of datatype bit :我有表SelectedType与列type_1 ... type_2_3的数据类型bit

P_ID   type_1 type_1_1 type_1_2 type_1_3 type_2 type_2_1 type_2_2 type_2_3

 1        0      1         1       0       0       1        0        1       
 2        1      0         1       0       0       1        0        0
 3        1      0         1       0       0       1        0        0
 4        0      0         0       1       1       1        1        1
...and so on 

And JSON Array和 JSON 数组

[
  {"value": "type_1_1"}, {"value": "type_2_1"}, {"value": "type_2_3"}
]

How can I update the SQL Server table using for loop and if {"value": "type_1_1"} equals to table Column name type_1_1 then set value to 1 or if value is 1 then set to 0?如何使用 for 循环更新 SQL Server 表,如果 {"value": "type_1_1"} 等于表列名 type_1_1 然后将值设置为 1 或者如果值为 1 然后设置为 0?

Here is what I'm trying so far:这是我目前正在尝试的:

public bool UpdatePredictSubGoalType(int id, string _selectedTypes)
{
        string a = "[]";
        string item = _selectedTypes;

        if (!item.Contains('[') && !item.Contains(']'))
        {
            string c = a.Insert(1, _selectedTypes);
            item = c;
        }

        bool res = false;

        JArray Ja = JArray.Parse(item);
        string sqlstr = "";

        try
        {
            using (conn = new SqlConnection(CommonDA.GetConnectionString()))
            {
                conn.Open();
                trans = conn.BeginTransaction();

                try
                {
                    for (int i = 0; i <= Ja.Count - 1; i++)
                    {
                        string x = Ja[i]["value"].ToString();

                        SqlCommand cmd = conn.CreateCommand();
                        sqlstr = @"Update SelectedType set "+ x +" = (0 or 1, i don't know how to do) where id = @id AND " + x + " = @" + x;
                        cmd.CommandText = sqlstr;
                        cmd.Transaction = trans;
                        cmd.Parameters.AddWithValue("@id", id);                            

                        cmd.ExecuteNonQuery();

                        trans.Commit();
                        conn.Close();

                        res = true;
                    }
                }
                catch (Exception Err)
                {
                    trans.Rollback();
                    CommonLB.SystemError(Err.Message);
                    CommonLB.SystemError("Data", "SQL:" + sqlstr);
                }
            }
        }
        catch (Exception Err)
        {
            throw new ApplicationException(Err.Message, Err);
        }

        return res;
    }

Assuming what I mentioned in the comments is correct (that presence of a value defines 1, absence defines 0) I think, before you set your 1s you'll need to set everything to 0, or get into having a collection of all your columns so C# can work out what should be 0..假设我在评论中提到的内容是正确的(值的存在定义为 1,不存在定义为 0)我认为,在设置 1 之前,您需要将所有内容设置为 0,或者开始收集所有列所以 C# 可以计算出什么应该是 0..

Something like this (install Dapper to make ExecuteAsync on a connection "a thing", or expand it to "the long way"):像这样的东西(安装 Dapper 以使 ExecuteAsync 在连接上成为“一件事”,或将其扩展为“长路”):

    using var conn = new SqlConnection(CommonDA.GetConnectionString()));

    var sql = "UPDATE t SET type_1=0, type_1_1=0, type_1_2=0, type_1_3=0, type_2=0, type_2_1=0, type_2_2=0, type_2_3=0 WHERE ID = @id";

    for (int i = 0; i <= Ja.Count - 1; i++){
      var c = Ja[i]["value"].ToString();

      if(!Regex.IsMatch(c, @"^type_\d(_\d)?$")
        continue;
      sql = sql.Replace($"{c}=0", $"{c}=1");
    }

    await conn.ExecuteAsync(sql, new { id });

We start off by naming very column in the table, and setting it type_x_y=0 .我们首先命名表中的type_x_y=0列,并将其设置为type_x_y=0 Then for every column name present in the json, we change that part of the SQL to type_x_y=1 with a bit of string replacement然后对于 json 中存在的每个列名,我们将 SQL 的那部分更改为type_x_y=1并进行一些字符串替换

The Regex is in there to guard against SQL injection attacking by the json supplier正则表达式是为了防止 json 供应商的 SQL 注入攻击

You can just pass the whole JSON array into SQL, and have SQL Server break it down.您可以将整个 JSON 数组传递给 SQL,然后让 SQL Server 对其进行分解。

  • Use OPENJSON to bring out separate rows使用OPENJSON带出单独的行
  • Pivot it back into a single row, each column having a 1 or 0将其转回单行,每列都有一个 1 或 0
  • Use a combination of ISNULL and NULLIF to keep the same value使用ISNULLNULLIF的组合来保持相同的值
    • If you want to overwrite all columns then you can simply do type_1 = j.type_1如果你想覆盖所有列,那么你可以简单地做type_1 = j.type_1
UPDATE st
SET
  type_1   = IIF(j.type_1   = 1, 1, st.type_1  ),
  type_1_1 = IIF(j.type_1_1 = 1, 1, st.type_1_1),
  type_1_2 = IIF(j.type_1_2 = 1, 1, st.type_1_2),
  type_1_3 = IIF(j.type_1_3 = 1, 1, st.type_1_3),
  type_2   = IIF(j.type_2   = 1, 1, st.type_2  ),
  type_2_1 = IIF(j.type_2_1 = 1, 1, st.type_2_1),
  type_2_2 = IIF(j.type_2_2 = 1, 1, st.type_2_2),
  type_2_3 = IIF(j.type_2_3 = 1, 1, st.type_2_3)
FROM SelectedType st
CROSS APPLY (
    SELECT *
    FROM OPENJSON(@json)
      WITH (value sysname) j
    PIVOT (COUNT(value) FOR value IN
        (type_1, type_1_1, type_1_2, type_1_3, type_2, type_2_1, type_2_2, type_2_3)
    ) pvt
) j
WHERE st.P_ID = @id;

Then your application code becomes very simple那么你的应用代码就变得很简单了

public bool UpdatePredictSubGoalType(int id, string _selectedTypes)
{
    if (!item.StartsWith('['))
        _selectedTypes = '[' + _selectedTypes;
    if (!item.EndsWith(']'))
        _selectedTypes = _selectedTypes + ']';

    try
    {
        const string query = @"
THE ABOVE QUERY
";
        using (var conn = new SqlConnection(CommonDA.GetConnectionString()))
        using (var cmd = new SqlCommand(query, conn))
        {
            cmd.Parameters.Add("@id", SqlDbType.Int).Value = id;                            
            cmd.Parameters.Add("@json", SqlDbType.NVarChar, -1).Value = _selectedTypes;
            conn.Open();
            cmd.ExecuteNonQuery();
        }
    }
    catch (Exception Err)
    {
        throw new ApplicationException(Err.Message, Err);
    }

    return true;
}

更改您的 sql 字符串:

str = $"Update SelectedType set [{x}] = CASE WHEN [{x}] = 0 then 1 else 0 end where id = {@id}";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM