[英]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
帶出單獨的行ISNULL
和NULLIF
的組合來保持相同的值
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.