簡體   English   中英

C# 中的 SQL Server 更新語句

[英]SQL Server Update statement in C#

我有表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 

和 JSON 數組

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

如何使用 for 循環更新 SQL Server 表,如果 {"value": "type_1_1"} 等於表列名 type_1_1 然后將值設置為 1 或者如果值為 1 然后設置為 0?

這是我目前正在嘗試的:

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;
    }

假設我在評論中提到的內容是正確的(值的存在定義為 1,不存在定義為 0)我認為,在設置 1 之前,您需要將所有內容設置為 0,或者開始收集所有列所以 C# 可以計算出什么應該是 0..

像這樣的東西(安裝 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 });

我們首先命名表中的type_x_y=0列,並將其設置為type_x_y=0 然后對於 json 中存在的每個列名,我們將 SQL 的那部分更改為type_x_y=1並進行一些字符串替換

正則表達式是為了防止 json 供應商的 SQL 注入攻擊

您可以將整個 JSON 數組傳遞給 SQL,然后讓 SQL Server 對其進行分解。

  • 使用OPENJSON帶出單獨的行
  • 將其轉回單行,每列都有一個 1 或 0
  • 使用ISNULLNULLIF的組合來保持相同的值
    • 如果你想覆蓋所有列,那么你可以簡單地做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;

那么你的應用代碼就變得很簡單了

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